--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/eaed219a-14f4-4a75-8bfd-3e823a4a7655n%40googlegroups.com.
Olá! Acho que no início o ideal é aprender a linguagem que tiver os materiais (tutoriais, livros, cursos) que você achar mais acessíveis. C# tem muito conteúdo bom e bem escrito, mas pode ser JavaScript, Java, Python, Go... O importante é começar com algo que facilite o aprendizado em algoritmos e estrutura de dados. Depois que você ganhar mais confiança, aí sim faz sentido pensar melhor para onde quer direcionar sua carreira.
C é sempre uma linguagem boa para aprender, porque ela ensina bastante sobre gerenciamento de memória e sistema operacional, sem ser tão complexa quanto C++. Mesmo que você nunca trabalhe diretamente com ela, é um conhecimento valioso.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKcXGkkAh25EKzpgYNKKetC_-jgZx9y6VvE1SCpiFwo5jTmqiQ%40mail.gmail.com.
Olá!!
Sou professor de Linguagem de Programação e Estrutura de
Dados desde 1998.
Eu diria que, para entendimento, apenas isso, poderia ser
qualquer linguagem. No entanto, como professor dessas disciplinas,
prefiro trabalhar com a Linguagem C. Já trabalhei bastante com
Pascal, uma linguagem simples e que permite o entendimento das
estruturas de dados, mas, infelizmente, foi retirada da grande
maioria das universidades.
Não sou a favor de linguagens que utilizam Funções/Métodos
Prontos, como C#, Java e python, para implementação de estruturas
como Listas Encadeadas (pilha, fila e listas), além de estruturas
mais complexas. Esse tipo de linguagem é boa para quem já tem o
domínio, já entende os processos de alocação de memória etc. Para
quem está iniciando, acho que seria importante entender como e
quando alocar memória e liberar memória, ou seja, criar a própria
função para isso. Portanto, C e Pascal são ótimas para esse fim.
Para o entendimento e implementação de muitas dessas estruturas, aconselho o livro do Thomas Cormen (Algoritmos: Teoria e Prática), pois apresenta pseudocódigos.
Não esqueçam que, sem a Linguagem C não existira: python,
lua, Java, entre outras.
Att.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/6aa07dcd-316b-4596-b20e-47d661e9b1abn%40googlegroups.com.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7PvoqMbv%3DJc8s3n6H6_NHrgz6aYJTNRVb3D16t_kgCHoywnQ%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAJcuyxHDuEvEdyp274TviRMJYerwNjJaFAmDOpc7rOb4naBAaw%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CACWmytnUBN1kchmSv8yAijKRD_vWOfaVFSyvu4XqcdEJQfcDUA%40mail.gmail.com.
Aí vem aquela discussão: colocar getters e setters para acessar membros privados de classe é uma boa abordagem ou não?
On Wed, 14 May 2025 at 06:36, Rafael Dias <rdme...@gmail.com> wrote:Aí vem aquela discussão: colocar getters e setters para acessar membros privados de classe é uma boa abordagem ou não?Se é um membro privado da classe, então você tem que criar o get/set para conseguir acessar
de fora da classe, ou seja, neste caso não é uma questão de estilo, mas uma necessidade.
E qual é a solução? Siga o princípio "Tell, don't ask". Não pergunte para o objeto "dar os dados" para você fazer algo; dê algo e mandeele mesmo (o objeto) passar seus dados.
At.te.----fx
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb9SeYud-654P697ekU_5efmgeJMVWi-K6%3DfTjyQsm%3Djcg%40mail.gmail.com.
On Wed, May 14, 2025 at 8:43 AM Thiago Adams <thiago...@gmail.com> wrote:On Wed, 14 May 2025 at 06:36, Rafael Dias <rdme...@gmail.com> wrote:Aí vem aquela discussão: colocar getters e setters para acessar membros privados de classe é uma boa abordagem ou não?Se é um membro privado da classe, então você tem que criar o get/set para conseguir acessar
de fora da classe, ou seja, neste caso não é uma questão de estilo, mas uma necessidade.Quem disse? Um objeto é pra ser uma "caixa-preta". Se você cria uma classe e coloca métodos get/set para cada atributo, o objetodeixa de ser uma "caixa-preta".
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7Pvops1fkZOrqGD0bQWYY5uwmRqJj2__ZqjX%3DcYL%3DNrmwqkg%40mail.gmail.com.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7Pvops1fkZOrqGD0bQWYY5uwmRqJj2__ZqjX%3DcYL%3DNrmwqkg%40mail.gmail.com.
Pessoal,Como o Thiago bem disse, métodos get/set diretos para cada atributo quebra a encapsulação. Mas tem alguma fonte de informação que diga explicitamente isto? Livro ou artigo? Vídeo no Youtube não vale.At.te.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/ba32cb26-d006-41b1-bb45-e9befa99651an%40googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb-rHEL2we8Shgf4hCHEqPbvLq6ZArKYYXHXVB5s7L0U1g%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKG6imfWJypxyoamdaKffFSs5DuTKjYtS2ib7uJ%3Dxt5HkhvvkQ%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb_SdfAMgkgZsJu%2BCbqkrzfUadDukRuDRbsPbuYmjUkhiA%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb82%3DgCQoVveieP-oiS%2BDwSwP86ifTfgbqBRCQjedsUNdg%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CACx3Z1UzHYDn1MK4r%2Bh%2BZY9B-T2D4z%3Dp2-atgkv5u-G%3Dep4%2BOw%40mail.gmail.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/4ecb3cee-05c8-4e28-96b3-9194ab4292b7n%40googlegroups.com.
Pior q não lembro de nenhuma fonte "forte" sobre isso.
Cai muito em coisas que muitas vezes são subjetivas.Eu acabo fazendo get e set mesmo no modo básico inline que simplesmente atribui, mas vai naquela, se um dia precisar por alguma validação não quebra todo mundo que chama.
Mas cai naquela: não é muito diferente de deixar o atributo público, mas depois se precisar validar ou restringir, só mudar para private e por o getter e setter e corrigir os erros de compilação e outros...
Cai muito em coisas que muitas vezes são subjetivas.Eu acabo fazendo get e set mesmo no modo básico inline que simplesmente atribui, mas vai naquela, se um dia precisar por alguma validação não quebra todo mundo que chama.Eu *NUNCA* faço métodos set. Se quiser "setar" alguma coisa no meu objeto, que o faça pelo construtor. E o porquê disso? Procuro criar meus objetos como sendo imutáveis. Se você colocaum método set, ele deixa de ser imutável.
Ah sim, no caso vc trabalhando com objetos imutáveis, estes ainda não conseguo aderir bem. Eu sempre faço aqui (a não ser que seja um código sem exceptions, como quando você pega um embarcado) tudo que é vital tem tem que ser inicializado no construtor. Mas eventualmente acaba tendo algum setter para atualizar alguma coisa.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb9jcgNHEr7S3VT1%2BUEw9mzMugY-d_a%3D7Yiv8PFE5dCfQQ%40mail.gmail.com.
No caso você está falando de fazer um objeto imutável, como strings em C# e Java. Eu nem sempre me sinto confortável com isso.
POr exemplo, muitas vezes tem um objeto que representa um recurso (tipo, uma venda mesmo) e você tem um campo "observações" que é só uma string que o usuário atualiza de tempos em tempos, dai vai um setter....
Agora de não conseguir setar no construtor, hoje só costumo ter esse problema no construtor nos embarcados que não tem exceção, então se eu validar no construtor e der problema, como não posso dar throw, tenho duas opções:
- Cria um estado de erro no objeto e depois de construir checar se ele é valido
- FAz via setter ou um método init que retorna erro se der problema (a solução que prefiro hoje)
Este tópico esta parecendo Java nos anos 2000, sobre OOP e boas práticas.
Não existe uma regra geral que diga que você não deve lançar exceções
no construtor.
Geralmente, até por uma questão de performance, os objetos são mutáveis.
Existe funções que mudam o estado do objeto não sei se você esta considerando elas
como "set" ou não.
Por exemplo, no vector tem um reserve. Poderia ser set_capacity(), ou seja, no fundo
tudo são dados e funções que alteram o estado destes dados.
On Mon, May 19, 2025 at 2:33 PM Thiago Adams <thiago...@gmail.com> wrote:
Este tópico esta parecendo Java nos anos 2000, sobre OOP e boas práticas.OOP e boas práticas é atemporal e independente de linguagem, IMHO.Não existe uma regra geral que diga que você não deve lançar exceções
no construtor.Não, não existe, mas o construtor é sobre a criação de um objeto e esta deve ser feita da maneira mais simples e rápida possível. Se você está lançando alguma exceção durante a construçãode um objeto, significa que ele está fazendo mais coisas do que deveria.
Geralmente, até por uma questão de performance, os objetos são mutáveis.Quem disse que os objetos imutáveis não são performáticos? Além disso, é melhor deixar para verificar a performance quando a performance começar a ser um problema.Existe funções que mudam o estado do objeto não sei se você esta considerando elas
como "set" ou não.Elas não deveriam mudar o estado do objeto. Mas veja que podem mudar o estado daquilo que um objeto representa, como uma tabela ou arquivo.
Por exemplo, no vector tem um reserve. Poderia ser set_capacity(), ou seja, no fundo
tudo são dados e funções que alteram o estado destes dados.Já configure o capacity no construtor. Se você está precisando ampliar um objeto que possui um vector já populado, então o que você precisa é de um outro objeto com o vector maior.
----At.te.--fx
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb_c7QTMfEC0%2BwNvYhPvhmsZbOcCO_KjU__W2Lea6joGJQ%40mail.gmail.com.
Ter um outro objeto vai ter precisar mais memória.
Ele poderia estar diminuindo a capacidade por exemplo.
Também pode ser que no constructor não se saiba a quantidade necessária.
Então acho bem difícil tentar generalizar um "guideline" para isso.
Quando os argumentos são inválidos, não seria melhor lançar exceção no construtor e parar a execução o quanto antes?Assim há uma garantia que o objeto, quando criado, está em um estado válido.
On Mon, May 19, 2025 at 12:01 PM Bruno Sanches <bcsa...@gmail.com> wrote:No caso você está falando de fazer um objeto imutável, como strings em C# e Java. Eu nem sempre me sinto confortável com isso.Por quê?
POr exemplo, muitas vezes tem um objeto que representa um recurso (tipo, uma venda mesmo) e você tem um campo "observações" que é só uma string que o usuário atualiza de tempos em tempos, dai vai um setter....O objeto é imutável, mas aquilo que ele representa, pode ser mutável, como por exemplo um arquivo ou uma tabela de banco de dados. Não há problema nisso.
Agora de não conseguir setar no construtor, hoje só costumo ter esse problema no construtor nos embarcados que não tem exceção, então se eu validar no construtor e der problema, como não posso dar throw, tenho duas opções:Construtor não é para ter código além de atribuições. Se você precisa validar algo, faça a validação em algum método. C++ nas versões recentes permite criar funções lambda? Se sim, você até pode criar uma no construtor, mas a*execução* fica a cargo de algum método.
- Cria um estado de erro no objeto e depois de construir checar se ele é validoEu só verifico que ele é válido na execução de algum método. Inclusive, construtor não é para lançar exceções, vide meu comentário acima.
- FAz via setter ou um método init que retorna erro se der problema (a solução que prefiro hoje)Não cria um objeto imutável e ainda por cima coloca acoplamento temporal. Essa solução também não me agrada.
Quando os argumentos são inválidos, não seria melhor lançar exceção no construtor e parar a execução o quanto antes?Assim há uma garantia que o objeto, quando criado, está em um estado válido.
Ele poderia estar diminuindo a capacidade por exemplo.Aí então você quer um outro objeto com menor capacidade.
Quando os argumentos são inválidos, não seria melhor lançar exceção no construtor e parar a execução o quanto antes?Assim há uma garantia que o objeto, quando criado, está em um estado válido.Mas quando é que você tem um objeto inválido? E se ele for só parcialmente inválido? Talvez você nem use esse "objeto inválido". Deixe para descobrir se ele éinválido ou não quando for usá-lo e não quando for criá-lo.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKG6imeuSN1v42z5Lgr6vQCtO61nYNMpnkPcJ_sFaUCZ1ikS_w%40mail.gmail.com.
Hábito mesmo, depende muito do contexto, mas na maioria dos casos é mais fácil ter um objeto mutável.
Não são conceitos diferentes. Tentando ser mas claro: existem casos de instâncias imutáveis. O melhor exemplo é string e data em C#:String str = "ola pessoal";Se eu precisar mudar ela, tipo:str = str + ", como vao vocÊs";O C# gera outra instância, o a instância original é imutável. Isso você pode fazer em C++ também.
Não concordo. Construtor faz validação sim. Até mesmo em conceito básico do C++ um RAII você vai ter alguma validação. Se vai ter uma classe arquivo, ela vai fazer um fopen vai validar se abriu o arquivo ou não. Se não conseguiu vai ter que dar throw no construtor.
Sempre garantir que a partir do momento que seu objeto foi construído, ele é válido.
Pq não? Não tem outro jeito de construtor reportar erros, a não ser ter um estado de erro, mas dai prefiro ter um método init.
Eu utilizo quando não tenho opção de fazer algo no construtor e validar.
O fato é: não existe resposta única para nenhuma das questões. Depende muito do contexto, de como quer blindar o código e o quanto quer complicar as coisas.
Date dt{2025, 2, 31}; //deveria dar um throw pois não existe 31/2/2025....muitas linhas depois:if(dt.IsValid()){//faça o q tem q fazer?}Isso vira um inferno até alguém esquecer de colocar o if e o código vira um campo minado....
essa do if, é real, faz o throw no construtor, é bom pra manter a equipe fora do hospital psiquiátrico kkk
--At.te.--fx
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb8Q0L_JhvViPLJG9s4ia%3DovX%2B8mEA996b3UkwevUHKNyw%40mail.gmail.com.
On Mon, May 19, 2025 at 5:51 PM Bruno Sanches <bcsa...@gmail.com> wrote:Hábito mesmo, depende muito do contexto, mas na maioria dos casos é mais fácil ter um objeto mutável.Pesquise sobre as vantagens de ter um objeto imutável e mude seu hábito. E não estou falando sobre concorrência. Thread-safe é consequência de ter um objeto imutável, não a sua razão.
Não são conceitos diferentes. Tentando ser mas claro: existem casos de instâncias imutáveis. O melhor exemplo é string e data em C#:String str = "ola pessoal";Se eu precisar mudar ela, tipo:str = str + ", como vao vocÊs";O C# gera outra instância, o a instância original é imutável. Isso você pode fazer em C++ também.Sim, muitas linguagens fazem isso. E qual o problema?
Não concordo. Construtor faz validação sim. Até mesmo em conceito básico do C++ um RAII você vai ter alguma validação. Se vai ter uma classe arquivo, ela vai fazer um fopen vai validar se abriu o arquivo ou não. Se não conseguiu vai ter que dar throw no construtor.Você faz o fopen() quando constrói o objeto? Eu prefiro fazer quando vou usar o objeto, não quando vou construí-lo.
Sempre garantir que a partir do momento que seu objeto foi construído, ele é válido.Onde você viu isso? Tem alguma referência?
Pq não? Não tem outro jeito de construtor reportar erros, a não ser ter um estado de erro, mas dai prefiro ter um método init.Porque os construtores foram feitos para criar um objeto, não para validá-lo. Validação é uma ação e portanto deve ser feito em um método. Você não precisa de método init(). Use o seu construtor e seja feliz.Eu utilizo quando não tenho opção de fazer algo no construtor e validar.E quando você não tem opção de fazer no construtor? Pode dar um exemplo?Como eu disse antes, validação é para ser feita fora do construtor.
O fato é: não existe resposta única para nenhuma das questões. Depende muito do contexto, de como quer blindar o código e o quanto quer complicar as coisas.A minha POUCA experiência me diz que quando você cria objetos imutáveis e deixa para validar fora do construtor, você cria classes melhores (isto é, um código melhor), inclusive sem acoplamentotemporal.Faça testes. Experimente. Depois me diga o resultado.
Usando este tipo de design, você vai precisar validar o estado do objeto cada vez que um método é chamado (e repetir a mesma chamada de validação no início de todos os métodos).Validando no construtor (ou em cada método que modifique o estado do objeto), você não precisa fazer esta verificação extra, pois é garantido que o estado é válido.
Não estou dizendo que um design é melhor que o outro, mas cada um tem seus prós e contras.
essa do if, é real, faz o throw no construtor, é bom pra manter a equipe fora do hospital psiquiátrico kkkNão, a validação você faz fora do construtor, em um método, mas não precisa ser em um método com if para verificar se a data é válida (veja o exemplo que eu dei). Deixe para fazerisso quando for usar algum método do objeto.Usando este tipo de design, você vai precisar validar o estado do objeto cada vez que um método é chamado (e repetir a mesma chamada de validação no início de todos os métodos).Validando no construtor (ou em cada método que modifique o estado do objeto), você não precisa fazer esta verificação extra, pois é garantido que o estado é válido.Não estou dizendo que um design é melhor que o outro, mas cada um tem seus prós e contras.
Eu sei que tem vantagens, mas foram raros os casos que achei que valeria a pena...
Não falei que isso é problema. O que disse é: se é imutável, é imutável, não altera seu estado após a criação.
Sim e geralmente só construo objeto quando preciso dele. Se um objeto foi construído ele é válido. Para que vou fazer:File file{"arquivo.txt};//... linhas e linhas depois....if(!file.open()){throw runtime_error("nao foi possivel carregar o arquivo");}Muito mais simples:FIle file{"arquivo.txt"}; //não abriu já da throw e fim...
Aposto que você vai amar esse construtor: https://github.com/bcsanches/DCCLite/blob/master/src/BrokerLib/dcc/SignalDecoder.cpp#L28
Não me recordo, depois de mais de 20 anos trabalhando, tem coisas q nem lembro onde aprendi. Mas quase como RAII...
Pq tem q ser fora?
Já fiz muito código com validação fora do construtor nos ultimos 20 anos e sempre foi um inferno... isso a gente só usava em códigos sem exceções (comum em muita base de código C++ ser exception free, faz parte). Eu particularmente não gostava de exceções, mas depois que comecei a usar e praticamente só tenho throw no código em construtores, facilitou muito a vida, a base de código ficou muito mais simples.
Eu ainda sou da filosofia que exception é exception, tanto que no meu código hoje raramente tem um catch, pois se o erro é tratável, não deveria ser exceção, mas essa é outra discussão.... (e bem acalorada também).
Eu sei das vantagens de objetos imutáveis, mas nos projetos que tenho hoje em mãos, não consigo lembrar de nenhum caso onde valeria a pena pelo custo de código extra e pela própria arquitetura do sistema nao encaixa bem. TAlvez no dia q eu começar um novo projeto do zero (se é que isso vai acontecer), eu faça algumas experiências....
Usando este tipo de design, você vai precisar validar o estado do objeto cada vez que um método é chamado (e repetir a mesma chamada de validação no início de todos os métodos).Validando no construtor (ou em cada método que modifique o estado do objeto), você não precisa fazer esta verificação extra, pois é garantido que o estado é válido.Há maneiras de contornar isso. Você pode criar uma variável booleana atômica (como faz isso em C++?) e, dado que já fez a verificação uma vez, mudar o estado dessa variável. Ou podecriar um vector vazio. Depois de validar em um método, coloca algo nesse vector e verifica se ele contém algo. Se conter, é porque já validou.Se tiver alguma maneira melhor se se fazer isso, deixe-me saber.
Se você não concorda comigo, sem problemas. Muitos não concordam. Só digo o seguinte: experimente, teste, faça sua pesquisa e experimentação e DEPOIS me diga o resultado.
Exatamente!!! Essa questão de validar em toda chamada somente em casos muitos específicos e nem consigo pensar em um exemplo que isso faria sentido. Sem falar que se vocÊ realmente precisar validar algo toda vez que chamar um método do objeto, tem que ver se não vale o próprio método fazer a validação e retornar erro ( ou dar throw...)
E entramos naquela coisa: se eu para chamar um método de um objeto tenho que ficar validando o estado dele, o que exatamente ele esta encapsulando?
On Mon, May 19, 2025 at 6:39 PM Bruno Sanches <bcsa...@gmail.com> wrote:Eu sei que tem vantagens, mas foram raros os casos que achei que valeria a pena...Estou interessado nos casos que NÃO valeu a pena. Você poderia compartilhá-los conosco?
Sim e geralmente só construo objeto quando preciso dele. Se um objeto foi construído ele é válido. Para que vou fazer:File file{"arquivo.txt};//... linhas e linhas depois....if(!file.open()){throw runtime_error("nao foi possivel carregar o arquivo");}Muito mais simples:FIle file{"arquivo.txt"}; //não abriu já da throw e fim...Mas aí que está: e se você não abrir o arquivo? E se fizer um:file.filename() para consultar o nome dele? Ou outra operação que não necessitasse abrir o arquivo?
Além disso, você está realizando ações (execução de código) quando está construindo um objeto. Essa operação deveria ser a mais simples, leve e rápida possível.
Aposto que você vai amar esse construtor: https://github.com/bcsanches/DCCLite/blob/master/src/BrokerLib/dcc/SignalDecoder.cpp#L28Definitivamente, não faria desse modo. :)Não me recordo, depois de mais de 20 anos trabalhando, tem coisas q nem lembro onde aprendi. Mas quase como RAII...Não entendi o "Mas quase como RAII"
Pq tem q ser fora?Pelo motivo que eu disse acima. Mas porque ele não pode ser fora? :)
On Mon, May 19, 2025 at 6:42 PM Bruno Sanches <bcsa...@gmail.com> wrote:Exatamente!!! Essa questão de validar em toda chamada somente em casos muitos específicos e nem consigo pensar em um exemplo que isso faria sentido. Sem falar que se vocÊ realmente precisar validar algo toda vez que chamar um método do objeto, tem que ver se não vale o próprio método fazer a validação e retornar erro ( ou dar throw...)Mostrei em outro e-mail como contornar isso. E outra coisa: talvez você não precise validar TODO o objeto. Cada caso é um caso. Mas tem alternativas para isso.
E entramos naquela coisa: se eu para chamar um método de um objeto tenho que ficar validando o estado dele, o que exatamente ele esta encapsulando?Ué, está encapsulando o estado dele... ou não?
A melhor maneira de fazer isso é no construtor garantir que se ele terminou a execução o objeto está em um estado válido e nem método do objeto permite que ele chegue em um estado inválido. Não precisa ter boolean, não precisa ficar lembrando de checar boolean em todo método e nem de ficar invocando método para verificar se o objeto está em um estado válido antes de usá-lo. E não vai ter problema de concorrência pois o construtor só vai ser executado por uma thread.
Colega, já perdi as contas de quantas vezes fiz programas com objetos que tinha que terminar a inicialização depois do construtor. A long time ago, nessa mesma galaxia, exception era algo do mal proibido em muito sistema que trabalhei. Cansei de fazer classe com método Init e isso era um porre e sujeito a erros, não preciso testar. Mas se precisar fazer, sei como fazer.
Eu a muito tempo aprendi: programadores erram, faça código que se proteja de seus próprios erros. TEr que fazer inicialização de algo em mais de uma etapa está sujeito a erro e até onde me lembro, um dos princípios da OO era justamente encapsulamento. Ao meu ver ter que chamar um método init ou algo do tipo para usar um objeto é quebra de encapsulamento, pois você tem que saber como ele funciona internamente para tal.
Esses tempos mesmo na acalorada apresentação lá de um módulo do Rust que deu uma briga linda de ver sobre mudar uma interface de um driver do linux era justamente por causa disso. Era uma interface complicada e fácil de errar no uso. Boas APIs são fáceis de usar da forma correta e difíceis de usar da forma errada.
A melhor maneira de fazer isso é no construtor garantir que se ele terminou a execução o objeto está em um estado válido e nem método do objeto permite que ele chegue em um estado inválido. Não precisa ter boolean, não precisa ficar lembrando de checar boolean em todo método e nem de ficar invocando método para verificar se o objeto está em um estado válido antes de usá-lo. E não vai ter problema de concorrência pois o construtor só vai ser executado por uma thread.Você tem um bom argumento.Mas ainda creio que a finalidade do construtor não é essa. Construtor é para construir um objeto. Verificação são outros 500. Construtor disparar uma exceção me soa MUITO estranho.
Colega, já perdi as contas de quantas vezes fiz programas com objetos que tinha que terminar a inicialização depois do construtor. A long time ago, nessa mesma galaxia, exception era algo do mal proibido em muito sistema que trabalhei. Cansei de fazer classe com método Init e isso era um porre e sujeito a erros, não preciso testar. Mas se precisar fazer, sei como fazer.Go não tem exceções. Não estou dizendo que isso é bom ou ruim, mas eles devem ter os argumentos deles, né?
E nenhum momento eu disse pra ter um método init().
Eu a muito tempo aprendi: programadores erram, faça código que se proteja de seus próprios erros. TEr que fazer inicialização de algo em mais de uma etapa está sujeito a erro e até onde me lembro, um dos princípios da OO era justamente encapsulamento. Ao meu ver ter que chamar um método init ou algo do tipo para usar um objeto é quebra de encapsulamento, pois você tem que saber como ele funciona internamente para tal.Não disse para você ter um método init() ou coisa do gênero. E mesmo que tivesse, não sei como ele quebra a encapsulação. Eu sei que coloca acoplamento temporal, mas quebra de encapsulação, não vejo. Você poderia explicar melhor?
Esses tempos mesmo na acalorada apresentação lá de um módulo do Rust que deu uma briga linda de ver sobre mudar uma interface de um driver do linux era justamente por causa disso. Era uma interface complicada e fácil de errar no uso. Boas APIs são fáceis de usar da forma correta e difíceis de usar da forma errada.Eu não vi como dar errado da forma que eu falei. Como seria?
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/52a80319-23fd-4eea-af5e-9f41d6a1da65n%40googlegroups.com.
Qualquer um, vamos pegar uma classe para armazenar um Vetor (matemático, não conteiner de dados).Vector point {5, 0, 5};Vector deslocamento{0, 0, 1};point += deslocamento;Mais simples que:point = point + deslocamento;
Mas para que eu vou instanciar uma classe para manipular o arquivo se eu não for abrir ele para ler dados ou escrever dados?Se eu só preciso do nome dele armazeno numa string ou no std::path
Pq? Não existe essa regra. Um vector pode ser bem pesado no construtor se você alocar algo grande....
Voce sabe o que é RAII?
Ele pode, mas veja o outro email... complica mais.... e o encapsulamento acaba...
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb-zAnOs6Hs1uhkhg%2BBf00Gjb-pH908ZLs7Hv1%3D6DftaiA%40mail.gmail.com.
O construtor dispara uma exceção pois é a única forma que ele tem de reportar erro e garantir a integridade do objeto. LEmbre-se que se você alocar dinamicamente, a não ser que você desligue, o new vai dar throw se não tiver memória e nem vai invocar o construtor.
Com certeza, mas GO tem classes? Só fiz um hello world em go a muito tempo...
Ok, mas se eu não vou validar a inicialização do objeto, como vou inicializar ele?
Veja no outro email se ficou claro isso. Se nao tento explicar de outro jeito
No outro email, veja o exemplo do arquivo :P
Acho que perdi essa parte, quando vocÊ fala do boolean? Se sim o problema só mudou de lugar...
Se para chamar o método X de um objeto, eu devo saber que ANTES de chamar ele devo invocar o método Y, ao meu ver quebrou o encapsulamento. Pois eu tenho que saber isso sobre o objeto antes de usar.
E se eu tiver que chamar Y somente em alguns casos e outros não, pior ainda...Um exemplo simples:File f;//...codigos qualquer....if(!f.open("arquivo.txt)){//deu erro, faça o tratamento....}char buffer[100];f.read(buffer, 100);Veja, eu tenho que saber, mesmo no caso banal e óbvio, que antes de ler o arquivo, preciso abrir ele.
Mas qual o sentido de ter a instância de um objeto que encapsula um arquivo se nao posso ler ou escrever nele?
Muito mais simples:File f{"arquivo.txt}; // se não deu throw, então o arquivo foi aberto e esta pronto para leitura e/ou escrita....
char buffer[100];f.read(buffer, 100);pronto. Muito mais simples (nao vamos entrar na discussão de que poderia ter um buffer overflow e tal no buffer... quis deixar a coisa simples)
Quando eh um construtor q ja ta recebendo dados pra instanciar, acho valido a validacaoTipo new date() e new date(1,1,1111)O segundo ja valida, o primeiro n
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/cf188be3-fb16-4bf4-b7a4-2f0be5d21e26n%40googlegroups.com.
On Mon, May 19, 2025 at 7:01 PM Bruno Sanches <bcsa...@gmail.com> wrote:Acho que perdi essa parte, quando vocÊ fala do boolean? Se sim o problema só mudou de lugar...Por que o problema só mudou de lugar? Não entendi. Poderia explicar melhor?Se para chamar o método X de um objeto, eu devo saber que ANTES de chamar ele devo invocar o método Y, ao meu ver quebrou o encapsulamento. Pois eu tenho que saber isso sobre o objeto antes de usar.
Essa thread virou mais assunto sobre o. “Reinvent Square Wheel Helper” pattern da PoG da desciclopedia …A regra pra todo programa e codigo é: pra existir tem que fazer sentido.
Nada impede o exemplo de setDay de uma hipotetiva classe Date mas… faz sentido? Muitas vezes eh o ego do programador querendo mostrar que “sabe fazer”…
Sobre ger/set 1:1 sem validacao, nao faz sentido criar codigo, eh mais facil acessar as variaveis direto. Se tem regra, eh outra historia
E usar visitors (Tell, dont ask) pode fazer sentido em classes tipo variant, onde a complexidade interna pode ser um impeditivo de ter um get/set eficiente, mas ser xiita e usar em tudo, tambem parece falta de bom senso
A minha opinião é que é melhor o ctor não falhar. Mas eu tiver que mexer em um fonte queja faz isso, e se fizer da maneira correta, então eh uma questao de estilo.
Nenhuma linguagem vai garantir que vc não pode chamar os métodos fora de ordem.
o encapsulamento permite pelo menos que o objeto se mantenha em um estado valido.
Tem como garantir.
Por exemplo, se vc fizer close antes de fazer open
basta vc retornar um erro e não mexer nada no estado da classe.
ou fazer um close e depois outro clone etc.
ou se fizer dois open etc..
Algo interessante de ler são as garantias fracas e fortes..
https://arne-mertz.de/2015/12/levels-of-exception-safety/
Isso cria um acoplamento, pois o objeto que inserir este também pode falhar e assim por diante.Um ctor default que nao falhar resolve. Se colocar os que falham ainda assim eh bom colocar um default. (tipo std::string)
> Meu intuito atualmente é atuar na parte back-end de projetos.Eu acho que essa parte da sua mensagem é chave. Não trabalho como desenvolvedor, mas acredito que seu objetivo tenha um grande peso na escolha da linguagem. E parece haver um consenso entre alguns colegas de que C# é promissor para backend no Brasil, então... :)Se fosse front-end, provavelmente JavaScript seria mais aconselhável e por aí vai.Sobre a mensagem do Leandro Cursino, tenho algumas dúvidas. :)>As IAs estão substituindo os programadores, então aprenda a construir soluções completas em vez de pequenas etapas com C ou qualquer outra linguagem.Mas não são as pequenas etapas que fazem a gente chegar lá? O que aconteceu com o "dividir para conquistar", baby steps, divisão de problemas em problemas menores? Como construir uma solução completa sem saber construir suas etapas?>As empresas querem desenvolvedores plenos que saibam trabalhar com MCP, RestAPI, Docker, AWS, Postgresql e muitas outras ferramentas.
>Não pense pequeno. Ficará desempregado.Tenho muitas dúvidas e nenhuma certeza. IA estão mesmo substituindo? MCP, Rest API, etc.. acho tudo isso muito fácil de entender para quem sabe programar, mas muito difícil para quem não sabe. Por exemplo, na minha opinião MCP é um JSON hypado, mas se a pessoa nunca usou JSON "na mão", vai se enrolar né? Talvez essa seja outra discussão, claro.. :)Abraços!rapaz... pra quem ta comecando e quer garantir o almoco/janta c# e ABAPEm sábado, 19 de abril de 2025 às 12:36:55 UTC-3, Flávio de A. e Silva escreveu:Olá!!
Sou professor de Linguagem de Programação e Estrutura de Dados desde 1998.
Eu diria que, para entendimento, apenas isso, poderia ser qualquer linguagem. No entanto, como professor dessas disciplinas, prefiro trabalhar com a Linguagem C. Já trabalhei bastante com Pascal, uma linguagem simples e que permite o entendimento das estruturas de dados, mas, infelizmente, foi retirada da grande maioria das universidades.
Não sou a favor de linguagens que utilizam Funções/Métodos Prontos, como C#, Java e python, para implementação de estruturas como Listas Encadeadas (pilha, fila e listas), além de estruturas mais complexas. Esse tipo de linguagem é boa para quem já tem o domínio, já entende os processos de alocação de memória etc. Para quem está iniciando, acho que seria importante entender como e quando alocar memória e liberar memória, ou seja, criar a própria função para isso. Portanto, C e Pascal são ótimas para esse fim.
Para o entendimento e implementação de muitas dessas estruturas, aconselho o livro do Thomas Cormen (Algoritmos: Teoria e Prática), pois apresenta pseudocódigos.
Não esqueçam que, sem a Linguagem C não existira: python, lua, Java, entre outras.
Att.
--
Prof. Dr. Flávio de Almeida e Silva
CV: http://lattes.cnpq.br/3625040770570963
Coordenador de Tecnologias na Educação - COTED
Universidade Tecnológica Federal do Paraná - UTFPR
Campus Francisco Beltrão
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/6aa07dcd-316b-4596-b20e-47d661e9b1abn%40googlegroups.com.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAM7p17NdYdj148%2BA25oR8J-6ZKKKPv4HD1512zfjvc9_8b7Xhw%40mail.gmail.com.
On Mon, May 19, 2025 at 8:43 PM Thiago Adams <thiago...@gmail.com> wrote:Tem como garantir.
Por exemplo, se vc fizer close antes de fazer open
basta vc retornar um erro e não mexer nada no estado da classe.
ou fazer um close e depois outro clone etc.
ou se fizer dois open etc..Mas aí é você que está garantindo, não a linguagem. O que você havia dito era a linguagem, certo?
On Mon, May 19, 2025 at 8:48 PM Thiago Adams <thiago...@gmail.com> wrote:Isso cria um acoplamento, pois o objeto que inserir este também pode falhar e assim por diante.Um ctor default que nao falhar resolve. Se colocar os que falham ainda assim eh bom colocar um default. (tipo std::string)Mas você passar um objeto como parâmetro de outro objeto já cria um acoplamento, não? Ainda não entendi a razão de não poder falhar.
Quanto ao construtor default, você se refere a construtor sem parâmetros? Se sim, aí o objeto teria que ser mutável, certo?
O problema do acoplamento é basicamente não ter um ctor vazio. Pois pode dificultar o uso deste objectoquando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.(Não me refiro a passado como parâmetro, mas sim sendo membro de outro objeto)
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
> Se sim, aí o objeto teria que ser mutável, certo?
sim
O outro motivo de não ter erros no ctor, na verdade é mais do que isso.Melhor ainda é não ter computação nenhuma, apenas ele coloca os membros do
objecto em um estado válido inicial. Motivo é a performance e ser "lazy" não faça agora o que
pode ser feito depois e que talvez nem venha a ser necessário.
On Mon, 19 May 2025 at 21:13, Fabrício Cabral <fabri...@gmail.com> wrote:On Mon, May 19, 2025 at 8:48 PM Thiago Adams <thiago...@gmail.com> wrote:Isso cria um acoplamento, pois o objeto que inserir este também pode falhar e assim por diante.Um ctor default que nao falhar resolve. Se colocar os que falham ainda assim eh bom colocar um default. (tipo std::string)Mas você passar um objeto como parâmetro de outro objeto já cria um acoplamento, não? Ainda não entendi a razão de não poder falhar.O problema do acoplamento é basicamente não ter um ctor vazio. Pois pode dificultar o uso deste objectoquando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.(Não me refiro a passado como parâmetro, mas sim sendo membro de outro objeto)
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
Melhor ainda é não ter computação nenhuma, apenas ele coloca os membros doO outro motivo de não ter erros no ctor, na verdade é mais do que isso.Quanto ao construtor default, você se refere a construtor sem parâmetros? Se sim, aí o objeto teria que ser mutável, certo?
> Se sim, aí o objeto teria que ser mutável, certo?
sim
objecto em um estado válido inicial. Motivo é a performance e ser "lazy" não faça agora o que
pode ser feito depois e que talvez nem venha a ser necessário.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7PvorHjnVmtwSuw%3DDyD9ZoLQspfXaPtKTBbBEr9unF_hScGg%40mail.gmail.com.
On Tue, May 20, 2025, 07:58 Thiago Adams <thiago...@gmail.com> wrote:On Mon, 19 May 2025 at 21:13, Fabrício Cabral <fabri...@gmail.com> wrote:On Mon, May 19, 2025 at 8:48 PM Thiago Adams <thiago...@gmail.com> wrote:Isso cria um acoplamento, pois o objeto que inserir este também pode falhar e assim por diante.Um ctor default que nao falhar resolve. Se colocar os que falham ainda assim eh bom colocar um default. (tipo std::string)Mas você passar um objeto como parâmetro de outro objeto já cria um acoplamento, não? Ainda não entendi a razão de não poder falhar.O problema do acoplamento é basicamente não ter um ctor vazio. Pois pode dificultar o uso deste objectoquando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.(Não me refiro a passado como parâmetro, mas sim sendo membro de outro objeto)
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
Por este motivo que existe a injeção de dependência, não? Assim, não há este tipo de acoplamento, o objeto já vem criado de fora da classe.Mas claro, aí começamos uma nova discussão...Melhor ainda é não ter computação nenhuma, apenas ele coloca os membros doO outro motivo de não ter erros no ctor, na verdade é mais do que isso.Quanto ao construtor default, você se refere a construtor sem parâmetros? Se sim, aí o objeto teria que ser mutável, certo?
> Se sim, aí o objeto teria que ser mutável, certo?
sim
objecto em um estado válido inicial. Motivo é a performance e ser "lazy" não faça agora o que
pode ser feito depois e que talvez nem venha a ser necessário.Bom ponto. Mas em casos onde o objeto é criado com membros inválidos, não é melhor mesmo saber disso, na maioria das vezes, assim que o objeto é criado?
Imagina criar um objeto com valores inválidos e descobrir num ponto futuro que ele foi mal construído. Pode ser necessário um rollback de outras operações, que teria sido evitado caso a verificação ocorresse antes.Mas claro, cada caso é um caso, certamente tem situações onde criar um objeto inválido e saber isso apenas depois não é um problema (inclusive por questões de performance), mas, na minha opinião, não seria a regra para todos os casos, e sim a exceção.
Bom ponto. Mas em casos onde o objeto é criado com membros inválidos, não é melhor mesmo saber disso, na maioria das vezes, assim que o objeto é criado?
Imagina criar um objeto com valores inválidos e descobrir num ponto futuro que ele foi mal construído. Pode ser necessário um rollback de outras operações, que teria sido evitado caso a verificação ocorresse antes.
Mas claro, cada caso é um caso, certamente tem situações onde criar um objeto inválido e saber isso apenas depois não é um problema (inclusive por questões de performance), mas, na minha opinião, não seria a regra para todos os casos, e sim a exceção.
Este estado "vazio" ainda tem que ser válido.Exemplo: o ctor sem argumentos da data poderia ser 1/1/1970.
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7PvopGw%3DvBKtKKD1FWKJcXwh4hO4BdXJzJ4iRd4fANY5Wd_g%40mail.gmail.com.
Entendi, tu defende sempre ter um construtor vazio que nunca falha e que permite inicializar/validar apenas quando necessário.
A vantagem de fazer tudo direto no construtor que é que a data nunca vai ser 1/1/1970, a não ser que esta seja realmente a data que tu quer, reduzindo a chance de bugs.
Mas daí voltamos nos casos onde o construtor vazio faz sentido existir e recomeçamos o loop :)
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7Pvop6i25u4dCOewq4DU48vYEWHEPc0f6Z6Te7AQ-VSE1gug%40mail.gmail.com.
On Mon, May 19, 2025 at 6:55 PM Bruno Sanches <bcsa...@gmail.com> wrote:Qualquer um, vamos pegar uma classe para armazenar um Vetor (matemático, não conteiner de dados).Vector point {5, 0, 5};Vector deslocamento{0, 0, 1};point += deslocamento;Mais simples que:point = point + deslocamento;Olha, meu cpp-fu tá meio enferrujado, mas pelo que eu entendi, você está mudando o valor de point, correto? Se sim, point não é imutável. Ainda não vi (ou não entendi) a diferença.
Mas para que eu vou instanciar uma classe para manipular o arquivo se eu não for abrir ele para ler dados ou escrever dados?Se eu só preciso do nome dele armazeno numa string ou no std::pathFoi só um exemplo. Além disso, você poderia querer validar o path do arquivo, sei lá...
Pq? Não existe essa regra. Um vector pode ser bem pesado no construtor se você alocar algo grande....Aí, então *talvez* você queira outra coisa, como criar o seu objeto e depois chamar um método load() para carregar essa coisa grande que você queira, não?
Voce sabe o que é RAII?Sei, só não entendi no contexto da sua frase.
Ele pode, mas veja o outro email... complica mais.... e o encapsulamento acaba...Não entendi porque a encapsulação acaba. Poderia explicar melhor?
On Mon, May 19, 2025 at 7:06 PM Bruno Sanches <bcsa...@gmail.com> wrote:O construtor dispara uma exceção pois é a única forma que ele tem de reportar erro e garantir a integridade do objeto. LEmbre-se que se você alocar dinamicamente, a não ser que você desligue, o new vai dar throw se não tiver memória e nem vai invocar o construtor.Eu acho que o caso do construtor disparar uma exceção quando não tem memória um caso BEM atípico, não é? Isso é comum de acontecer com você? Se sim, o que você faz nestes casos?
Com certeza, mas GO tem classes? Só fiz um hello world em go a muito tempo...E qual o problema de não ter classes?
Ok, mas se eu não vou validar a inicialização do objeto, como vou inicializar ele?Atribua os parâmetros que você recebeu aos atributos do objeto. Validação você faz depois, quando precisar, em algum método que for invocado ao objeto.
E se eu tiver que chamar Y somente em alguns casos e outros não, pior ainda...Um exemplo simples:File f;//...codigos qualquer....if(!f.open("arquivo.txt)){//deu erro, faça o tratamento....}char buffer[100];f.read(buffer, 100);Veja, eu tenho que saber, mesmo no caso banal e óbvio, que antes de ler o arquivo, preciso abrir ele.Então no caso acima, há uma quebra de encapsulação porque você teve que fazer um open() antes de um read()?Mas qual o sentido de ter a instância de um objeto que encapsula um arquivo se nao posso ler ou escrever nele?Depende do que faz o seu arquivo. É só ler e escrever?
Muito mais simples:File f{"arquivo.txt}; // se não deu throw, então o arquivo foi aberto e esta pronto para leitura e/ou escrita....Aqui você não apenas criou um objeto arquivo, como também já deu open() nele, certo? E se você quiser, sei lá, só ler a permissão (que não precisa de um open() antes), como seria?
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAP7Pvop6i25u4dCOewq4DU48vYEWHEPc0f6Z6Te7AQ-VSE1gug%40mail.gmail.com.
Com não tem diferença?point = point + deslocamento;
E cai no que o Thiago comentou no outro email, desempenho... ficar criando e destruindo objetos toda hora nem sempre é uma boa idéia...
Mas é um exemplo que não tem sentido. Para validar o path não preciso abrir o handle para o arquivo, o SO tem funções para checar se o arquivo existe.
E pq não vou fazer isso diretamente no construtor? Só consigo pensar em utilidade para isso hoje em casos de otimizações (mas você mesmo falou lá atrás que não devemos otimizar sem profiling, etc), mas em jogos era comum a gente fazer buffers de objetos (E ter tudo de forma estática e não dinÂmica), então como tínhamos re-uso de objetos, entrava essa situaçaõ do load (vc pegando um obejto do pool)
Você fazer validações e tudo mais no construtor, ao meu ver naõ deixa de ser uma forma de RAII
O que é encapsulamento? é o objeto esconder suas entranhas. O objeto tem uma interface, onde eu peço para ele realizar suas tarefas conforme minha necessidade. Só consigo pensar agora no exemplo do arquivo, uma classe que encapsula acesso a um arquivo para leitura e escrita. Não me interessa do ponto de vista de usuário da classe como ela internamente gerencia o acesso ao arquivo, como ela carrega ele, como ela manda os dados, isso é problema dela.O que me interessa é: eu instancio ela, passo o nome do arquivo que quero acessar e o caminho e ela me dá acesso a ele.Agora, se eu construo ela:File f{"arquivo.txt"};e depois:f.open();
Qual o sentido? Eu só quero ler e escrever no arquivo, então só vou instanciar o objeto para fazer isso, qual sentido de fazer um carregamento tardio?
E se tenho que chamar o load, antes de fazer leitura e escrita, quebrou o encapsulamento, pois pq preciso fazer isso?
Abrir o arquivo é problema da classe, não meu.
Claro, isso pensando em um caso de uso bem simples, tudo é discutível e existem n necessidades...
Pensando num caso bem simples onde fiz um classe só para ler e escrever num arquivo, sim.
Você tem funções específicas no SO para tal e não precisa necessariamente acessar o arquivo para isso: https://en.wikipedia.org/wiki/Single-responsibility_principle
On Tue, May 20, 2025 at 10:03 AM Bruno Sanches <bcsa...@gmail.com> wrote:Com não tem diferença?point = point + deslocamento;Sinceramente, a diferença é mínima. E eu (e muita gente, dá uma olhada na literatura) vai dizer que prefere point = point + descolamento porque é maislegível do que da outra forma.
E cai no que o Thiago comentou no outro email, desempenho... ficar criando e destruindo objetos toda hora nem sempre é uma boa idéia...Certo, mas aí você tem que avaliar quando não é, certo? Normalmente, imutabilidade é sim uma boa se não em todos, pelo menos na maioria dosobjetos da aplicação. Para descobrir quais não são, aí você tem que avaliar a sua aplicação. Um refactoring nestes (poucos) casos não é nada demais.
Mas é um exemplo que não tem sentido. Para validar o path não preciso abrir o handle para o arquivo, o SO tem funções para checar se o arquivo existe.Certo, só que você está pegando um exemplo e fazendo dele regra. Pense o contrário.
E pq não vou fazer isso diretamente no construtor? Só consigo pensar em utilidade para isso hoje em casos de otimizações (mas você mesmo falou lá atrás que não devemos otimizar sem profiling, etc), mas em jogos era comum a gente fazer buffers de objetos (E ter tudo de forma estática e não dinÂmica), então como tínhamos re-uso de objetos, entrava essa situaçaõ do load (vc pegando um obejto do pool)Motivos para não fazer diretamente no construtor:1. Quebra o paradigma declarativo da programação orientada a objetos.
2. Coloca muita funcionalidade que (talvez) nem seja usada para pelo objeto.
3. Diminui drasticamente o tempo de construção do objeto, que deveria ser feito de maneira simples e rápida.
4. Desloca a funcionalidade (inteligência) que deveria estar nos métodos.
--At.te.--fx
--
http://ccppbrasil.github.io/
https://twitter.com/ccppbrasil
[&] C & C++ Brasil - http://www.ccppbrasil.org/
Para sair dessa lista, envie um e-mail para ccppbrasil-...@googlegroups.com
---
Você recebeu essa mensagem porque está inscrito no grupo "ccppbrasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para ccppbrasil+...@googlegroups.com.
Para ver esta conversa, acesse https://groups.google.com/d/msgid/ccppbrasil/CAKUebb8TiE41%3D_eme-LrWYqaz2mtq3XCPymq02ChsjoA%2BgTv5w%40mail.gmail.com.
Subjetivo, ambos os casos... em C/C++ a gente se acostuma com += -=++ --...
refactoring nem sempre é trivial e vale a pena? ISso tem custo...
Você pode pensar o contrário. Se um programador meu abrir um arquivo para checar permissão ou simplesmente armazenar o nome dele e checar path, bato nele...
Ahm?
MAs se vc coloca a funcionalidade em outro ponto seu objeto já esta inchado...
Quem ditou isso?
Quem ditou isso? Pq?
Um copy e paste da wikipedia:
In class-based, object-oriented programming, a constructor (abbreviation: ctor) is a special type of function called to create an object.
It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.
A constructor resembles an instance method, but it differs from a method in that it has no explicit return type, it is not implicitly inherited and it usually has different rules for scope modifiers.
Constructors often have the same name as the declaring class.
They have the task of initializing the object's data members and of establishing the invariant of the class, failing if the invariant is invalid. A properly written constructor leaves the resulting object in a valid state.
Immutable objects must be initialized in a constructor.