Alura > Cursos de Programação > Cursos de PHP > Conteúdos de PHP > Primeiras aulas do curso SOLID com PHP: princípios da programação orientada a objetos

SOLID com PHP: princípios da programação orientada a objetos

Preparando o terreno - Introdução

Olá, pessoal. Sejam muito bem-vindos à Alura. Meu nome é Vinicius Dias, e eu vou guiar vocês nesse treinamento de SOLID e boas práticas de Orientação a Objetos.

Vamos começar falando um pouco de alguns conceitos da Orientação a Objetos, conceitos muito importantes para darmos continuidade ao treinamento, e depois falaremos de cada um desses princípios: sobre Princípio de Responsabilidade Única, Princípio de Aberto e Fechado, Princípio de Substituição de Liskov, Princípio de Segregação de Interface, e Princípio da Inversão de Dependência.

E além de ver e falar sobre esses princípios, vamos implementar na prática em um projeto bem simples, mas que vai dar base para entendermos como cada princípio é aplicado e quais as vantagens de cada um.

No final, vamos ter um código, bem tranquilo, bem simples de entender representando um modelo fictício da Alura, onde nós temos um vídeo, onde nós temos a AluraMais que nada mais é do que um vídeo, só que você recebe pontuação por isso, nós temos um curso que você pode receber pontuação além de poder assisti-lo, vamos separar o feedback, onde ele vai ter suas próprias regras, enfim, vamos trabalhar bastante.

Para esse treinamento eu espero que você já tenha conhecimento com Orientação a Objetos, porque nesse treinamento vamos falar sobre algumas boas práticas da Orientação a Objetos. Também espero que você já tenha o PHP instalado na sua máquina e que você baixe esse projeto no primeiro exercício dessa aula.

Com isso, você já vai estar pronto para dar continuidade para esse treinamento. Te espero no próximo vídeo para começarmos a bater um papo sobre alguns conceitos da Orientação a Objetos.

Preparando o terreno - Coesão

Vou deixar esse projeto aqui para vocês baixarem. É um projeto que representa bem por alto um modelo da Alura, onde temos cursos, tem vídeos da AluraMais, tem para o vídeo em si, tem um serviço para assistir cursos, vídeos etc, um calculador de pontuação para fazer aquele cálculo de quantos pontos você ganha por assistir um curso etc, enfim, bem resumido.

Mas eu quero conversar com vocês sobre, obviamente, como é o assunto do curso, Orientação a Objetos. Se você estudou sobre Orientações a Objetos, e espero que você tenha estudado para chegar nesse treinamento já um pouco mais avançado, você com certeza já ouviu falar sobre alguns pilares da Orientação a Objetos como, herança, encapsulamento, polimorfismo, abstração, enfim, esses termos, esses pilares da Orientação a Objetos.

Mas a Orientação a Objetos também traz, enquanto estamos desenvolvendo, utilizando esse paradigma da Orientação a Objetos, esbarramos em conceitos e problemas um pouco diferentes e nesse treinamento vamos falar mais sobre esses conceitos, e o primeiro que eu quero conversar com vocês é sobre a Coesão.

O que é Coesão no sentido de desenvolvimento de software, de arquitetura de software? Uma classe coesa, ela faz só o que faz sentido, ela só tem implementado nela o que faz sentido, para sua definição, para seu modelo, para seu domínio.

Um exemplo, no nosso projeto aqui, é a classe Video. O que a classe Video representa? Ela representa um vídeo da Alura, seja na AluraMais, seja um vídeo de um curso, independente do que for, é um vídeo. Esse vídeo pode ter sido assistido ou não, esse vídeo tem um nome, o vídeo tem uma duração, isso tudo faz, é referente ao vídeo e somente ao vídeo.

[01:48]Eu não tenho aqui dentro da classe Video alguma coisa fazendo menção a um curso, ou a AluraMais, ou a pontuação. Dessa forma, eu tenho a classe Video sendo responsável somente pelo que ela realmente deve ser responsável, ou seja, ela tem uma única responsabilidade, que é representar o vídeo.

E vamos conversar um pouco melhor sobre responsabilidade em um capítulo futuro. Mas toda classe não é assim? Você só descreveu qualquer classe que faz só o que tem que fazer.

Vou te dar um exemplo que provavelmente você já viu desenvolvendo no seu trabalho, nos seus estudos, que é sugerir aqui um exemplo de uma classe Pessoa, só que essa classe tem nome, telefone, endereço, até aí tudo bem, esses poderiam ser atributos de uma pessoa, mas tem a cor da casa onde essa pessoa mora, tem o modelo do celular que ela possui. Aqui já estamos entrando em responsabilidades, em atributos, propriedades que não são dessa classe, que não pertencem à pessoa.

A cor da casa dessa pessoa podia muito estar dentro de um objeto casa. O modelo do celular, se eu realmente precisasse disso, estaria aqui dentro de telefone. Essa pessoa já está tendo atributos, tendo informações demais. E pior do que isso, ela tem responsabilidades, ela executa ações que não deveria.

Como por exemplo, imprimir um relatório. Não é uma pessoa que deve imprimir um relatório, não é a classe Pessoa. A classe Pessoa serve para representar uma pessoa. E a representação de uma pessoa não faz impressão de um relatório, muito menos salva os dados em um banco de dados. A própria pessoa, além de representar seus dados vai se salvar no banco? Isso é uma péssima prática.

Você tem muitas responsabilidades, você tem muitos atributos, você tem muita coisa dentro da mesma classe. Essa classe não está coesa. Essa classe não faz sentido para o modelo dela, ela está fazendo muito mais do que deveria.

E isso acarreta em problemas que vamos discutir nesse treinamento, mas basicamente isso acarreta em classes difíceis de manter. Em vários momentos, por vários motivos diferentes, eu vou precisar vir aqui nessa classe Pessoa e editar o código dela.

E sempre: editar um código que já existe pode gerar bugs. Você provavelmente já sabe disso, mas quando mexemos em código que já existe, podemos estar criando um bug novo, podemos estar quebrando uma funcionalidade que já funciona, fazer deixar de funcionar.

Vamos também conversar sobre isso. Como evitar mexer em código que já está funcionando. Se eu precisar implementar alguma coisa nova, eu crio um código novo.

Isso é o que é chamado de Coesão e vamos ver mais para frente como resolver um problema de uma classe que não é coesa. Agora, que já entendemos esse conceito de Coesão, já definimos bem o que é isso, vamos continuar conversando sobre outros problemas, outros conceitos que esbarramos durante o desenvolvimento do Orientação a Objetos.

Preparando o terreno - Encapsulamento

Olá, pessoal. Bem-vindos de volta. No último vídeo eu falei no desenvolvimento da Orientação a Objetos, quem dera nós estivéssemos desenvolvendo esse paradigma, eu quis dizer, durante o desenvolvimento utilizando a Orientação a Objetos. Bom, continuando, o próximo conceito que eu quero falar com vocês é algo que vocês com certeza já ouviram falar, que é um daqueles pilares que eu citei, que é o encapsulamento.

E o que é o encapsulamento? É ter as propriedades privadas e os métodos públicos, criar getter e setter. Se você tem essa visão, de que isso é encapsulamento, tenho uma má notícia para você. Não é isso. Encapsulamento não é só ter propriedades privadas e métodos públicos, até porque, se eu tiver todos os métodos públicos, eu estou fazendo exatamente o contrário do encapsulamento.

Para entendermos bem o conceito do encapsulamento, vou dar um exemplo da vida real. Quando você compra um aparelho de DVD, existe lá um botão, independentemente do modelo do aparelho, pelo menos no controle com certeza tem, um botão de um triângulo deitado, um triângulo para o lado, e você sabe que esse triângulo representa o play. Se você pegar um videocassete, que é um aparelho mais antigo, e você encontrar esse botão, essa imagem, você vai saber que esse botão dá o play, que esse botão executa a reprodução.

Isso é o encapsulamento. Por baixo dos panos, o que está acontecendo, como cada aparelho funciona, não importa para nós. O que importa é a ação que está disponibilizada para nós. Só que o aparelho, os desenvolvedores do aparelho encapsularam a ação de dar play através de um botão, simplificaram essa ação e disponibilizaram uma interface para nós, que é um botão.

Isso, traduzindo em código, pode ser visto de forma semelhante aqui. Nós temos um assistidor, de curso, de vídeo da AluraMais, independente do que for, e se eu tenho um curso, eu preciso assistir de uma forma, tenho que pegar todos os vídeos e depois ir marcando um por um como assistido. Se for um vídeo da AluraMais, eu simplesmente marco ele e digo que eu quero assistir.

Nós temos implementações diferentes, isso não está muito bem encapsulado, está bem claro aqui que eu preciso conhecer a implementação da classe Curso para saber como eu que eu marco o curso como assistido. Isso não é legal, e vamos ver como melhorar isso depois.

Mas agora, outro exemplo também de algo que não está bem encapsulado é como recuperar a pontuação de cada um. Eu conheço a implementação de curso e sei aqui dentro da classe CalculadorPontuacao que um curso vale 100 pontos quando eu finalizo ele. Já um vídeo da Alura mais vale a quantidade de minutos que ela tem, multiplicado por dois. Então eu conheço a implementação, as regras de outras classes, eu estou ferindo aqui o encapsulamento.

Já um exemplo do encapsulamento acontecendo é esse método: minutos de duração. Eu preciso saber quantos minutos de duração existe aqui nesse conteúdo. Que no caso eu sei que é um vídeo da Alura mais. Então eu preciso conhecer, saber quantos minutos de duração.

[03:11]Mas eu não quero saber como ele calcula esses minutos de duração, se ele pega um time-stamp e depois compara com outro time-stamp e me retorna a diferença, se ele faz o cálculo utilizando o relógio do sistema ou não, eu não quero saber. Aqui, a implementação está sendo feita através de uma classe DateInterval que é uma classe do PHP, mas tudo que ela me retorna é os minutos. Então, aqui temos um exemplo bem simples de como o encapsulamento pode nos ajudar.

Se alguma pessoa nova vier para nossa equipe e precisar pegar os minutos de duração, ela não precisa conhecer a implementação da classe DateInterval, nem da classe Video, ela só vai pegar os minutos de duração. Ela sabe que isso retorna um inteiro para ela que representa os minutos.

Com isso, com o encapsulamento, facilitamos a migração de funcionalidades, como, por exemplo, se eu quiser mudar de um vídeo cassete para um aparelho de DVD, ou de um aparelho de DVD para um aparelho de Blu-Ray, eu sempre vou ter o botão de play para começar a reproduzir o conteúdo.

Aqui, se eu quiser marcar como assistido algum conteúdo, eu quero poder marcar como assistido qualquer conteúdo, eu quero encapsular esse comportamento dentro das minhas classes para que isso fique, para que a implementação interna de cada um fique por responsabilidade delas, eu só quero executar uma ação.

O encapsulamento nos ajuda com isso. As classes que fornecem o encapsulamento de forma correta vão facilitar seu uso. Ou seja, outras pessoas que desenvolvem e vão utilizar essa classe, vão utilizar ela com mais facilidade e essa é a vantagem do encapsulamento.

Agora que já entendemos o que é e em que pode nos ajudar a coesão, e também o encapsulamento, falta mais um conceito que eu quero passar com vocês antes de colocarmos a mão na massa e escrever código em si. Eu sei que essa parte teórica não é tão emocionante, tão divertida, mas é muito importante para darmos continuação a esse curso. Te espero no próximo vídeo para falarmos sobre acoplamento.

Sobre o curso SOLID com PHP: princípios da programação orientada a objetos

O curso SOLID com PHP: princípios da programação orientada a objetos possui 61 minutos de vídeos, em um total de 43 atividades. Gostou? Conheça nossos outros cursos de PHP em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda PHP acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas