Aplicando os princípios SOLID com AdvPL/TL++ (Parte 2 — OCP)

Eduardo Riera
TOTVS Developers
Published in
3 min readApr 26, 2018

Open-Closed Principle

“Entidades de software devem ser abertas para extensão e fechadas para modificação”.

O Princípio Open-Closed (OCP) afirma que entidades de software (módulos, classes, métodos e outras entidades) devem ser abertos para extensão, mas fechados para modificação. Todos os módulos, classes, métodos, entre outros, devem ser projetados de forma modular para que outros desenvolvedores possam alterar o seu comportamento sem alterar o seu código-fonte.

A importância deste principio esta no fato que um projeto de software é frequentemente modificado durante o seu ciclo de vida, por exemplo, para atender aos novos requisitos do cliente. Portanto, o objetivo de um desenvolvedor deve ser criar um sistema flexível que seja fácil de modificar e estender. O princípio Open-Closed ajuda os desenvolvedores a obter uma código-fonte flexível.

Class Report From LongClassName

EndClass

Class ReportPdf From Report

Method GerarPdf()

EndClass

Class ReportWord From Report

Method GerarWord()

EndClass

Class RunReports From LongClassName

Method RunReport()

EndClass

Method RunReport(aObjects) Class RunReports

Local nX

For nX := 1 To Len(aObjects)

Do Case

Case aObjects[nX]:ClassName() == “ReportWord”

aObjects[nX]:GerarWord()

Case aObjects[nX]:ClassName() == “ReportPdf”

aObjects[nX]:GerarPdf()

EndCase

Next nX

Observando o código acima, em primeira vista parece, ok. Porém podemos identificar diversos problemas que poderão ocorrer durante o ciclo de manutenção deste código. Por exemplo, vamos supor que temos um novo requisito para criar a funcionalidade “GerarExcel”. Para fazer isto, basta criar uma classe que herdada da classe “Report” e incrementar o método “RunReport” da classe “RunReports”. Note que este padrão seria seguindo para cada nova implementação.

Do ponto de vista do principio OCP, a classe "RunReports" não esta fechada para alteração e muito menos esta aberta para extensão.

Mas qual o problema de termos um If ou Case a mais? Toda vez que uma nova implementação for feita, seria necessário refazer todos os casos de teste para verificar qualquer quebra do código-fonte. Para o deploy da aplicação, seria necessário enviar um pacote maior que o necessário para a implementação, por conta das dependências.

Agora vamos ver uma outra forma de escrever este mesmo código-fonte.

Class Report From LongClassName

Method Gerar()

EndClass

Class ReportPdf From Report

Method Gerar()

EndClass

Class ReportWord From Report

Method Gerar()

EndClass

Class RunReports From LongClassName

Method RunReport()

EndClass

Method RunReport(aObjects) Class RunReports

Local nX

For nX := 1 To Len(aObjects)

aObjects[nX]:Gerar()

Next nX

Agora vamos analisar o que foi feito. Em primeiro lugar, transformamos a “Report” em uma classe abstrata. Entenda por classe abstrata uma classe que não precisa ser instanciada. Nesta classe abstrada foi adicionado o método “Gerar” que deverá ser implementado em toda classe que herdar a nossa classe abstrata. Implementamos o método “Gerar” nas classes que implementam o formato de geração do relatório e alteramos o método “RunReport”, removendo o DoCase/EndCase.

Com esta alteração, caso tenhamos que implementar o método “GerarExcel”, basta implementar a classe “GerarExcel”, com base na classe abstrata “Report”.

O OCP nos convida a planejar melhor as abstrações e polimorfismo, garantindo que tenhamos um código-fonte mais flexível e, portanto, mais fácil de ser mantido.

O AdvPL não tem em sua implementação os conceitos de POO: Classe Abstrata e Interface , porém o TL++ introduz o conceito de Interface, possibilitando a utilização deste principio. Veja mais em: http://tdn.totvs.com/pages/viewpage.action?pageId=357600393

--

--

Eduardo Riera
TOTVS Developers

Software engineer, ERP specialist and enthusiast technology, helping companies in the era of digital transformation.