[MÚSICA] [MÚSICA] Olá.
Bem-vindo ao curso sobre TDD.
Eu sou o Clóvis Fernandes e hoje iremos fazer uma pequena apresentação
sobre como seria fazer uma refatoração, assim alto nível,
nós iremos depois apresentar material de leitura detalhando,
o uso da singular responsability principle, está certo?
Então hoje a gente vai mostrar muito rapidamente a aplicação,
uma refatoração usando o SRP do SOLID.
Português é a responsabilidade única, não é?´Está certo?
É o principio da responsabilidade única que eu chamei a atenção na aula anterior
de apresentação do SOLID.
Volto a falar agora sobre esse princípio.
Quando o Uncle Bob chama de responsabilidade da classe,
ele está se referindo aquilo que nós quando fizemos
a definição dos cartões CRC,
nós falávamos que era a finalidade da classe, a descrição da classe, está certo?
É isso que nós estamos usando.
Então, o termo ficou o nome que o Uncle Bob deu,
não é o mais adequado, mas ficou e a gente tem que estar sempre explicando isso.
No fundo você vai sempre olhar para o que é tarefa ou que é papel ou que
aquela classe está exercendo, está certo?
E é isso que nós vamos querer que seja apenas papel,
uma tarefa, uma finalidade, está certo?
Ou uma responsabilidade como o Uncle Bob fala,
mas essa responsabilidade não é aquela que nós trabalhamos nos cartões CRC.
O R do CRC, responsability, ele quer dizer as responsabilidades,
tudo o que a classe faz ou sabe, está certo?
Obviamente, no nosso caso aqui, nós vamos estar tratando como se fosse tarefa,
finalidade da classe.
Está okay?
E, nesse sentido, como eu vou ter uma finalidade.
Devo ter, espero ter uma finalidade, todas as outras classes
que tenham acoplamento, dependam de mim, está certo?
Só vai existir uma razão para eu mudar, porque eu tenho uma finalidade,
está certo?
Agora, quando eu tenho duas finalidades,
aí a coisa já começa a ficar complicada, está certo?
Isso tem a ver com com a questão da coesão, não é?
Nós já tínhamos conversado também que todos os 5 princípios
trabalham com a coesão na classe, eu quero obter alta coesão, está certo?
E baixo acoplamento, alta coesão.
O conjunto de responsabilidades que eu defini para aquela classe devem ajudar
a satisfazer a finalidade da classe, a tarefa da classe.
Está certo?
Já o acoplamento eu quero ter baixo acoplamento, está certo?
E vão existir maneiras de eu trabalhar esse, de eu baixar esse acoplamento,
gerenciar ele para ficar de uma maneira mais
confortável para trabalhar, está certo?
Bom, com relação à questão da coesão,
quando eu tenho duas finalidades, está certo?
Aí, eu já começo a ter uma, grau de coesão baixo.
Imagine que a minha classe tenha 10 responsabilidades no
sentido lá do cartões CRC, não é?
Está certo?
E cada uma satisfaz uma finalidade diferente para a minha classe,
ou seja, eu tenho uma classe que tem 10 finalidades.
Está certo?
Ou seja, na verdade, uma classe desse tipo é amontoado de coisas,
não tem significado para mim.
Está certo?
Ou seja, as outras classes dependerem dessa classe com tão baixa coesão,
está certo?
Vão existir muitos problemas, porque toda a vez que eu fizer alguma mudança uma,
todas elas vão ter que ser testadas para saber se a mudança que eu fiz
numa responsabilidade das 10 afetou as outras ou não, está certo?
Então, isso é importante,
ter uma responsabilidade apenas e também ter número baixo de responsabilidades.
Isso é outra coisa importante também.
Quando a gente trabalhava com o cartão CRC, o cartão já era delimitador.
Aquele cartão, que consegue colocar no máximo, 15,
menos que 15 responsabilidades, sendo uma por linha, está certo?
Então, esse seria bom número também.
Está certo?
Entre 10 e 15 responsabilidades, 10 seria mais agradável.
Porque se você fizer uma análise como nós mostraremos, não é,
da, sobre a, essas múltiplas finalidades,
você vai perceber que isso pode ocorrer, como eu falei dos acoplamentos.
Qual a influência que o acoplamento tem na coesão?
É isso que nós vamos mostrar.
Como nós estamos desenvolvendo isso com o TDD, à medida que novas responsabilidades,
no sentido que nós vinhamos trabalhando de requisitos, não é, elas vão sendo
incorporadas, adicionadas, eu vou criando novas classes, acoplando com outras.
Então, a questão da coesão eu não consigo trabalhar sem saber o
contexto que essa classe está, termos de acoplamento.
Quem depende dessa classe, está certo?
Porque dependendo do,
se tem poucas dependências, acoplamento baixo, está certo?
Pode acontecer que eu não precise, trabalhar se
eu tiver duas finalidades, está certo, num dado momento.
À medida que eu vou, novas classes por causa de novas responsabilidades,
os acoplamentos de novas classes a essa classe podem aumentar e aí, realmente,
pode ser que eu tenha que, realmente,
fazer uma refatoração para tratar esse tipo de problema.
Vamos exemplificar então.
Eu estou mostrando aí uma classe retângulo, não é?
Está certo?
A classe retângulo, ela tem 2 métodos apenas.
O método draw para desenhar e o método área que vai me voltar
double a área do retângulo, está certo?
A pergunta é: eu consigo dizer se há
alguma problema de finalidade só olhando essa classe?
Fica muito difícil, está certo?
Eu tenho só 2 métodos, mas eu podia, eu estou exemplificando,
podia ter mais métodos na verdade, está certo?
Eu estou só exemplificando isso.
Bom, o que é que acontece?
Eu vou examinar, vou olhar se tem mau cheiro, não é?
Está certo?
Será que tem mau cheiro?
Mas uma coisa é importante, para esse princípio,
eu tenho que olhar o contexto, quem está dependendo dessa classe, está certo?
Então, olhando isso,
vocês vejam que eu tenho uma aplicação gráfica que vai fazer uso do retângulo.
Está certo?
Ela depende da classe retângulo e ela depende também da interface
gráfica com o usuário, o g, u, i, o GUI, não é?
Está certo?
A graphical user interface.
A aplicação gráfica, ela desenha retângulo na tela.
Bom, outro,
a outra classe que depende do retângulo é a aplicação de geometria computacional.
Está certo?
A aplicação de geometria computacional,
ela usa o retângulo só para obter a matemática das formas geométricas.
Ele está interessado apenas nisso.
Nunca desenhe o retângulo na tela, está certo?
Então, vocês vejam que eu tenho duas classes que
dependem de retângulo, está certo?
Uma depende do método draw para desenhar, a outra depende do
método área e aí, a classe retângulo fica claro que ela tem duas tarefas, não é?
Para satisfazer as duas necessidades das classes que dependem dela.
Uma é fornecer modelo matemático para aplicação de geometria computacional
e a outra é de ajudar, não é, a renderizar o retângulo, numa interface gráfica.
Então, vocês vejam que eu tenho aqui duas tarefas,
duas razões para mudar e se eu mudar alguma coisa
no método, referente à renderização para desenhar.
Está certo?
De qualquer forma, ele vai afetar a aplicação de geometria computacional,
porque eu não sei o que é que vai acontecer.
Então, alterando alguma coisa aqui, mesmo que eu não
altere a interface do método draw ou área,
vai afetar a aplicação de geometria computacional.
Lá vou ter que testar de novo, para ver se agora, ainda está funcionando.
Está certo?
Mesma coisa se eu mudar alguma coisa na área, eu vou ter que testar
a aplicação de geometria computacional e também a aplicação gráfica.
porque eu não sei se a mudança que eu fiz vai afetar ou não,
então esse é o mau cheiro, né, tá certo.
Existem 2 razões, ou mais né, 2 no mínimo, né,
tá certo nesse caso, no exemplo, é 2, podem existir
outras classes mais do que 2, para eu fazer mudanças, entendeu?
Eu faço uma mudança que vai interferir mais gente do que deveria.
Se eu tenho uma finalidade só, eu faria uma mudança todo mundo que
estivesse interessado mim seria afetado,
tá certo mas quando eu tenho 2 eu estou amplificando isso,
né tá certo e sem saber, às vezes eu estou fazendo coisas que não preciso.
Quando eu tenho uma só, todos que dependem de mim precisam ser testados de novo
porque eu realmente mudei, agora na outra, nesse exemplo que eu tenho 2 finalidades,
isso eu posso estar fazendo teste desnecessário, tá certo.
Então o que que a gente faz então?
A gente vai fazer aquilo que o princípio propõe.
No nosso caso, fazer uma classe para cada uma das finalidades
aquilo que o Uncle Bob chama de responsabilidade.
Então vocês percebam que eu separei 2 classes, né, tá certo.
O que eu estou chamando de responsabilidade aí é no sentido do
Uncle Bob, é na finalidade tá certo.
Então eu tenho uma classe que continua sendo o mesmo nome que é o retângulo,
então essa classe vai ter uma interferência mínima na, nenhuma na
verdade na aplicação gráfica porque a aplicação gráfica só usava o método draw.
O nome era retângulo então ele não tem alteração nenhuma,
tá certo, efeito nenhum essa operação de quebrar 2 classes.
Já a outra classe retângulo bom, a retângulo,
no sentido de renderizar faz uso também da classe nova retângulo geométrico.
O que é que acontece?
A aplicação geométrica, de geometria computacional com relação à assinatura
do método área, tá certo, não há mudança nenhuma,
mas o nome da classe da qual ela está acoplada mudou.
Antes era retângulo, agora passa a ser retângulo geométrico, tá certo,
houve alguma alteração.
O DIP, o Dependency Inversion Principle,
vai ajudar até eu eliminar essa dependência que eu acabei de colocar aqui,
quer dizer, eu poderia fazer essa mudança,
eu vou mostrar exemplo depois material de leitura,
que a gente mostra e até esse efeito colateral que continuou tendo agora,
vai sumir, tá certo, na hora que eu estiver fazendo a refatoração.
Vocês vejam que agora eu coloquei aqui o antes e o depois,
eu tenho antes retângulo e depois eu tenho o retângulo
e o retângulo geométrico, tá certo, eles estão até acoplados ao outro.
O que é que acontece aqui?
Não é uma coisa que é imediata, eu falo assim, eu quero,
eu encontrei esse retângulo e vou refatorar.
Não, é aquilo que eu mostrei, eu tenho que ver o contexto, tá certo,
eu tenho que ver o contexto.
Já quando aparece uma nova responsabilidade
que vai adicionar o contexto da aplicação de geometria computacional,
nessa hora é que eu vou fazer esse tipo de refatoração,
tá certo, porque aí eu vou perceber que eu vinha
tolerando ali, eu vinha tolerando porque ela,
é na verdade ela nem aparecia porque o contexto meu não exigia isso.
Mas a outra agora começou a usar só a parte da área, só a parte matemática.
Na verdade seria conjunto de métodos de retângulo que
fosse satisfatório para a aplicação de geometria computacional.
Então nessa hora é que eu vou fazer a refatoração, tá certo?
Então eu não teria, usando TDD,
dúvida de quando eu deveria fazer, tá certo?
O exemplo está só mostrando uma coisa que foi feita e proposto e apresentado
pelo Uncle Bob na década, no final da década de 80, tá certo?
Com isso a gente conclui a refatoração
que aplicamos o SRP, né, tá certo,
o Single Responsibility Principle que é o primeiro princípio,
a letra S, né, do SOLID o conjunto do SOLID,
para fazer uma refatoração que nós vimos que mau
cheiro significa violar o SRP, tá certo,
que ao invés de ter 1 tinha 2 finalidades à classe, tá certo.
E aí o que é que nós fizemos?
Resolvemos criando 2 novas classes a partir daquela classe inicial, tá certo.
Obrigado.
[MÚSICA]