O que são padrões de projeto na engenharia de software?
No livro A Pattern Language, Christopher Alexander e seus colegas definem um padrão como:
Cada padrão descreve um problema que ocorre repetidamente em nosso ambiente e, em seguida, descreve o núcleo da solução para esse problema, de tal forma que você pode usar essa solução um milhão de vezes, sem nunca fazê-lo da mesma maneira duas vezes.
Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice
Cristopher e os outros autores estavam se referindo a padrões de arquitetura de construção, mas, desde muito tempo, a disciplina de engenharia de software adotou este mesmo conceito para o desenvolvimento de software, que foi cristalizado pelo famoso livro Design Patterns: Elements of Reusable Object-Oriented Software de Erich Gamma, Richard Helm, Ralph Johnson e John Vlissides (conhecidos como Gang of Four ou GoF). No livro, eles definem padrões de projeto como:
Padrões de projeto descrevem objetos e classes que se relacionam para resolver um problema de projeto genérico em um contexto particular.
É preciso entender que os padrões de projeto descritos nestes livros não são soluções que devem ser aplicadas em toda e qualquer situação, mas sim, descrições gerais de soluções para problemas comuns de projetos de software. Desse modo, as soluções propostas podem ser entendidas como um catálogo, a partir do qual pode-se estabelecer um vocabulário comum entre todas as pessoas envolvidas no desenvolvimento de um software, facilitando a comunicação e a compreensão do código.
Para ilustrar o que foi dito até aqui, vamos considerar um exemplo. Suponha que você está construindo um sistema de gerenciamento de uma biblioteca pessoal e, no seu banco de dados relacional, há uma tabela para armazenar os dados de um livro. A tabela pode ser criada com o seguinte comando SQL, em um banco de dados SQLite:
Vamos escolher o padrão Active Record para representar os dados de um livro no nosso sistema. Para isso, vamos criar uma classe em JavaScript conforme o diagrama abaixo:
E este é o código:
Note que todo o SQL necessário para manipular os dados no nosso banco SQLite está encapsulado na classe ActiveRecord
. Além disso, a classe Book
herda todos os métodos da classe ActiveRecord
e, portanto, não é necessário escrever o mesmo código para cada tabela do banco de dados. Desse modo, é possível criar várias entidades distintas no nosso sistema, como Author
, Publisher
, Category
, BookCategory
, BookAuthor
, BookPublisher
, etc. Todas elas herdam os métodos da classe ActiveRecord
e, portanto, não é necessário escrever o mesmo código para cada tabela do banco de dados.
Mais que isso, podemos reimplementar os métodos da classe pai na classe filha, caso haja algum requisito especial para alguma entidade, como transformar o delete
em um soft delete. Por exemplo:
Este padrão pode resolver o nosso caso de uso, porém, como próprio Martin Fowler alerta, este padrão pode não ser o mais adequado para se aplicar em uma entidade que precisa se relacionar com um repositório (ou repositórios) de dados mais complexos (apesar de que Ruby on Rails utiliza este padrão extensamente).
Se tiver alguma dúvida, comentário ou sugestão, deixe um comentário abaixo ou entre em contato comigo pelo Twitter.