Pessoal, bom dia.
Hoje é o dia 12 de julho de 2020.
Um domingo de sol, no qual, naturalmente, vou ficar em casa,
porque é pandemia, então, vamos à gravação de exposição de aula.
Estamos aqui no Grupo de Slides número 6.
Aonde a gente continua falando de listas, mas agora listas mais efetivamente.
De maneira tal que a gente vai melhorar
a composição estética e também a composição
no âmago das listas pra que eles respeitem coesão e desacoplamento
e associado a isso, em alguma maneira,
a gente também vai falar de alocação dinâmica.
Continuar falando o que a gente já falou na exposição anterior.
Vamos aprofundar o assunto indubitavelmente.
Isso posto, vamos colocar em Modo Exibição aqui.
Aí está.
Slides 2.
Vamos retomar os nossos últimos slides, tá.
Aonde a gente tava falando de objeto Elemento Aluno.
A gente de fato encontra essa solução baseada em Elemento Aluno
basta você verificar a última aula, né.
Aonde você tem essa classe aqui de associação, ou de relacionamento, tá.
Vai permitir animar aquele relacionamento da Disciplina
ser cursada por um conjunto de Alunos, né,
e os Alunos cursarem um conjunto de Disciplinas.
Essa relação n pra n.
Pra isso a gente criou aquela classe de associação
que já foi bem debatida na aula passada, né.
Então, não vou reentrar no mérito.
Aqui, por algum motivo de impressão,
ele tá trazendo essa linha contínua que deveria ser pontilhada tal qual é
quando o slide não está em Modo Exibição.
Avancemos aqui.
Aqui tá o código relativo àquele modelo como a gente já discutiu na aula passada, né.
Você percebeu que agora o Aluno não tem mais pProximo e pAnterior,
porque isso foi colocado de maneira decente e estética, inclusive,
na classe chamada Elemento Aluno,
que essa sim gerencia o Aluno e tem pProximo e pAnterior.
Ainda, isso aqui está público, tá. Você vai ter que privar isso aqui
fazer sets e gets apropriados, insisto.
Muito bem.
Se você parar pra reparar agora lá na classe.
No próximo slide.
Disciplina.
Não tem mais pAlunoPrimeiro.
tem pElemento, El, AlunoPrimeiro.
pElAlunoAtual.
São ponteiros de Elemento Aluno.
Obviamente, né, que essas entidades que gerenciam os Alunos na lista conforme já discutido.
E aí, é baseado nisso que a função incluaAluno funciona
e a listeAlunos e a listeAlunos2, tá.
Se você olhar aqui a incluaAlunos, a incluaAluno, perdão,
no singular, incluaAluno.
Vai receber o endereço de algum Aluno
por meio de um ponteiro
tem aqui a função que a gente
trabalhou, discutiu bastante na exposição anterior
que eu mostrei pra vocês na noite de ontem.
Aqui, eu fiz algumas melhoras no código, tá.
Porque código é igual a vida da gente, né.
A gente, ainda que com parcimônia, a gente tem que ir melhorando
a nossa existência, né. Dia a dia, passo a passo, tá.
Porque esse é o sentido da vida.
E o código não foge disso.
Esse código em azul aqui, ó.
Nos slides anteriores, esse código em azul estava fora do if
agora eu coloquei ele pra dentro do if, porque faz mais sentido.
Só faz sentido eu criar esse ponteiro auxiliar e fazer alocação de memória dinâmica
no âmbito aí, do experimento dado,
se aquele if for aprovado.
Só faz sentido depois de eu alocar dinamicamente, aqui, o Elemento Aluno,
fazer com que ele cuide de um Aluno,
só faz sentido se esse if passar.
Até o código funcionava como estava, tá.
Tem problema nenhum.
Só... do ponto de vista de inclusão, bem entendido.
Se eventualmente o if não fosse aprovado e
a gente tivesse a execução do ocorrendo,
o que ia acontecer é que
você ia ter uma alocação de memória dinâmica
aonde não ia ter amarração de próximo nem anterior.
Então, depois na deleção que usa próximo e anterior
não ia contemplar esse cara que teria sido criado, né,
sem ter sido amarrado com próximo e anterior, tá.
Ele ia ficar um zumbi na memória.
Então, aquela situação lá serve, pra você prestar bastante atenção quando você tá alocando memória, tá.
Quando você tá alocando memória.
você tem que pensar se o contexto todo
ele, depois, vai lhe permitir desalocar memória, tá.
Nesse sentido aqui, tá.
Se eu aloquei memória pra lista Elemento Aluno
eu tenho que ter um jeito de localizá-lo depois.
Esse ponteiro aqui, ó.
É um ponteiro temporário, ele só existe dentro da função, então ele é um apelido
pra esse objeto que tá sendo criado aqui,
mas ele é um apelido dentro desse contexto dado.
Depois isso some.
Mas, professor, como é que eu vou conseguir ter acesso esse cara?
Através da lista encadeada. Lá do primeiro, no próximo, próximo, próximo,
ou do atual, no anterior, anterior, anterior.
Então, pra eu poder ter acesso a ele,
eu tenho que utilizar esses amarramentos aqui.
Se esses amarramentos não acontecerem, depois eu não consigo localizá-lo.
Se eu não consigo localizá-lo, daí eu não consigo deletar.
Por isso que esse código quando estava fora aqui, tá,
ele era um potencial risco.
Por que que ele era um potencial risco, gente?
Eu insisto.
Porque você pode ter uma alocação dinâmica, e o if não ser aprovado,
e depois você não amarrar ele com próximo nem anterior.
Porque pra amarrar com próximo e anterior
esse if, aqui, que tá em vermelho agora, ele tinha que ser aprovado.
Nos nossos casos de execução, tá,
o if era sempre aprovado.
Então, não tem problema nenhum,
mas, insisto, se o if não fosse aprovado poderia ter problema.
É por isso que tem esse ajuste agora feito aqui, tá,
e essa discussão que eu tô fazendo com vocês.
Muito bem.
Agora, tá melhor, tá mais refinado nosso código, tá.
A gente garante que só vai alocar memória
quando tiver as condições apropriadas para.
São essas condições aqui.
Daí a gente aloca. Faz o Elemento Aluno alocado cuidar do Aluno,
e faz as amarrações de próximo e anterior e etc,
nesse âmbito aqui.
Ali no else, tá.
Eu melhorei também, aqui, ao nível de mensagem,
e eu testo se o ponteiro é diferente de nulo.
Se é diferente de nulo, isso significa que daí o Aluno não foi incluído porque
ou porque não foi aprovado e deveria ter sido essa condição primeiro aqui, ó.
Agora, se o pontelo...
Perdão. Se o ponteiro não é diferente de nulo, ou seja, ele é igual a nulo
então é porque o ponteiro é nulo e não pode ser incluído.
Eu coloco outra mensagem pro usuário aqui
e até posso melhorar o texto da mensagem se for o caso, aqui dentro, tá.
Então, eu rogo que vocês vão lá no código de vocês, na versão de vocês, tá,
e façam essa melhoria que eu tô indicando aqui nesses slides.
Inclusive, reflitam sobre o que eu falei, com atenção, tá,
pra deixar isso bem sedimentado na cognição de vocês.
Muito bem.
Isso considerado, o aposto considerado,
aqui então, se aqui está a função incluaAluno
que foi melhorada ali, à luz da discussão agora feita,
ainda a gente tem o listeAlunos
e o listeAlunos2 que estão expostos, esses que vocês já conhecem.
Aqui, nós temos na classe Principal
na função Executar, nós temos a chamada...
Inclusive eu tô com dois Executar aqui.
Certo. Esse aqui é o Executar usual,
e esse aqui é o Executar com teste, tá.
Como eu tô com dois Executares aqui, eu vou manter um só.
Está aqui.
Então, tá aqui, o liste... o Executar que chama o ListeAlunosDisciplina.
Tá ali, ó. Eu posso chamar os Alunos listados em Metodos2_2007.
e em Computacao2_2007.
E como vocês tão vendo, depois das mensagens,
eu faço ainda um pequeno teste aqui,
pra ver se alterar o nome do triplo A
se nas listas onde ele está
contemplado, se essa alteração vai ocorrer.
Ela vai ocorrer, porque nas minhas listas,
com o código que eu fiz, eu não estou inserindo clone do triplo A
eu estou inserindo o endereço do triplo A.
Então, quando eu navegar naquelas listas, vou tá acessando o triplo A. no final das contas,
aonde, naturalmente, vai acessar as informações mais recentes.
Isso considerado, tá, como prefácio dessa aula,
vamos avançar agora do slide 7 para o 8,
aonde tem uma reflexão muito importante,.
que ela começa do ponto de vista estético, mas ela é mais profunda.
Ela entra na coesão e no desacoplamento.
Olhando esse código em azul e, particularmente, o código em vermelho,
Lhes parece filosoficamente correto?
Eu quando eu olho o mundo real, eu olho uma Disciplina. A Disciplina
tem um pPrimeiro e tem um pAtual, ou ela tem uma Lista de Alunos?
Imagine você numa madrugada dando um, eventualmente, né, manutenção num código
seu, de anos atrás, ou de outrem
e você, de repente, tá em uma classe Disciplina e vê um pElAlunoPrim e um pElAlunoAtual, tá.
Vai levar uns minutos até você se localizar pra lembrar que isso aqui é uma lista encadeada.
Enfim, vai levar um instante de tempo pra você se localizar.
Por quê? Porque isso não é esteticamente interessante,
e também traz problemas técnicos,
do ponto de vista da reutilização de código,
ou seja, afeta coesão e desacoplamento.
Vamos lá.
Novamente, a gente quando faz orientação a objetos,
a gente tem que olhar o mundo real, né.
Como é que tá no mundo real a coisa?
Como é que é a Disciplina? A Disciplina tem um lista de Alunos?
Ah, tem uma lista de Alunos, ela não tem um pPrimeiro e pAtual.
Professor, mas eu ia implementar a lista por pPrimeiro e pAtual.
Ok. Uma coisa é a implementação outra coisa é como você tá enxergando
a classe Disciplina ela mesma.
Então, vamos pensar nos seguintes termos no próximo slide.
Slide 9.
Olhe só o que eu fiz aqui, gente.
Modelo, tá. Modelagem.
Olha o que eu tô fazendo aqui.
Eu continuo tendo a classe Disciplina.
Continuo tendo a classe Aluno.
A Disciplina é cursada por um ou mais Alunos.
Cada Aluno cursa uma ou mais Disciplinas numa relação n pra n.
Explica a existência da classe ElAluno.
Cada ElAluno ele vai tratar Aluno na lista,
mas olhe só o que mudou aqui.
Agora, a Disciplina não tem mais pElAlunoPrim nem pElAlunoAtual.
O que a Disciplina tem é o que ela tem que ter
que é uma lista de Alunos.
Inclusive, ela tá pública, aqui, tá. Depois é só deixar privado.
Pôr um menos ali.
E daí claro refletir sobre o código.
Então, veja,
agora você olha pra Disciplina
e você vê que ela tem uma lista de Alunos fica
esteticamente evidente, fica intuitivo.
Ah, legal. Sim, faz sentido.
A Disciplina tem uma lista de Alunos.
Inclusive, essa lista aqui. Essa lista de Alunos.
Tem o ObjLAlunos dessa Lista de Alunos que
permite realizar aquilo,
mas essa lista de Alunos não realiza a associação cursar sozinha.
Ela realiza em colaboração com o ElAluno.
E é por isso que a ListaAlunos, agora sim,
daí, no seu âmago, ela tem
um pElAlunoPrim e um pElAlunoAtual
que é ponteiro de ElAluno cada qual.
O que explica essa associação aqui, de Conhecer Primeiro Conhecer Atual, né.
E aí, o Elemento já vai continuar tendo o Conhecer Próximo e Conhecer Anterior.
Então, veja, toda aquela lógica de composição de lista
agora ela não tá mais dentro, imbricada
ela não tá mais inclusa de maneira não organizada,
como deveria, dentro da Disciplina.
Vejam, isso aqui é uma construção que a gente vem fazendo, tá. É evolutivo.
Então, a gente começou com uma solução simples e veio refinando ela.
Como não raro acontece em processos de amadurecimento.
A gente foi amadurecendo o código, tá.
Então, aqui, a gente eliminou
a confusão, entre aspas, da nossa solução inicial, tá.
Óbvio que foi uma confusão calculada, tá.
Pra gente poder fazer esse processo pedagógico,
mas aqui a gente eliminou essa confusão, essa entropia.
Então, se você olhar aqui
agora, a Disciplina
tudo que é referente à sua lista de Alunos ela terceirizou
pra uma classe apropriada chamada ListaAlunos,.
Então, tá aqui o objeto
ObjLAlunos, da classe ListaAlunos.
Inclusive, aqui, você tem um incluaAlunos, o listeAlunos e o listeAlunos2.
Todo aquele código de inclusão de listagem vai estar nessas funções aqui.
E essas funções lá,
simplesmente, vão chamar essas funções aqui,
de maneira muito organizada, muito límpida.
Isso fica bastante explícito
na hora que a gente olha o código que reflete esse modelo.
Próximo slide inclusive a gente começa a ver isso.
Tá aqui, ó.
Disciplina.
Até eu salientei o código aqui, tá.
ObjLAlunos do tipo Lista Alunos.
Olha a ListaAlunos.
ListaAlunos agora, aqui, tem pElAlunoPrim e pElAlunoAtual
ponteiros de Aluno cada qual.
Se você olhar aqui eu tenho a construtora ListaAlunos.
Tem dois parâmetros, né. O número de Alunos
e um char aqui que é o nome da Lista.
Pode ser "Lista da Disciplina 'tal'".
Enquanto a Disciplina aqui, por exemplo, pode ser, sei lá eu, "Técnicas de Programação"
aqui a vai ser então "Lista da Técnicas de Programação"
aqui nesse vetor de caracteres vindo por parâmetro.
Eu não sei se já falei em slides anteriores, abrindo um parênteses,
que alguns compiladores em C++ mais recentes tão reclamando
quando você coloca aqui só um 'char', tá.
Ele pede que você coloque um const na frente.
Se ele reclamar que não tá reconhecendo char* ou char[],
aí você coloca um 'const' na frente
e ele resolve a questão.
Tá, mas fechando o parêntese e voltando ao ponto.
Então, o que acontece aqui? Eu tenho a construtora, tenho a destrutora
e agora eu tenho o algoritmo de inclusão e de listagem.
É aqui dentro que estão os algoritmos, naturalmente,
porque aqui que estão os ponteiros pElAlunoPrim e pElAlunoAtual.
E lá, nesses caras aqui,
o incluaAluno, por exemplo, ele vai pegar o parâmetro, e, simplesmente repassar pra esse cara ali.
ObjLAlunos.incluaAluno, repassando obviamente o parâmetro.
Inclusive, a gente vai discutir isso aqui, já aqui nos próximos slides,
tudo isso que eu tô falando.
Se aqui a gente tá vendo o ListaAlunos.h,
vamos ver o ListaAlunos.cpp no próximo slide.
Tá ali, ó.
ListaAlunos ele recebe o número de alunos.
Tem a contagem de alunos.
O pElAlunoPrim e o pElAlunoAtual, naturalmente, recebe nulo.
O parâmetro n alimenta o atributo nome.
Aqui está a destrutora com a lógica de desalocação usando delete, já discutido na aula anterior.
Só que agora, obviamente, no âmbito da classe ListaAlunos
não mais lá, imbricado, né,
incrustado dentro da classe Disciplina.
Agora organizado dentro da classe ListaAlunos.
Aonde deve estar.
E aqui o incluaAluno cumpre aquela lógica que a gente falou, né.
Ora, se eu corrigi, lá, o código naquela feita.
Aqui não vai ser outramente.
A gente já vai fazer aqui, em tempo de execução,
até para sensibilizá-lo a respeito.
Tá aqui o código agora, no lugar apropriado, né.
À luz da discussão feita no início ali, aliás,
não necessariamente no início, mas um pouco depois do início dessa exposição.
E aqui, professor, também vamos corrigir? Vamos, não tem problema, a gente corrige tudo.
Tu vem aqui, coloca o if aqui.
Olha que interessante, aqui eu já estou usando o cout
não o printf igual eu fiz na outra solução.
Inclusive, lá naquela solução eu já deixava o indicativo lá,
pra utilização de cout.
Aqui, você pode colocar as suas chaves.
Uma coisa que é fundamental, pessoal,
que eu imagino que vocês já observaram intuitivamente nos meus códigos,
que tudo é muito identado.
Isso facilita organização de código, elegância.
É uma coisa que facilita muito a comunicação, tá.
Quanto mais elegante você é,
e isso não significa soberbo, elegância, inclusive, tem muito a ver com simplicidade
você comunica melhor o que você quer comunicar.
O código obviamente que ele comunica também, tá.
Ele conta algo. É uma linguagem, né.
E aqui tá o else, tá, aonde eu posso colocar
a mensagem pro usuário de maneira um pouquinho mais elegante
pra ele saber o que tá acontecendo.
Por mais que ele seja um código extremamente pedagógico,
nada impede de a gente ser elegante, aqui, aonde precisa ser.
Aqui eu tô precisando de espaço,
então como eu tinha deixado uns espaços de backup lá,
podemos utilizá-lo.
Esse espaço, com certeza, vai ser útil.
E eu venho aqui
eu vou usar esse cout daqui
pra evitar muito retrabalho.
Ponteiro nulo.
"Ponteiro está nulo".
Finalizando aqui pra não deixar rastro.
Aqui, aparentemente, eu estou com uma chaves a mais.
Se eu não me equivoco. Não, não me equivoco.
Estou sim com chave a mais, estava aliás,
e agora não estou mais, tá.
Então o código agora ficou corrigido
e além de estar corrigido ele está no local certo.
Está na classe ListaAlunos que é da sua alçada.
Não está numa classe Disciplina ou outra classe.
Imaginem vocês que eu precisasse ter uma lista de Alunos dentro de Departamento.
Posso... posso ponhar não posso?
Posso ter uma ListaAluno também dentro da própria Universidade.
Aí, eu vou ter que ter uma...
eu ia ter que ter um algoritmo desse...
Se eu não tivesse a ListaAlunos
eu ia ter que ter um algoritmo desse
imbricado, incrustado dentro da Disciplina,
dentro do Departamento e dentro da Universidade.
O mesmo código,
similar e repetido em vários lugares.
Por quê? Porque eu não teria organizado bem o meu modelo.
Isso é um pepino.
Quando você tem códigos que são a mesma coisa repetidos em lugares distintos,
isso é mal sinal.
Entre aspas, como dizem, smell bad, cheira mal.
Significa que o seu modelo provavelmente tá com problema de acoplamento.
Não tá coeso e desacoplado o suficiente.
Legal.
Acho que é isso que eu tinha pra comentar com relação a esse slide e ajuste pra ser feito.
Obviamente depois no código de vocês, lá nas versões de vocês,
vocês vão fazer esses ajustes que eu fiz aqui em tempo de execução.
Incluindo substituir os printfs eventuais que sobraram, tá, pra cout.
Aqui a listagem, tá,
que é o mesmo código que tinha antes e detalhe
que agora ele tá no local certo, tá.
Está dentro do ListaAlunos.
Aqui eu tô fazendo um aterramento
um pouco de perfeccionismo, tá,
porque logo em seguida eu já uso o ponteiro, então,
há quem diga que isso é desnecessário, tá.
Mas existe aquele mantra,
se você cria um ponteiro, primeiro aterra ele.
Isso antes de usá-lo.
Eu tô seguindo o mantra à luz de qualquer crítica de exagero.
Os ponteiros aqui tão aterrados tanto agora na função de inclusão
quanto na função de listagem,
os ponteiros são criados de maneira temporária pros fins dados.
Se você olhar agora a classe... vou voltar pra classe Disciplina
Tá aqui o Disciplina.h que a gente já tinha visto.
Tá aqui o respectivo .cpp.
Vejam que interessante.
A Disciplina agora, insisto,
não tem mais código incrustado aqui, né,
colocado a fórceps dentro da Disciplina
e ela tem sim algo elegante, ela tem o ObjLAlunos.
ObjLAluno da classe ListaAlunos.
Se você olhar aqui o incluaAluno que recebe o endereço de um Aluno supostamente
ele vai simplesmente repassar isso pra sua lista incluir.
Na listagem, ele vai pedir pra sua lista fazer a listagem,
seja do início pro fim, seja do fim pro começo,
respectivamente, na função listeAlunos e depois na função listeAlunos2.
Então, veja, pessoal, que agora o modelo fica elegante.
Se vocês me permitirem voltar um pouquinho aqui no Diagrama de Classes, tá.
É um modelo que respeita desacoplamento.
A lista está desacoplada de outras classes.
Ela existe por ela mesma.
E, aqui, a hora que eu preciso fazer com que a Disciplina
utilize o ListaAlunos
eu crio um objeto ObjLAlunos aqui,
mantendo a coesão apropriada.
Então, ficou bastante elegante, bastante decente nosso modelo,
conforme eu gostaria
que os códigos de vocês sempre chegassem a ter
chegassem respeitando coesão e desacoplamento.