• Nenhum resultado encontrado

aplicáveis, mas cuidado para não cair na armadilha de pensar que precisamos de uma ferramenta especial para tudo. É importante lembrar que Ruby é como plasticina! Vamos mantê-lo assim.” - Jamis Buck

7.4.4 Don’t Repeat Yourself - DRY

DRY é um principio de desenvolvimento que foca-se essencialmente na redução da dupli- cação de código. A filosofia deste principio enfatiza que a informação deve ser duplicada o menos possível, pois a duplicação aumenta a dificuldade de mudança, diminui a cla- reza e leva a que sejam criadas oportunidades de inconsistência. A escrita de código que respeite este principio pode ser feita através de componentes reutilizáveis, permitindo ao programador de software evitar as operações de "copia e cola". Tanto em Struts2 como Rails, este é um principio fortemente encorajado pelas regras de implementação de ambos os Frameworks. Por este ser um principio transversal a todo o tipo de desenvolvimento de aplicações informáticas, não serão abordados individualmente.

Em ambos os Frameworks é possível a reutilização de código nos diversos componentes M-V-C. Os Frameworks apresentam mecanismos como é os caso dos templates de resultado parciais que são definidos num só lugar e incluídos em diversas outros templates - Dry View e a utilização de Interceptors em Struts2 e do ApplicationController em Rails permite que sejam efetuadas operações de verificação em todas as Actions (em Struts2) e Controllers (em Rails) - Dry Controller. Para além destes mecanismos em ambas as linguagens dos Frameworks é possível conceber funções e classes genéricas que permitam uma reutilização sucessiva do código. Desta forma o princípio DRY faz com que seja mais fácil dar manutenção a grandes sistemas de software.

7.5 e c o s s i s t e m a d o f r a m e w o r k

7.5.1 Bibliotecas

Atualmente no setor do desenvolvimento de software, a produtividade é um fator que deixa de ser refletido apenas pela quantidade de código que é implementado nas equipas de desenvolvimento, passando também a contemplar a capacidade de incorporar funciona- lidades feitas por terceiros. Por isso é cada vez mais frequente, que os Frameworks emer- gentes disponibilizem para além da sua implementação standard um conjunto de plugins facilmente personalizáveis, que permitem a extensão das aplicações através da incorporação de novas funcionalidades.

64 Capítulo 7. resultados

Em Struts2 (Java) estes plugins têm o nome de JARs. Estes ficheiros são pacotes de classes e de configurações que podem estender, alterar ou adicionar funcionalidades extras ao próprio Framework. A instalação de um JAR é feita através da colocação do ficheiro num diretório específico da aplicação. É importante denotar que existe sempre a necessidade de verificar a existência de dependências em relação ao outros JARs, o que terá que ser feito manualmente caso existam. Apesar disto existe forma de solucionar este inconveniente através do uso de uma ferramenta de gestão de dependências chamado Maven. Maven dispõe de um ficheiro chamado pom.xml, onde apenas é necessário definir a referência ao plugin desejado, sendo que serão automaticamente descarregadas todas as dependências a ele inerentes. No excerto7.9é apresentado um exemplo da definição de uma dependência.

<dependency >

<groupId > org . apache . struts </ groupId >

<artifactId > struts2 - convention - plugin </ artifactId > <version >2.3.30 </ version >

</ dependency >

Código 7.9: Definição de dependências utilizando Maven

No entanto isto requer que no início da configuração inicial invés de ser criado um projeto Java Web, seja criado um projeto do tipo Maven, ou então terá que ser efetuada uma migração para o novo projeto.

Rails

Em Rails (Ruby) estes plugins são disponibilizados na forma de GEMs. No entanto, ao contrário do que acontece em Java, Ruby possui por definição um sistema de gestão de pacotes chamado RubyGems que facilita a criação, a partilha e a instalação de plugins, assim como a garantia de instalação automática das suas dependências. Desta forma Rails apenas possui na sua estrutura um ficheiro de definição de GEMs chamado Gemfile (que pode ser visto na figura15). No excerto7.10 abaixo é apresentado um exemplo de definição de uma

GEM.

gem 'devise ' , '~> 3.2.4 '

Código 7.10: Definição de dependências utilizando RubyGems

7.5.2 Internacionalização - I18n

Internacionalização (I18n) refere-se à capacidade de uma aplicação alternar entre idiomas de uma forma fácil, adaptando a aplicação a uma determinada região. Esta funcionalidade tem um caráter cada vez mais importante, pois é utilizada para que as aplicações possam satisfazer um público cada vez maior, acompanhando assim a globalização. Através deste

7.5. Ecossistema do framework 65

recurso é possível alcançar um novo nível de utilidade, simplificando o desenvolvimento de aplicações multilingue.

Tanto Struts2 como Rails disponibilizam este mecanismo internacionalização de formas muito similares. Cada Framework define uma localização para criação de arquivos de configuração que devem respeitar uma nomenclatura específica relativamente ao nome do arquivo. Cada arquivo contém as propriedades definidas como pares chave-valor. Na View são utilizadas Tags específicas que permitem invocar a tradução dos elementos para serem apresentados no idioma pretendido.

7.5.3 Asynchronous JavaScript and XML - AJAX

AJAX não é apenas um tecnologia, é um conjunto de várias tecnologias. AJAX incorpora a capacidade de:

• Alterar estilos (CSS);

• Apresentação dinâmica de conteúdo através da Manipulação do DOM1 ; • Manipulação e troca de informações através de XML ou JSON;

• Obtenção de dados através de pedidos HTTP;

• Utilização de JavaScript ou JQuery, como linguagem de ligação entre componentes. AJAX permite que sejam obtidos dados para atualizar uma determinada página, sem ter de efetuar o recarregamento total dos conteúdos da página, ao contrário do que acontece nas arquiteturas convencionais em que a cada pedido são descarregados todos os recursos. AJAX foi utilizado nas duas implementações de SeTaRe em algumas das funcionalidades. Um exemplo disso que pode ser apresentado é o da figura8, em que o processo de procura

encadeado, que requer a introdução e seleção de vários dados, nomeadamente a escolha de um país, de uma cidade desse país, e de uma agência disponível nessa mesma cidade. Desta forma quando é selecionado determinado país, é efetuado a uma Action um pedido de consulta das cidades do país selecionado, que retorna como resposta uma lista. Essa lista é depois carregada e apresentada como lista de opções de seleção ao utilizador, tornando assim a página mais interativa, sem o habitual recarregamento total da página.

Struts2

No caso específico de SeTaRe, o objetivo do pedido é apenas obter como resultado uma lista (cf. Map<id,nome>) das cidades. Por essa razão a melhor abordagem foi enviar como resposta um objeto do tipo JSON. Struts2 dispõe de um plugin chamado struts2-json-plugin, que permite fazer o serialize do atributo da Action class que contem os métodos de leitura

66 Capítulo 7. resultados

e de escrita, num objeto do tipo JSON. Por fim, apenas é necessário que se defina o tipo de resultado de resposta da Action como JSON, o que pode ser feito a partir de uma Java Annotation como se apresenta no excerto7.11.

@Result ( type = " json ")

Código 7.11: Definição de formato de resposta em Struts2 Rails

Em Rails a implementação de pedidos AJAX é ainda mais simplificada do que em Struts2, uma vez que não é necessária a inclusão de nenhum plugin adicional. Rails implementa um serviço inteligente que interpreta o cabeçalho do pedido HTTP submetido pelo cliente, e de- termina automaticamente qual o formato de resposta que necessita. Desta forma tal como é apresentado no excerto7.12, podemos definir vários formatos de resposta, que Rails irá

compreender se um cliente pretende uma página HTML, um objeto JSON ou até mesmo uma lista de cidades em formato XML.

def cities

@cities = Country . find_by ( city : city [: id ]) respond_to do | format |

format . html { redirect_to ( cities_list_url ) } format . json { render : json => @cities }

format . xml { render xml : @cities . to_xml ( include : @cities ) } end

end

Código 7.12: Tipos de formatos de resposta em Rails

7.5.4 Scaffolding

Scaffolding é uma forma rápida, fácil e direta de gerar partes das aplicações. Alguns Fra- meworks disponibilizam esta funcionalidade de gerar código automaticamente apenas atra- vés do executar de um comando. Struts2 não dispõe desta funcionalidade na sua distribui- ção standard nem de plugins que permitam alcançar o efeito. Pelo contrário, Rails dispõe da funcionalidade por definição. Esta funcionalidade é definida pela execução do genera- tor apresentado no excerto7.13, que permite que sejam criados todos os componentes que

implementam o modelo MVC.

$ rails generate scaffold car

7.5. Ecossistema do framework 67

Embora esta não seja considerada um funcionalidade crucial, tem o seu valor quando estamos perante aplicações que implementam um elevado número de operações CRUD (Create, Read, Update, Delete), pois Scaffolding permite gerar o Controller, Model e todas as páginas (Views) associadas a cada operação. Desta forma pode considerar-se que no âmbito dos princípios ágeis pelos quais Rails se rege, esta poderá ser uma boa abordagem para facilitar o desenvolvimento de um protótipo inicial ou até para provar um determinado conceito sem um gasto elevado de tempo.

7.5.5 Segurança

Em geral os Frameworks Web oferecem um conjunto de funcionalidades de segurança que protegem as aplicações contra os mais diversos tipos de ataques. Neste tópico serão abor- dados os mais conhecidos problemas de segurança: SQLinjection, Cross-Site Scripting (XSS) e a Gestão de Sessões.

Rails

• SQL Injection

Em Rails a proteção contra este tipo de ataques é tratada pelo componente Active Record. Este módulo fornece mecanismos que funcionam como interfaces com a base de dados chamados de sanitization helpers e query builders que moderam assim todas as operações críticas que possam ser efetuadas na base de dados. Este mecanismos utilizam uma abordagem de lista negra de expressões, que verificam as expressões e descartam os caracteres SQL especiais [24]. No desenvolvimento em Rails, raramente é necessário escrever queries SQL, sendo geradas e executadas automaticamente. Por exemplo para guardar um alteração na base de dados, o Active Record dispõe do método save, que quando utilizado gera automaticamente a expressão SQL para fazer o INSERT ou UPDATE e executa-a de seguida. O método save aplica a si mesmo a verificação dos valores dos atributos do Model. Quando se efetuam operações manuais tal como consultar informações da base de dados, o utilizador por utilizar os Query Bluilders. Por exemplo a consulta de carros do SeTaRe:

1 Car . where ( model : , 'coup é'). limit (10) . all 2 // convertido SQL :

3 SELECT * FROM cars WHERE model = ''coup é'' LIMIT 10

68 Capítulo 7. resultados

A proteção XSS é implementada através dos módulos Action View e Active Support. A implementação é semelhante à da proteção contra SQL Injection. Mais uma vez, a estrutura usa uma abordagem de lista negra, e fornece sanitization helpers e builders que são usados para construir código HTML comum, tais como links entre páginas e formulários. O mecanismo mais importante é o método escape html, que descarta os caracteres HTML considerados perigosos (& ,>, <, ¨, ´). Outros mecanismos muito importantes, são sanitize css e escape javacript que atuam nos blocos de código CSS e JS utilizando expressões regulares para que a manipulação do lado cliente não seja possível.

• Gestão de Sessões

Rails dispõe também de algumas medidas de proteção contra ataques de manipula- ção de sessões fornecidas nos componentes Action Controller e Action Dispatch. Rails utiliza um valor de hash imprevisível de 32 bytes MD5 como identificador de sessão, e permite que os ataques de fixação de sessão sejam evitados através de um session reset helper. Rails não tem pré-definida uma estrutura de autenticação, e dado o esforço que seria necessário para implementar manualmente, os programadores recorrem à utili- zação de GEMs como o Devise (tal como foi utilizado em SeTaRe) que implementam todo o pacote de mecanismos de gestão. Estas bibliotecas implementam a proteção e o reset de sessões automaticamente.

Struts2

• SQL Injection

Struts2 por si só não dispõe de mecanismos de proteção contra SQL Injection uma vez que se trata de um Framework Pure-MVC. Tal como em Rails estes mecanismos são fornecidos pelo componente Active Record, em Struts2 é Hibernate que é responsável por proteger este tipo de ataques. Através do Hibernate é também possível executar queries SQL nativas utilizando Named Parameters. Os Named Parameters fazem a ligação do valor passado como argumento, ex:

1 ...

2 q = entityManager . createQuery (''SELECT c FROM Car e WHERE c.

licensePlate = ':id ' '')

3 q. setParameter (''id'', licensePlate ) 4 ...

Código 7.15: Proteção contra SQL Injection com Named Queries

Desta forma "licensePlate"é atribuida ao "id"no comando SQL fazendo com que os ca- racteres perigosos sejam automaticamente descartados pelo driver JDBC. Outra forma

7.5. Ecossistema do framework 69

poderá ser através do uso da API Criteria, que fornece um tipo de escrita segura ori- entada a objetos. Esta é baseada num modelo de classes Entidada para além da API de escrita de queries. Desta forma é possível que sejam desenvolvidas queries que o compilador de Java verifica e valida quando compila ex:

1 session . createCriteria ( Car .class, ''car''). add ( Restrictions .eq(''

licensePlate'', licensePlate ))

Código 7.16: Criteria Queries em Struts2

• XSS - Cross Site Scripting

A proteção contra XSS em Struts2 é implementada pela API JSP que disponibiliza um conjunto de tags que permitem a validação de inputs e outputs. Alguns exemplos são: <s:textfield/>; <s:textarea/>; <s:property/>. Estas tags tal como em Rails permitem que se descartem os caracteres especiais ‘<’, ‘>’ and ‘”’. Apesar desta proteção básica fornecida pelos estes componentes, não existe nenhuma tag no Struts2 que garanta a proteção em contexto de código JS ou CSS, o que implica que o programador tenha de recorrer a outras bibliotecas para garantir a segurança da aplicação.

• Gestão de Sessões

Struts2 fornece mecanismos de gestão de sessões que são implementados através de Interceptors dedicados, ou através da implementação da Interface SessionAware nas Action Classes. Estes mecanismos permitem gerir as sessões dos objetos HTTP, bem como manipular de forma segura os dados que são armazenados através dos métodos clear(), invalidate(), remove(), put(), get(), etc.

7.5.6 Testes

A habilidade de fazer testes no código que é desenvolvido permite validar as funcionali- dades que são implementadas, garantindo que a aplicação está a funcionar corretamente. Atualmente a prática de testes considerada melhor aceite pelos Frameworks é Test Driven Development conhecida pela sigla TDD. TDD é uma técnica através da qual são utilizados testes unitários autónomos para que o design do software seja conduzido e forçado a tornar- se mais independente. Com os testes tradicionais, um teste é considerado bem sucedido quando um ou mais defeitos são encontrados, enquanto que utilizando TDD tem-se uma noção clara do sucesso do teste quando este não possuí falhas. Assim TDD aumenta a confiança de que o código desenvolvido, quando preenche os requisitos do sistema.

70 Capítulo 7. resultados

Apesar de não terem sido efetuados testes unitários na implementação de SeTaRe, Struts2 dispõe de um plugin JUnit que permite facilitar o desenvolvimento de testes unitários nas Action Classes. Este plugin fornece uma Classe StrutsTestCase que serve de base para testar os componentes de Struts2.

Rails

Tal como na implementação em Struts2, em Rails também não foram desenvolvidos ne- nhum tipo de testes unitários. No entanto em Rails, para além de não ser necessário acres- centar nenhum plugin extra, esta é uma prática fortemente encorajada desde o começo do desenvolvimento. Um exemplo disso é a criação automática de ficheiros dedicados ao teste funcional dos componentes sempre que um novo Controller ou Model são gerados.

7.6 e x t e n s i b i l i d a d e

Extensibilidade é um princípio de software definido pelo crescimento futuro das aplicações. Este princípio arquitetural define-se pela capacidade de estender o software e pelo nível de esforço necessário para implementar a extensão pretendida. As extensões podem ser efetuadas através da adição de novas funcionalidades ou através da modificação de fun- cionalidades já existentes. Regra geral, as aplicações de software são desenvolvidas para terem uma duração prolongada e para suportarem a introdução de novas funcionalidades. Desta forma o objetivo do principio da extensibilidade é permitir a mudança, minimizando o impacto nas funcionalidades já existentes.

Em Rails ou em Struts2, o princípio da extensibilidade é atingido não através de um mecanismo específico, mas por toda uma inclusão de princípios, como os que foram anteri- ormente falados como são exemplo disso CoC e DRY. Todos estes princípios de desenvolvi- mento pretendem contribuir para a organização do código desenvolvido fazendo com que o código se torne facilmente inteligível, eficiente e flexível [25].

No entanto em Stuts2, a gestão do código como por exemplo a definição de Classes é fácil devido à linguagem de programação estática (Java). Utilizando o IDE NetBeans, podemos procurar o local específico onde métodos e Classes estão definidas, invés de procurar algo hipotético como em Rails (Ruby), onde a gestão do código tal como os nomes das classes de- finidas pode ser considerada difícil de entender devido ao seu tipo de linguagem dinâmica. Através da dinâmica da linguagem Ruby pode facilmente tornar-se confuso, assumir com certezas sobre o que estamos a escrever e a alterar, tendo em conta que não existem avisos de um compilador estático como acontece em Java. Em Struts2, o IoC embora tenha uma forma algo rígida de implementação, esta define uma forma standard de alcançar o baixo acoplamento entre os componentes. Enquanto que em Rails existe uma maior liberdade, sendo que a forma de implementação fica ao critério de programador. Desta forma caso não sejam definidas práticas de desenvolvimento nas equipas este fator pode representar

Documentos relacionados