Desenvolvimento

3 fev, 2017

Programação orientada a objeto x protocolo

Publicidade

Com o crescimento rápido da tecnologia, o mercado de software foi automaticamente se adequando a essa evolução. Muitas linguagens de programação, paradigmas e práticas foram criadas nos últimos anos por pesquisadores e estudiosos. Algumas se tornaram padrões reconhecidos pela área e seu uso é constante nos dias de hoje; outras, porém, foram até mesmo esquecidas com o passar do tempo.

Neste artigo, vou falar sobre dois conceitos do desenvolvimento de software. Um deles é mais antigo e bastante utilizado pelos desenvolvedores, a programação orientada a objetos. E o outro é programação orientada a protocolos, que foi recentemente lançada em uma nova linguagem de programação, o Swift (por sua vez, criada pela Apple).

Cada uma delas possui vantagens e desvantagens. Vou fazer aqui um comparativo para mostrar quando a utilização de cada uma é melhor implementada no desenvolvimento de software. Vamos lá?

Programação orientada a objeto

O conceito mais difundido atualmente é orientação a objetos. Um dos motivos pelos quais sua utilização teve uma grande expansão foi a vantagem no reaproveitamento de código e o fato de ser uma representação sistêmica muito baseada no que encontramos no mundo real. Desde então, a abordagem vem sendo utilizada em aplicações modernas e também como base de ensinamento em escolas técnicas e universidades ao redor do mundo.

A representação do mundo real utilizada no conceito é baseada em objetos. Pode se simplificar o termo objeto para uma entidade que representa um algo real e concreto. Essa representação pode ou não possuir características e realizar ações.

Para exemplificar o uso de objetos, vou usar um veículo automotivo. No conceito de objeto, as propriedades são chamadas de atributos e as ações de métodos. No caso do objeto veículo, a cor ou o modelo podem ser descritos como atributos e o ato de ligar e desligar são seus métodos. Com essa aproximação do objeto, o desenvolvedor consegue deixar a arquitetura de sua aplicação mais próxima da sua área de atuação.

Principais conceitos

A programação orientada a objetos possui quatro conceitos importantes para entender a abordagem: abstração, encapsulamento, herança e polimorfismo.

Abstração

É quando transformamos uma entidade do mundo real em um objeto para uso na programação. Esse objeto vai ter características e ações da entidade. Assim:

Encapsulamento

O encapsulamento aplica segurança na programação orientada a objetos, escondendo as características e as ações de um objeto. Ou seja, as informações ficam visíveis apenas para o próprio objeto, e outros objetos ou elementos externos ficam sem acesso.

Herança

Um dos conceitos que mais tem relação com o mundo real. A herança é utilizada quando um objeto possui características e ações iguais às de outros objetos. No mundo real, quando se pensa em herança física, consideramos as semelhanças que um filho possui com relação a seus pais, como cor de cabelo e altura, por exemplo.

Polimorfismo

No mundo real, o polimorfismo acontece quando uma entidade consegue alterar uma característica ou ação que foi concedida pela herança. Não é sempre que o objeto precisa usar de fato todas as informações que estão atreladas à entidade superior ao fazer uma herança de entidades. Nesses casos, o polimorfismo pode ajudar.

Para utilizar o polimorfismo em algumas linguagens de programação orientadas a objetos, é necessário que uma nova informação seja associada à fonte herdada (ou fontes ancestrais). Isso irá substituir o valor da informação do objeto pai pelo objeto filho.

Programação orientada a protocolos

Em 2014, na conferência oficial de desenvolvedores que a Apple realiza anualmente, a gigante fez um dos anúncios mais importantes da história dos desenvolvedores da plataforma: uma nova linguagem de programação para seu ambiente de desenvolvimento, que pode (ou não) substituir o antigo Objective C.

O Swift é uma linguagem feita de uma mistura de antigos conceitos de programação, como Programação Orientada a Objetos, Programação Funcional e, agora, Programação Orientada a Protocolos. No anúncio, a Apple diz que a Swift é a primeira linguagem orientada a protocolos no mercado e que o foco é abstração e simplicidade.

Dave Abrahams, contratado pela Apple para ser o engenheiro chefe da linguagem, disse que a programação orientada a protocolos foi pensada com o intuito de proporcionar um melhor código fonte, utilizando structs, types e protocolos no lugar das classes e subclasses.

Principais conceitos

Para entender e usar melhor a Programação orientada a protocolos, é preciso entender alguns princípios, como Structs, Types e Protocolos.

Structs

O comportamento é parecido com o das classes da programação orientada a objeto. Ambos possuem inicializadores, propriedades e métodos, mas as maiores diferenças entre uma e outra são: herança e cópia por referência.

Quando uma classe em Objective C é criada, ela possui uma herança padrão que é a classe NSObject. A Struct, por sua vez, é criada com apenas uma estrutura de dados que pode, ou não, possuir propriedades e atributos. Não existe nenhum tipo de comportamento atribuído externamente.

Outra importante diferença é a cópia por referência. Quando os valores de uma classe são passados para uma nova classe, essa transferência é feita por referência de ponteiros. Isso implica que quando um valor for alterado, ambas as classes sofram alterações. Em contrapartida, a Struct realiza, de fato, uma cópia dos valores e transfere para a nova Struct, assegurando que uma vez alterada a fonte primária dos dados, a secundária não será afetada automaticamente.

Types

No Swift, a tipagem dos objetos foi dividida em dois grupos: named types e compound types. Named types são tipos de objetos que permitem a escolha de uma própria nomenclatura e definição única que podem ser utilizadas em classes, estruturas, enums e protocolos. Compound types são tipos de objetos que podem ter mais de um tipo associado.

Protocolos

São formas de obrigar a implementação de funcionalidades por meio de métodos e propriedades. Essa implementação pode ocorrer em classes, structs e enums, e é o protocolo que diz qual funcionalidade deverá ser implementada. Também há possibilidade de um protocolo ser estendido e serem adicionados comportamentos de ações que serão executadas antes que o objeto implementador do protocolo realize sua ação. Em outras palavras, quando um protocolo é estendido, ele possui a mesma funcionalidade da herança da orientação a objetos, porém sem nenhuma associação fortemente vinculada.

Comparação

Levando em consideração que o uso da programação orientada a protocolos também possui conceitos de programação orientada a objetos, vamos falar sobre as principais diferenças entre cada um dos conceitos: herança e protocolos.

Os programadores são acostumados a solucionar problemas utilizando práticas da orientação a objetos, como classes e subclasses. Com o uso sem conhecimento das consequências da herança, isso pode gerar um problema de complexidade na aplicação.

Uma prática muito comum entre os desenvolvedores é a utilização de uma classe que possui uma ou mais responsabilidades chaves e a criação de várias subclasses para estender o seu uso. Assim, quando a subclasse for executar a funcionalidade, podemos acrescentar algum comportamento extra, mas o comportamento base será sempre da classe que foi herdada. Nesse caso, quando a classe herdada sofrer alterações de comportamento, todas as suas subclasses também passam a ter o comportamento modificado, o que pode gerar grandes bugs na aplicação.

Para exemplificar o uso da herança e a forma como o protocolo substitui esse conceito, vamos apresentar implementações dos conceitos e uma análise crítica de suas formas de serem inseridas em sistemas de informação.

No exemplo, vamos implementar um aplicativo mobile que possui um menu de opções para funcionalidades diferentes. Para que o usuário consiga navegar entre os fluxos do aplicativo, é preciso acionar a funcionalidade de mostrar e ocultar o menu. Olha só:

Neste exemplo, criamos uma classe base que possui duas assinaturas de métodos: uma para mostrar o menu e outra para esconder o menu. Criando a classe responsável pelo comportamento da exibição do meu, as outras classes precisam ser criadas como uma hierarquia da classe “ComportamentoMenuViewController”.

No exemplo acima, citamos classes com herança e override dos métodos de comportamento de menu. Nesse estado em que as classes se encontram, podemos ver que com o crescimento do sistema vai ter uma alta dependência entre as classes.

Quando precisarmos modificar algo na classe “ComportamentoMenuViewController”, isso impactará todas as demais classes que possuem sua herança. Essa modificação pode conter comportamento diferente ou deleção de comportamento, ou seja, o código fica sensível a novas falhas. A implementação desse caso de uso utilizando herança é conhecido na comunidade de desenvolvedores como god class, uma classe que governa todas as outras.

O uso de protocolo tem suas vantagens para a implementação desse cenário de caso de uso. O Protocolo não gera uma dependência entre classes, podemos até usar o termo “contrato” para entender. O contrato é nada mais do que contratar um comportamento que algum protocolo esteja fornecendo.

A possibilidade de contratar ou não um comportamento de protocolo permite que a classe tenha apenas o comportamento que ela deseja, o que torna a implementação mais modular e extensível.

No último exemplo, mostramos a implementação do mesmo caso de uso utilizado na herança, mas usando protocolo. Os conceitos são muito parecidos, a diferença é que o protocolo consegue abstrair o acoplamento de referência das classes e torna o código melhor para futuras manutenções.

Conclusão

Se comparada à engenharia civil, engenharia de telecomunicações e engenharia elétrica, a engenharia de software é uma das engenharias mais novas, que ainda não conseguiu amadurecer o suficiente para ter uma perspectiva concreta de quando vai ser entregue e o que vai ser entregue. Talvez um dos motivos seja a rapidez em que a tecnologia evolui, o que faz com que cada vez mais os softwares se tornem complexos e difíceis de serem desenvolvidos.

São muitas alterações constantes, e acredito que ainda não tenhamos chegado à fórmula definitiva de como se construir um software. Apesar do aumento de complexidade, os recursos que os desenvolvedores de software utilizam também foram melhorados. Vários conceitos foram criados em favor a essa mudança constante e cada um possui seu lugar.

Essa mudança não quer dizer que os novos conceitos são melhores que os antigos. Da mesma forma que a programação orientada a objetos surgiu para resolver um problema, a programação orientada a protocolos também surgiu para resolver outros tipos de problema. Cada conceito possui suas vantagens, desvantagens e ponto de atuação.

Atualmente é fácil perceber que, no geral, os desenvolvedores estão adotando muito as abordagens que possuem abstração, conceito muito utilizado pela programação orientada a protocolos. Ela consegue fazer com o que o desenvolvedor separe as funcionalidades de acordo com qualquer contexto e ainda assim minimizar as referências fortes de objetos.

Ambos os conceitos conseguem chegar em um mesmo resultado. Porém, por possuir a facilidade de uma maior abstração, a orientação a protocolos tem o maior índice de aceitação. A atual cobrança por uma melhor qualidade dos produtos também teve seu nível de exigência aumentado recentemente, e quando falamos de testes unitários, arquiteturas escaláveis, integração contínua, deploy automatizado etc., tudo depende de como o software foi arquitetado. Sem abstração, é praticamente impossível implementar técnicas de melhorias, e as novas linguagens e paradigmas recém criados estão facilitando essa integração e auxiliando o desenvolvedor a criar softwares melhores, duradouros e com uma menor taxa de manutenção.

Ficou alguma dúvida ou tem algo a acrescentar? Aproveite o campo abaixo!

***

Artigo publicado originalmente em: http://www.concretesolutions.com.br/2017/01/27/programacao-objeto-x-protocolo/