DevMedia
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login

Código no Banco vs Código na Aplicação - Dez variáveis que influenciam na tomada de decisão.

Separação de Interesses, do termo em inglês Separation of Concern (SoC), esse é um conceito amplamente usado no desenvolvimento de projetos complexos e com requisitos altos de escalabilidade. Dez variáveis que influenciam na decisão de projeto.

[fechar]

Você não gostou da qualidade deste conteúdo?

(opcional) Você poderia comentar o que não lhe agradou?

Confirmo meu voto negativo

Introdução

Separação de Interesses, do termo em inglês Separation of Concern (SoC), esse é um conceito amplamente usado no desenvolvimento de projetos complexos e com requisitos altos de escalabilidade, portabilidade e de fácil manutenção. O desenvolvimento de software sob o paradigma orientado a objetos procura elicitar principios que facilitam o uso de SoC e também conduzam para um melhor reaproveitamento e reutilização do código para novas gerações ou versões do sistema.

Segundo Martin Fowler, obter alta granularidade não é uma tarefa fácil, a granularidade é um tipo de métrica empregada em orientação a objetos e outros tipos de paradigmas que tem como característica medir o grau que uma parte do sistema deve ser fatorado, de forma a se criar um componente que possa ser reaproveitado. Existem dois tipos de granulariade conhecidas, granularidade grossa e granularidade fina, a primeira relaciona um alto grau de acoplamento e um sistema pouco coeso e a segunda mede o inverso, um sistema fracamente acoplado e fortemente coeso. Em geral, é desejável que se tenha níveis de granularidade coerentes com o projeto desenvolvido. Para se alcançar esses níveis deve-se realizar um "trade-off" entre os princípios de orientação a objetos e as necessidades do projeto, algumas variáveis que devem ser identificados e controladas como pontos de prova são: (1) desenvolvedores com conhecimento na linguagem; (2) flexibilidade do sistema; (3) portabilidade do sistema; (4) desempenho; (5) tempo de desenvolvimento; (6) capacidade de testar o sitema e efetuar a depuração; (7) garantia de manutenção; (8) compreensão do código; (9) duplicidade; (10) encapsulamento (Fowler; Larman; Booch; Runbaum; Beck).

Esses dez princípios enumerados anteriormente, estão diretamente associadas com dois fatores constantes ao desenvolvimento de software – Banco de Dados (BD) e Linguagem de Programação (LP). Essas duas constantes levam a decisões de projetos importantes, um deles é se a codificação da regra de negócio do sistema deve estar localizada no banco de dados de dados, na forma de Stored Procedures (SP) ou codificada na aplicação.

Em seu artigo "Domain Logic and SQL" (http://martinfowler.com/articles/dblogic.html), Martin Fowler, explora esse tópico para um exemplo de Clientes que possuem muitos pedidos e para cada pedido existe um Item cadastrado, cada item pode sofrer um desconto agregado no pedido como um todo. A listagem 1 é um exemplo de um método em Java recuperar pedidos a partir do mês atual.

class LogicaPedido{
      Collection result;
      //outras variaveis de instancias DAOCliente DAOPedido
      public Collection pedidoMesAtual(){
      int clienteID = daocliente.busca_cliente("bia");
      for(Pedido dataPedido: daopedido.busca_pedido(clienteID))
         if( dataPedido.pedidoAtual() )
            result.add(dataPedido);
      return result;
     }
}

class DAOCliente{
      public int busca_cliente(String nome) throws SQLException{
             String sql="SELECT * FROM cliente WHERE nome=?";
             int id;
             //Rotina para usar o PreparedStatement
             return id;
     }
}

class DAOPedido{
      public Collection busca_pedido(int id) throws SQLException{
      String sql="SELECT * FROM pedido WHERE id=?";
      Collection pedidos;
      //Rotina para usar o PreparedStatement
      return pedidos;
     }
}

Listagem 1: Código em Java para recuperar o pedido atual (adaptado de Fowler).

A listagem anterior mostra apenas o DAOCliente, o objeto DAOPedido foi omitido mas segue o mesmo princípio. Na listagem é possível observar claramente a separação de interesses entre a aplicação e o código SQL do banco de dados. A separação de interesses foi obtida com auxílio do padrão de projeto DAO, nesse caso o padrão de projeto consegue separar com alta granularidade os componentes do sistema responsáveis pela camada de persistência, centralizando assim a responsabilidade da lógica. Um modelo ideal para esse exemplo, seria a integração dos padrões DAO e MVC.

Em contrapartida, uma segunda abordagem é apresentada na listagem 2:
 
class LogicaPedido{
      Collection result;
      //outras variaveis de instancias DAOCliente DAOPedido
      public Collection pedidoMesAtual() throws SQLException{
              int clienteID;
              String nome;
              PreparedStatemente st;
              Collection result;
              String sql ="SELECT DISTINCT
              MONTH(o.data) AS mes
              FROM itens_pedido ip INNER JOIN pedido p ON ip.pedidoID = p.pedidoID
              INNER JOIN cliente c ON p.clienteID = c.clienteID WHERE (c.nome = ?) AND
             (ip.produto = 'IPhone') GROUP BY ip.pedidoID, ip.data, c.nome HAVING
              (SUM(ip.preco) > 5000)";
              //cria PreparedStatement
              ...
              ResultSet rs = st.executeQuery(sql);
              while(rs.next()){
                   result.add(rs.getDate("mes").toString());
              }
              return result;
      }
}

                Listagem 2: Código em Java para recuperar o pedido atual com SQL (adaptado de Fowler).

A listagem 2, é um exemplo de código em Java que usa diretamente uma associação com a linguagem SQL. Embora o exemplo SQL não seja complexo, essa listagem é um exemplo claro que a medida em que a aplicação vai necessitando de novos recursos e consultas, o código SQL pode se tornar cada vez mais complicado e de difícil manutenção. Um outro exemplo é mostrado abaixo, na Listagem 3, onde é usado para retornar um Pedido uma Stored Procedure (SP) em Postgres/plpgsql. Essa SP usa um cursor para retornar um conjunto de itens, esse cursor é aberto com um comando SQL equivalente ao da listagem 2, observe no entanto as diferenças entre as diferenças entre as formas de declaração entre as listagens anteriores.


CREATE OR REPLACE FUNCTION fn_retorna_pedido(integer) RETURNS TEXT AS
$$
DECLARE
      ppedido ALIAS FOR $1;
      cursor REFCURSOR;
      col_data exemplo.itens_pedido.data%TYPE;
      result TEXT;
BEGIN
      result:='''';
      OPEN cursor FOR SELECT DISTINCT MONTH(ip.data) AS mes
              FROM itens_pedido ip INNER JOIN pedido p ON ip.pedidoID = p.pedidoID INNER JOIN
      cliente c ON p.clienteID = c.clienteID WHERE (c.nome = ppedido)
      AND (ip.produto =  ''IPhone'') GROUP BY ip.pedidoID, ip.data, c.nome
      HAVING (SUM(ip.preco) > 5000);
     
       LOOP
           FETCH cursor
           INTO col_data
           EXIT WHEN NOT FOUND;
           result:=result||col_data || '' \n ''; /* || é uma concatenacao */
       END LOOP;

       RETURN result;
END;
$$

LANGUAGE ''plpgsql'' VOLATILE

Listagem 3: Código de uma Stored Procedure em Postgres/plpgsql.


Como pode-se observar, da primeira listagem até a última (Listagem de 1 a 3), que o nível de abstração e semântica vai do maior para um menor grau de abstração. A última listagem não apresenta, um nível desejádo de SoC e também viola condições e conceitos importantes de orientação a objetos como encapsulamento e reutilização de código. Pode-se observar que a última listagem apresenta um alto nível de acoplamento e baixa coesão, pois a função fn_retorna_pedido() não pode ser um componente e "plugada" facilmente em outras partes do sistema (observe os métodos da listagem 1).

Dessa forma, como BD e LP são constantes deve-mos então observar as variáveis apresentadas no início deste artigo.


Desenvolvedores com conhecimento na Linguagem
A Figura 1 ilustra dez Linguagens de Programação (LP''s) em função da porcentagem/popularidade dos principais motores de buscas da Internet.


Comparativo


Figura 1: Dez linguagens de programação (adaptado TIOBE - http://www.tiobe.com/).


Como pode-se observar, as linguagens de referência no índice TIOBE (mes de referência junho de 2010), com aproveitamento acima de 50% são as linguagens C/C++ e Java. É conveniente notar, que segundo o índice TIOBE essas linguagens são as linguagens mais populares a patir dos principais motores de buscas atuais. Nota-se uma mínima popularidade em relação a família de linguagens PL/SQL (3,94%) contra (90,17%) da linguagem Java.

Essa característica tem um impácto direto na quantidade de desenvolvedores que tem conhecimento sobre linguagem de banco de dados (SP), isso pode em certo sentido prejudicar o bom desenvolvimento do sistema caso o sistema seja desenvovido com prazos críticos e com pessoal não treinado.

Flexibilidade do sistema, Portabilidade e Desempenho

Linguagem de Programação como PL/SQL são linguagens que estão diretamente ligadas a banco de dados como Oracle, mySQL, Postgres, SQL Server, Informix, Sybase, DB2 entre outros. Segundo Martin Fowler, existe uma dependência direta entre um sistema de banco de banco de dados e a capacidade do sistema se tornar mais flexível. O código totalmente implementado no banco de dados, caracteriza por outro lado um alto desempenho se comparado com as chamadas preparadas em Java. O desenpenho do banco de dados se comparado com rotinas alocadas no pool de conexão da linguagem Java e servers containers como o Apache Tomcat e Glassfish podem executar cerca de vinte vezes mais rápidas.

Esse resultado, em alguns casos, é tomado como o primeiro na decisão de projeto e arquitetura de um sistema, no entato tal prática deve ser claramente analisada. Como comparação, considere uma implementação em linguagem C para uma tarefa de troca de valores, esse tipo de operação é muito comum para algoritmos de ordenação como o Bubble Sort.

A Listagem 4, abaixo mostra um exemplo de uma chamada em Assembly (AT&T) para realizar uma operação de troca.

void troca_lm(int a, int b){
      int aTemp,bTemp;

      asm ("movl %2, %%eax;"
           "movl %3, %%ebx;"
           "movl %%eax, %%edx;"
           "movl %%ebx, %%eax;"
           "movl %%edx, %%ebx;"
           "movl %%eax, %0;"
           "movl %%ebx, %1;"
          :"=r"(aTemp),"=r"(bTemp) /* output */
          :"r"(a),"r"(b) /* input */
          :"%eax", "%ebx", "%edx" /* clobbered register */
         );

}

A Figura 2 ilustra o tempo de troca em função do tempo.

Linguagem C vs LM


Figura 2: Número de troca em função do tempo para código em C e AT&T.

Como era de se espera, observa-se uma acentuada melhora da linguagem de montagem sobre a linguagem C. Contudo, assim como linguagens de consultas como PL/SQL e Stored Procedures (SP), o programador deve conhecer em detalhes a linguagem a reconhecer que também não são todos os pontos ou partes do sistema que devem ser implementados no banco de dados. Para esse caso simples de uma troca, o problema em C torna-se trivial, mas para outros tipos de rotinas se torna praticamente inaceitável o uso de linguagem de montagem nos dias atuais.

A linguagem C com o uso da inner function – asm(), permite facilmente a integração de código de máquina em um programa estruturado. Pode-se, constatar também que o desenvolvimento em linguagem C em ambientes Linux é totalmente facilitado pela adoção de técnicas de depuração como o uso da ferramenta GDB. Uma aspecto contraditório quanto ao uso de Stored Procedures em banco de dados é o uso de uma ferramenta de depuração e teste. Atualmente é escasso o número de ferramentas que facilitam a depuração e o teste, a ferramenta dbUnit é uma extensão do JUnit que permite realizar teste de unidade em banco de dados, mas que não fornece nenhuma garantia estrutural ou de cobertura.

Outro aspecto ainda não muito bem definido é o uso de Stored Procedures com o desenvolvimento Ágil, em eXtreme Programming (XP) procura-se usar o desenvolvimento focado em TDD (Test-Driven Development), contudo ainda não é muito claro a integração e a real vantagem de SP com a Agilidade.



Para finalizar a tabela abaixo ilustra os prós e contras quanto ao uso de linguagem PL/SQL/SP.

Variáveis
Prós
Contra
Desenvolvedorescom conhecimento na linguagem

-
Portabilidade do sistema

-
Tempo de desenvolvimento

-
Desempenho
+

Capacidade de testar o sitema e efetuar a depuração

-
Garantia de manutenção

-
Compreensão do código
+

Duplicidade

-
Encapsulamento

-
Flexibilidade do sistema e Reuso

-

Tabela 1: Tabela comparativa entre prós e contras.

Conclusão

Como pode-se constatar o artigo apresenta uma visão geral sobre metricas em OO e também discute algumas das boas práticas de programação. É importante observar que o presente artigo discutiu de forma abrangente o emprego de SP no banco de dados versus a sua respectiva implicações que isso pode provocar. O artigo também apresente 10-variáveis que são fortes candidatas na tomada de decisão de projetos complexos. Vale observar que um aspecto não identificado no artigo é o caráter segurança, mas que será abordado em futuras pesquisas.


Referências

dbUnit - http://www.dbunit.org/
Martin Fowler - http://martinfowler.com/articles/dblogic.html
TIOBE - http://www.tiobe.com/
Design Patterns - http://sourcemaking.com/design_patterns





















Graduado em Ciência da Computação pela Universidade Presbiteriana Mackenzie. Mestre em Engenharia Elétrica pela Universidade Presbiteriana Mackenzie. Doutorando da Universidade Federal de São Carlos (UFSCar) - aceiro@gmail.com

O que você achou deste post?
Conhece a assinatura MVP?
Serviços

Mais posts