Ajuda para escolher uma linguagem de programação

280 views
Skip to first unread message

Allan Souza

unread,
Apr 17, 2025, 6:26:20 PMApr 17
to ccppbrasil
Olá colegas de grupos, eu gostaria de fazer uma pergunta...
Eu tenho 25 anos e estou querendo ingressar na área de programação, atualmente tenho uma noção OK de lógica de programação, mas sem muito contato com estruturas de dados(só mexi um pouco com matrizes e vetores) ou algo mais avançado. Eu fui pesquisar alguma linguagem de programação e das que eu vi achei interessante .NET/C#, mas ao mesmo tempo já vem um tempo que venho observando C e C++ já que conheço a área de programação há um bom tempo.

Eu queria saber se para um iniciante é interessante aprender C, C++ ou C#? Meu intuito atualmente é atuar na parte back-end de projetos. Se precisarem de mais informações eu darei com todo prazer. Agradeço a aqueles que puderem me responder.

De antemão desejo um bom feriado a todos e uma ótima semana santa para aqueles que irão participar. Deus abençoe vocês!


Bruno Sanches

unread,
Apr 18, 2025, 11:41:11 AMApr 18
to ccppb...@googlegroups.com
Olá!

Olha, é um assunto que você vai encontrar 1001 respostas diferentes e muitas brigas, nunca vi um consenso.

Sobre qual linguagem aprender, eu acho que talvez a pergunta deva ser: qual área você gostaria de trabalhar? Se tem uma área em específico, quais linguagens são mais comuns nessa área? E dai focar nestas.

Sobre aprender C;C++ ou C#, eu particularmente acho C uma boa linguagem para iniciantes, é meio controverso, mas é uma linguagem de certa forma ridiculamente simples e acho boa para aprender conceitos básicos, desenvolver lógica em algoritmos, etc.

Abs

Bruno Sanches
========================
https://github.com/bcsanches



--
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.

Fabio A Mazzarino

unread,
Apr 18, 2025, 8:14:38 PMApr 18
to ccppb...@googlegroups.com
Vou ser polêmico ao fechar a indicação de uma única linguagem. Mas tb acho que algumas pessoas vão concordar.

Se vc quer *uma única* linguagem, com maior aceitação no mercado brasileiro, pra investir, eu recomendaria C#.

Atualmente, nas grandes (não falo sobre tamanho) universidades do país, a linguagem C é uma das preferidas para ensinar conceitos fundamentais do desenvolvimento de software, como estrutura de dados, sistemas operacionais e sistemas distribuídos. Outras matérias clássicas como grafos, compiladores, etc, vejo mais outras linguagens, como Java ou até mm python. Mas nesses casos é uma questão acadêmica.


Lab C++ - Código, Dicas e Snippets


Em qui., 17 de abr. de 2025 às 19:26, Allan Souza <jefferso...@gmail.com> escreveu:

Leandro Cursino

unread,
Apr 19, 2025, 12:21:14 AMApr 19
to ccppb...@googlegroups.com

Acredito que o mundo mudou depois do Claude IA.
Dá uma olhada nos vídeos do Youtube e no CEO do Shopfy.
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.
As empresas querem desenvolvedores plenos que saibam trabalhar com MCP, RestAPI, Docker, AWS, Postgresql e muitas outras ferramentas.
Não pense pequeno. Ficará desempregado.


Em qui., 17 de abr. de 2025 às 19:26, Allan Souza <jefferso...@gmail.com> escreveu:

Otávio Basso

unread,
Apr 19, 2025, 8:50:56 AMApr 19
to ccppb...@googlegroups.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.


Allan Souza

unread,
Apr 19, 2025, 11:36:32 AMApr 19
to ccppbrasil
No caso meu caso eu penso bastante em construir uma base sólida, mas sem me desviar muito a ponto de querer trabalhar com uma linguagem que é uma incerteza de conseguir o emprego... Como eu ando observando um pouco o mercado e até alguns comentários, linguagens como C# se tornam mais preferidas... Não sei como é a barreira de entrada para juniors, porque ando vendo bastante vagas para pleno/senior.. Se alguém souber sobre isso eu agradeço em me responder..

Flávio de A. e Silva

unread,
Apr 19, 2025, 11:36:55 AMApr 19
to ccppb...@googlegroups.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.


--
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

de...@roo.com.br

unread,
May 8, 2025, 1:37:40 AMMay 8
to ccppbrasil
rapaz... pra quem ta comecando e quer garantir o almoco/janta c# e  ABAP 

Fernando Mercês

unread,
May 8, 2025, 9:42:22 AMMay 8
to ccppb...@googlegroups.com
> 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!


--
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.

pontilh...@gmail.com

unread,
May 13, 2025, 3:21:26 PMMay 13
to ccppb...@googlegroups.com
Olá pessoal.

Faz sentido colocar inline function nos gets e sets da classe ?
é uma boa prática?
prós / contras ?


inline int GetValue() const {
    return codigo;
}
inline void SetValue(int nCodigo) {
    this->codigo = nCodigo;
}

Valeu ;)

Jorge A Pontilho

Thiago Adams

unread,
May 13, 2025, 3:27:18 PMMay 13
to ccppb...@googlegroups.com
Se a definição da função  (implementação)  está visível na declaração da classe,
ela já é considerada inline.

class X {
  int i;
public:
  int get() {return i; }
};



Edgar Nsangu

unread,
May 14, 2025, 5:28:40 AMMay 14
to ccppb...@googlegroups.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.


--
Seja bem vindo!

Rafael Dias

unread,
May 14, 2025, 5:36:45 AMMay 14
to ccppb...@googlegroups.com
Aí vem aquela discussão: colocar getters e setters para acessar membros privados de classe é uma boa abordagem ou não? 




--
Rafael Dias Menezes
tel.:
+436507008854

Fabrício Cabral

unread,
May 14, 2025, 6:56:27 AMMay 14
to ccppb...@googlegroups.com
Não, porque quebra a encapsulação. Maiores detalhes:


At.te.



--
--fx

Thiago Adams

unread,
May 14, 2025, 7:43:50 AMMay 14
to ccppb...@googlegroups.com


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.
Já acessar o get/set de um membro privado dentro da classe, é uma opção.

Talvez a sua questão seja mais em relação a ter um membro público
sem get/set versus um privado + get/set?

Quando for algo que não deixa o encapsulamento sensível, pode ser tudo público sem get/set.
Exemplo
struct point {
  int x, y;
};

Mas se for um objecto que representa data, você poderia ter get e set para evitar uma data
com dia "35" por exemplo.

Isso é meio que esperado de um código C++.




Fabrício Cabral

unread,
May 14, 2025, 8:49:23 AMMay 14
to ccppb...@googlegroups.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 objeto
deixa de ser uma "caixa-preta".

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 mande
ele mesmo (o objeto) passar seus dados.

At.te.

--
--fx

Lauro Moura

unread,
May 14, 2025, 9:27:26 AMMay 14
to ccppb...@googlegroups.com


On Wed, May 14, 2025 at 9:49 AM Fabrício Cabral <fabri...@gmail.com> wrote:

<snip>
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 mande
ele mesmo (o objeto) passar seus dados.

Bom artigo do Martin Fowler sobre "Tell, don't ask": https://martinfowler.com/bliki/TellDontAsk.html

Especialmente a nota de rodapé (livre tradução):

>  E certamente mesmo o princípio mais fundamental de colocar dados e comportamento juntos deve às vezes ser dispensado em favor de outros critérios/interesses - como a divisão em camadas. *Bom design é sobre tradeoffs* (ênfase minha), e colocar dados e comportamentos juntos é apenas um fator para ter em mente.

E outro artigo dele sobre "erradicadores de getters": https://martinfowler.com/bliki/GetterEradicator.html

> Se estamos procurando uma regra prática, uma que prefiro é uma que ouvi pela primeira vez de Kent Beck, que é sempre ter cuidado com casos em que algum código invoca dois ou mais métodos no mesmo objeto. Isso acontece com métodos de acesso e outros comandos. Se você pede a um objeto dois dados, você pode trocar isso por apenas um método com os dados que você está calculando? Se você diz a um objeto para fazer duas coisas, consegue trocar por um único comando? Claro que há vários casos onde você não pode, mas é sempre bom se perguntar isso.
 

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.

Thiago Adams

unread,
May 14, 2025, 9:47:02 AMMay 14
to ccppb...@googlegroups.com
On Wed, 14 May 2025 at 09:49, Fabrício Cabral <fabri...@gmail.com> wrote:

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 objeto
deixa de ser uma "caixa-preta".


Acredito que originalmente a pergunta era sobre estes get/set diretos, 1 para 1, por isso
minha resposta foi direcionada para a questão de acesso.

Mas fazer get/set para tudo, direto, obviamente fura o encapsulamento.





pontilh...@gmail.com

unread,
May 14, 2025, 10:32:32 AMMay 14
to ccppb...@googlegroups.com
Em primeiro lugar muito obrigado pelas contribuições ;)

Bom, pelo que entendo vale a pena analisar se realmente é necessário aquele get/set, digo isso porq é comum ver alguém criando uma classe, e de imediato cria get/set para tds os membros (é até um recurso da maioria das IDEs), quem nunca, kkkkkkk.

Achei bem interessante esse vídeo que o Fabricio Cabral passou, porq me fez ser um pouco mais critico na hora de criar os métodos.

Att.
Jorge A Pontilho


--
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.

Fabrício Cabral

unread,
May 16, 2025, 12:16:00 PMMay 16
to ccppb...@googlegroups.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.


--
--fx

Thiago Adams

unread,
May 16, 2025, 12:35:04 PMMay 16
to ccppbrasil
On Friday, May 16, 2025 at 1:16:00 PM UTC-3 fabri...@gmail.com wrote:
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.


Um exemplo não serve?

class Date {
    int day, month, year;   
public:    
   
int getDay() {return day;}  
void setDay(int d) {day = d;}
    Date(int d, int m, int y) { /*verifica se a data é valida*/ }
};

 
Este setDay (direto) quebra o encapsulamento pois não verifica se day faz sentido.
Ainda assim , daria para corrigi-lo.
Retornar ponteiros ou referencias não const também podem criar um problema
de encapsulamento.



Fabrício Cabral

unread,
May 16, 2025, 12:42:39 PMMay 16
to ccppb...@googlegroups.com
Thiago,

Infelizmente, tem gente que não acredita nem vendo. Tô apelando para ter uma referência para ver se AJUDA a convencer!

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.


--
--fx

Bruno Sanches

unread,
May 16, 2025, 3:18:29 PMMay 16
to ccppb...@googlegroups.com
MAs o exemplo da classe Date do Thiago ilustra bem o problema.

A classe ou objeto tem que se manter íntegro. Se você tem um "setter" como o setDay que não faz validação, quebra a integridade do objeto, quebra o encapsulamento...

Date d{1, 1, 2025);

d.setDay(45); //ops


Bruno Sanches
========================
https://github.com/bcsanches


Fabrício Cabral

unread,
May 16, 2025, 6:25:23 PMMay 16
to ccppb...@googlegroups.com
Bruno,

Concordo plenamente com você e com o Thiago, mas mesmo assim, tem gente que não acredita. Assim, se tiver mais alguma fonte, seja livro ou artigo, gostaria de saber.

At.te.



--
--fx

de...@roo.com.br

unread,
May 16, 2025, 9:18:27 PMMay 16
to ccppbrasil
Faz sentido colocar inline function nos gets e sets da classe ?


inline: o qualificador nem sempre eh aplicado, vai depender do compilador, nivel de otimizacao e se `faz sentido`
allways inline (atributo): da uma forcada, mas, so se tiver sem otimizacao

CTF Home

unread,
May 18, 2025, 7:39:45 PMMay 18
to ccppb...@googlegroups.com
Olá!
Que eu me recordo, sobre funções inline, que estudei há 20 anos. Às funções inline, o programador invocada usando diretivas do pré-processador no código fonte melhorando o desempenho do programa diminui a escrita de código. 
O Livro que eu sugiro para estudo, How to programe, autores Deitels

Bruno Sanches

unread,
May 19, 2025, 9:16:22 AMMay 19
to ccppb...@googlegroups.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...

Bruno Sanches
========================
https://github.com/bcsanches


Bruno Sanches

unread,
May 19, 2025, 9:17:21 AMMay 19
to ccppb...@googlegroups.com
a função inline não tem relação com o pré processador, o compilador que na hora de gerar o código que vai decidir se suprime a chamada e "copia e cola" o código da função ou mantém a chamada.

Bruno Sanches
========================
https://github.com/bcsanches


Bruno Sanches

unread,
May 19, 2025, 9:18:04 AMMay 19
to ccppb...@googlegroups.com
Eu deixo tudo inline nesses casos, a não ser que tenha uma lógica mais complexa de validação...

Bruno Sanches
========================
https://github.com/bcsanches


Fabrício Cabral

unread,
May 19, 2025, 9:25:21 AMMay 19
to ccppb...@googlegroups.com
Bruno,

On Mon, May 19, 2025 at 10:16 AM Bruno Sanches <bcsa...@gmail.com> wrote:
Pior q não lembro de nenhuma fonte "forte" sobre isso.

Pois é, também nunca vi. Se alguém achar, favor avisar!

 
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ê coloca
um método set, ele deixa de ser imutável.
 
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...

"Não é muito diferente", não. Não tem diferença nenhuma!

At.te.

--
--fx

Bruno Sanches

unread,
May 19, 2025, 9:45:47 AMMay 19
to ccppb...@googlegroups.com
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ê coloca
um 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.


Fabrício Cabral

unread,
May 19, 2025, 10:51:22 AMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 10:45 AM Bruno Sanches <bcsa...@gmail.com> wrote:

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.

Se você tiver que setar alguma coisa depois que o seu objeto estiver construído, você acaba colocando acoplamento temporal no seu objeto, o que é ruim. Mas só por curiosidade: por qual caso você passou que você teve que setar alguma coisa no seu objeto depois que ele foi construído e que não poderia ser feito no construtor?

At.te.

--fx

Bruno Sanches

unread,
May 19, 2025, 11:01:38 AMMay 19
to ccppb...@googlegroups.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)




Bruno Sanches
========================
https://github.com/bcsanches


--
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.

Fabrício Cabral

unread,
May 19, 2025, 11:12:01 AMMay 19
to ccppb...@googlegroups.com
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 é valido

Eu 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.

At.te. 

--
--fx

Thiago Adams

unread,
May 19, 2025, 1:33:48 PMMay 19
to ccppbrasil

Este tópico esta parecendo Java nos anos 2000, sobre OOP e boas práticas.


On Monday, May 19, 2025 at 12:12:01 PM UTC-3 fabri...@gmail.com wrote:

>"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. ..."


>"Eu 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."

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.


Fabrício Cabral

unread,
May 19, 2025, 1:43:34 PMMay 19
to ccppb...@googlegroups.com
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ção
de 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

Thiago Adams

unread,
May 19, 2025, 2:19:32 PMMay 19
to ccppbrasil
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.


Márcio

unread,
May 19, 2025, 2:21:22 PMMay 19
to ccppb...@googlegroups.com


On Mon, May 19, 2025, 14:43 Fabrício Cabral <fabri...@gmail.com> wrote:

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ção
de um objeto, significa que ele está fazendo mais coisas do que deveria.

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.



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.

Fabrício Cabral

unread,
May 19, 2025, 4:44:14 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 3:19 PM Thiago Adams <thiago...@gmail.com> wrote:

Ter um outro objeto vai ter precisar mais memória.

Quanto mais memória? Você já fez um profiling? A gente se prende nessas questões, mas não sabe nem se precisa dessa otimização...

Ele poderia estar diminuindo a capacidade por exemplo.

Aí então você quer um outro objeto com menor capacidade.
 

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.

Aí então você quer é uma lista encadeada e não um vector.

 At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 4:47:23 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 3:21 PM Márcio <marci...@gmail.com> wrote:
 
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.

At.te.

--
--fx

Bruno Sanches

unread,
May 19, 2025, 4:51:31 PMMay 19
to ccppb...@googlegroups.com

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ê?

Hábito mesmo, depende muito do contexto, mas na maioria dos casos é mais fácil ter um objeto mutável.



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.

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.
 
 

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.

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.
 

- Cria um estado de erro no objeto e depois de construir checar se ele é valido

Eu 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.

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.
 


- 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.

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.

 

Bruno Sanches

unread,
May 19, 2025, 4:53:54 PMMay 19
to ccppb...@googlegroups.com

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.

Exatamente o que faço se estou numa base de código que lida com exceções.  

a não ser em situação muito específica, o objeto vai sempre estar em um estado válido.

Mesma coisa em um sistema que estamos finalizando aqui (sistema comercial básico com CRUD e outras coisas), eu sempre pego no pé dos devs: o programa pode quebrar, pode explodir o computador, não importa, mas, em hipótese alguma, podemos permitir que os dados no BD fiquem inconsistentes, o resto a gente dá um jeito...



Bruno Sanches

unread,
May 19, 2025, 4:54:52 PMMay 19
to ccppb...@googlegroups.com

Ele poderia estar diminuindo a capacidade por exemplo.

Aí então você quer um outro objeto com menor capacidade.

O vector pode tanto aumentar, quanto diminuir e continua sendo contínuo.
 

Bruno Sanches

unread,
May 19, 2025, 4:58:55 PMMay 19
to ccppb...@googlegroups.com
 
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.

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....

Roberto Spadim

unread,
May 19, 2025, 5:00:55 PMMay 19
to ccppb...@googlegroups.com
essa do if, é real, faz o throw no construtor, é bom pra manter a equipe fora do hospital psiquiátrico kkk

--
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.


--
Roberto Spadim
SPAEmpresarial

Fabrício Cabral

unread,
May 19, 2025, 5:05:50 PMMay 19
to ccppb...@googlegroups.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 acoplamento
temporal.

Faça testes. Experimente. Depois me diga o resultado.

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 5:10:12 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 5:58 PM Bruno Sanches <bcsa...@gmail.com> wrote:

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....

Acho que não expliquei direito. Permita-me melhorar:

// Cria uma data inválida
Date dt{2025, 2, 31};

const int day = dt.day(); // Aqui, no método day() você verifica se a data é válida. Se for, retornar o dia, senão, dispara uma exceção

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 5:11:56 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 6:00 PM Roberto Spadim <rob...@spadim.com.br> wrote:
 
essa do if, é real, faz o throw no construtor, é bom pra manter a equipe fora do hospital psiquiátrico kkk

Nã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 fazer
isso quando for usar algum método do objeto.

At.te.

--
--fx

Márcio

unread,
May 19, 2025, 5:26:25 PMMay 19
to ccppb...@googlegroups.com
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.




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.

Bruno Sanches

unread,
May 19, 2025, 5:39:36 PMMay 19
to ccppb...@googlegroups.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.


Eu sei que tem vantagens, mas foram raros os casos que achei que valeria a pena...
 

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 falei que isso é problema. O que disse é: se é imutável, é imutável, não altera seu estado após a criação.
 


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.

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...




Sempre garantir que a partir do momento que seu objeto foi construído, ele é válido.

Onde você viu isso? Tem alguma referência?

Não me recordo, depois de mais de 20 anos trabalhando, tem coisas q nem lembro onde aprendi. Mas quase como RAII...
 


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.

Pq tem q ser fora?
 

 
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 acoplamento
temporal.

Faça testes. Experimente. Depois me diga o resultado.

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....


Fabrício Cabral

unread,
May 19, 2025, 5:39:53 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 6:26 PM Márcio <marci...@gmail.com> wrote:
 
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 pode
criar 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.


Não estou dizendo que um design é melhor que o outro, mas cada um tem seus prós e contras.

Mas eu estou dizendo com todas as letras: o design que eu estou dizendo é melhor, mas queria ver argumentos contra.

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.

At.te.

--
--fx

Bruno Sanches

unread,
May 19, 2025, 5:42:29 PMMay 19
to ccppb...@googlegroups.com
 
essa do if, é real, faz o throw no construtor, é bom pra manter a equipe fora do hospital psiquiátrico kkk

Nã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 fazer
isso 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.

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?

 

Fabrício Cabral

unread,
May 19, 2025, 5:49:55 PMMay 19
to ccppb...@googlegroups.com
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?
 
Não falei que isso é problema. O que disse é: se é imutável, é imutável, não altera seu estado após a criação.

Certo.
 
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.
Definitivamente, 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? :)

 
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. 

Se for pra usar com aquele seu if (obj.IsValid()) vai ser um inferno mesmo.


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). 

Traga essa discussão para a lista. Vamos movimentar esse negócio! :)

 
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....

Faça experiências mesmo! Depois nos conte o resultado!

Se for ruim, quero MUITO saber! Principalmente as razões.

 At.te.

--
--fx

Bruno Sanches

unread,
May 19, 2025, 5:50:58 PMMay 19
to ccppb...@googlegroups.com
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 pode
criar 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.

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.

 

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.

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.


Fabrício Cabral

unread,
May 19, 2025, 5:52:18 PMMay 19
to ccppb...@googlegroups.com
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?
 
At.te.

--
--fx

Bruno Sanches

unread,
May 19, 2025, 5:55:49 PMMay 19
to ccppb...@googlegroups.com
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?

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};

Mais simples que:
point = point + deslocamento;


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?

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

 

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.

Pq? Não existe essa regra. Um vector pode ser bem pesado no construtor se você alocar algo grande....
 

 

Definitivamente, 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"

Voce sabe o que é RAII?
 

 
Pq tem q ser fora?

Pelo motivo que eu disse acima. Mas porque ele não pode ser fora? :)

Ele pode, mas veja o outro email... complica mais.... e o encapsulamento acaba...
 

Bruno Sanches

unread,
May 19, 2025, 6:01:12 PMMay 19
to ccppb...@googlegroups.com
Em seg., 19 de mai. de 2025 às 18:52, Fabrício Cabral <fabri...@gmail.com> escreveu:
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.

Acho que perdi essa parte, quando vocÊ fala do boolean? Se sim o problema só mudou de lugar...

 

 
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?

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)

 

Fabrício Cabral

unread,
May 19, 2025, 6:02:14 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 6:50 PM Bruno Sanches <bcsa...@gmail.com> wrote:

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?

At.te.

--
--fx

Bruno Sanches

unread,
May 19, 2025, 6:06:20 PMMay 19
to ccppb...@googlegroups.com

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.

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.
 


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é?

Com certeza, mas GO tem classes? Só fiz um hello world em go a muito tempo...
 

E nenhum momento eu disse pra ter um método init().

Ok, mas se eu não vou validar a inicialização do objeto, como vou inicializar ele?
 
 

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?

Veja no outro email se ficou claro isso. Se nao tento explicar de outro jeito
 


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?

No outro email, veja o exemplo do arquivo :P


Thiago Adams

unread,
May 19, 2025, 6:07:20 PMMay 19
to ccppbrasil
(eu respondi esta mensagem mas nao estou vendo ela..entao vou responder novamente)
fazer uma mudanca de estado eh geralmente menos custoso

se vc tem um vector membro de uma classe e vc remove 1 item vc muda o estado.
fazer um novo vector com um item a menos e depois apagar o antigo eh mais custoso.

Roberto Spadim

unread,
May 19, 2025, 6:16:41 PMMay 19
to ccppb...@googlegroups.com
Quando eh um construtor q ja ta recebendo dados pra instanciar, acho valido a validacao

Tipo 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.

Fabrício Cabral

unread,
May 19, 2025, 6:19:44 PMMay 19
to ccppb...@googlegroups.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};

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::path

Foi 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?

At.te.

--
--fx

Virgilio Fornazin

unread,
May 19, 2025, 6:29:10 PMMay 19
to ccppb...@googlegroups.com
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



--
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.

Fabrício Cabral

unread,
May 19, 2025, 6:29:50 PMMay 19
to ccppb...@googlegroups.com
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.

 
Veja no outro email se ficou claro isso. Se nao tento explicar de outro jeito

Se você puder explicar de outro jeito, eu agradeço.

 
No outro email, veja o exemplo do arquivo :P

Deixa eu olhar lá... é tanto e-mail que eu tô quase me perdendo... :)

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 6:49:30 PMMay 19
to ccppb...@googlegroups.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. 

Ao meu ver, isso é mais acoplamento temporal do que quebra da encapsulação. Mas vou analisar seu argumento com calma, pois é MUITO interessante!


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?

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)

Certo, mas não vou entrar nesse mérito.

At.te.
 
--
--fx

Thiago Adams

unread,
May 19, 2025, 6:59:47 PMMay 19
to ccppbrasil
Acho que seria interessante abrir um topico so sobre esta questao da memoria 

Fabrício Cabral

unread,
May 19, 2025, 7:00:12 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 7:16 PM Roberto Spadim <rob...@spadim.com.br> wrote:
Quando eh um construtor q ja ta recebendo dados pra instanciar, acho valido a validacao

Tipo new date() e new date(1,1,1111)
O segundo ja valida, o primeiro n

Roberto,

Eu nunca disse que não deveria validar. O que eu disse é QUANDO deveria validar. Meu argumento é que não deveria validar no construtor. Já outros acham que o
melhor seria validar no construtor.

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 7:02:41 PMMay 19
to ccppb...@googlegroups.com
Abre Thiago! Também acho muito interessante! Vamos discutir, trocar ideias!

Só para deixar claro: não sou o dono da razão! Minhas perguntas são legítimas, não quero irritar ninguém. Me perdoe se é o que está parecendo, mas JURO que não é!

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.


--
--fx

Thiago Adams

unread,
May 19, 2025, 7:11:38 PMMay 19
to ccppbrasil
A minha opinião é que é melhor o ctor não falhar. Mas eu tiver que mexer em um fonte que
ja faz isso, e se fizer da maneira correta, então eh uma questao de estilo.

Thiago Adams

unread,
May 19, 2025, 7:14:14 PMMay 19
to ccppbrasil
On Monday, May 19, 2025 at 7:49:30 PM UTC-3 fabri...@gmail.com wrote:
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. 



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.

Fabrício Cabral

unread,
May 19, 2025, 7:23:04 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 7:29 PM Virgilio Fornazin <virgilio...@gmail.com> wrote:

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.

Certo.

 
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”…

Nada impede porque a linguagem deixa. Mas devo fazer? Aí já são outros 500. Não entendi a parte do "ego do programador". Por que seria ego fazer um setDay()?


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

Suponha que não tem nenhuma validação a ser feita. Se você criar métodos get/set para cada atributo, você está quebrando a encapsulação, certo?


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

Depende do que você esteja fazendo. Mas você fazer get/set pra evitar um "visitor" nos atributos de um objeto, ao meu ver, está errado porque quebra a encapsulação.

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 7:25:22 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 8:11 PM Thiago Adams <thiago...@gmail.com> wrote:
 
A minha opinião é que é melhor o ctor não falhar. Mas eu tiver que mexer em um fonte que
ja faz isso, e se fizer da maneira correta, então eh uma questao de estilo.

Thiago, quais são os argumentos que você usaria para afirmar que é melhor o ctor não falhar? (Pergunta legítima, quero realmente saber).

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 7:26:39 PMMay 19
to ccppb...@googlegroups.com
On Mon, May 19, 2025 at 8:14 PM Thiago Adams <thiago...@gmail.com> wrote:

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.

Não vai, porque não tem como ela garantir isso. Quem tem que garantir é você, porque se você permite isso, você está colocando acoplamento temporal no seu objeto.

At.te.

--
--fx

Thiago Adams

unread,
May 19, 2025, 7:43:24 PMMay 19
to ccppbrasil
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/

Thiago Adams

unread,
May 19, 2025, 7:48:32 PMMay 19
to ccppbrasil
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)

Fabrício Cabral

unread,
May 19, 2025, 8:08:22 PMMay 19
to ccppb...@googlegroups.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?


Algo interessante de ler são as garantias fracas e fortes..
https://arne-mertz.de/2015/12/levels-of-exception-safety/

Vou ler... obrigado!
 

At.te.

--
--fx

Fabrício Cabral

unread,
May 19, 2025, 8:13:51 PMMay 19
to ccppb...@googlegroups.com
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?

At.te.

--
--fx

Marcelo Fleury

unread,
May 20, 2025, 6:42:18 AMMay 20
to ccppb...@googlegroups.com
Bom dia,

Sugiro você definir desafios de programação e buscar cumprir os mesmos.

Você disse ter interesse em aprender backend, então se proponha a desenvolver algum projeto backend que te faça sentido. Vai precisar aprender tcp/ip, http e restful pelo menos.

Por questões de mercado(vagas) e praticidade(backend(express/fastify/nestjs)/frontend(reactjs/nextjs)/iot(tesseljs)/mobile(react native)), recomendo aprender Typescript/Javascript. 

Em 2023 escrevi uma apostila, que você pode usar gratuitamente:

Boa sorte!

[]s

Em qui., 8 de mai. de 2025 às 10:42, Fernando Mercês <nan...@gmail.com> escreveu:
> 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!


On Thu, May 8, 2025 at 2:37 AM de...@roo.com.br <de...@roo.com.br> wrote:
rapaz... pra quem ta comecando e quer garantir o almoco/janta c# e  ABAP 



Em 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.

--
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.

Thiago Adams

unread,
May 20, 2025, 6:50:43 AMMay 20
to ccppb...@googlegroups.com


On Mon, 19 May 2025 at 21:08, Fabrício Cabral <fabri...@gmail.com> wrote:
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?



O encapsulamento permite que cada objeto cuide de si mesmo, e reporte um
erro se o chamador está tentando fazer algo  sem sentido. Vai até este ponto.


Thiago Adams

unread,
May 20, 2025, 6:58:20 AMMay 20
to ccppb...@googlegroups.com
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 objecto
quando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
(Não me refiro a passado como parâmetro, mas sim sendo membro  de outro objeto)
 

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


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.




Fabrício Cabral

unread,
May 20, 2025, 7:09:07 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 7:58 AM Thiago Adams <thiago...@gmail.com> wrote:
 
O problema do acoplamento é basicamente não ter um ctor vazio. Pois pode dificultar o uso  deste objecto
quando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
(Não me refiro a passado como parâmetro, mas sim sendo membro  de outro objeto)

Normalmente, um objeto não deveria ter um ctor vazio ou que não tenha parâmetros. File tem um construtor vazio ou que não recebe parâmetros?
Se tiver, ao meu ver, está errado. Deveria, ao menos, receber o nome do arquivo como parâmetro.


> Se sim, aí o objeto teria que ser mutável, certo? 
sim

Para mim, objetos mutáveis são um erro. Objetos imutáveis levam a um melhor design e permitem o compartilhamento, sem efeitos colaterais (ser thread-safe
é uma consequência disso).
 

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.

*EXATAMENTE*!! Perfeito!

At.te. 

--
--fx

Márcio

unread,
May 20, 2025, 7:14:17 AMMay 20
to ccppb...@googlegroups.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 objecto
quando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
(Não me refiro a passado como parâmetro, mas sim sendo membro  de outro objeto)
 

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...



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


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.


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.




--
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.

Thiago Adams

unread,
May 20, 2025, 7:29:17 AMMay 20
to ccppb...@googlegroups.com


On Tue, 20 May 2025 at 08:14, Márcio <marci...@gmail.com> wrote:


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 objecto
quando ele for usado dentro de outra classe que está dentro de outra classe e assim por diante.
Imagine que o objeto file por exemplo nao tivesse um ctor vazio.
(Não me refiro a passado como parâmetro, mas sim sendo membro  de outro objeto)
 

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...



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


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.


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.

Fabrício Cabral

unread,
May 20, 2025, 7:41:52 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 8:14 AM Márcio <marci...@gmail.com> wrote:

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?

Não, você pode saber que ele é inválido depois, sem problemas.

 
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.

Se você passar os valores inválidos, vai acontecer a mesma coisa (rollback), só que no construtor. A ideia é que ele faça isso em um método, não no construtor.


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.

Eu penso justamente o contrário: em qual caso não poderia verificar DEPOIS que o objeto é inválido? Por que tem que ser no construtor?

At.te.

--
--fx

Fabrício Cabral

unread,
May 20, 2025, 7:43:38 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 8:29 AM Thiago Adams <thiago...@gmail.com> wrote:

Este estado "vazio" ainda tem que ser válido.
Exemplo: o ctor sem argumentos da data poderia ser 1/1/1970.

Thiago, por que ter um construtor sem parâmetros? Deixa os parâmetros. Eles são essenciais para a construção do objeto. Se os valores passados forem inválidos, aí
se descobre depois, quando for utilizar o objeto.

 At.te.

--
--fx

Márcio

unread,
May 20, 2025, 7:45:23 AMMay 20
to ccppb...@googlegroups.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.

Fabrício Cabral

unread,
May 20, 2025, 7:57:49 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 8:45 AM Márcio <marci...@gmail.com> wrote:

Entendi, tu defende sempre ter um construtor vazio que nunca falha e que permite inicializar/validar apenas quando necessário.

Não, Márcio. Construtor vazio somente nos objetos que fazem sentido. No caso do Date, não faz sentido ter um construtor vazio.

 
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.

Sem construtor vazio, não há esse problema.

 
Mas daí voltamos nos casos onde o construtor vazio faz sentido existir e recomeçamos o loop :)

Raros os casos fazem sentido. Mas eles existem!

 At.te.

--
--fx

Thiago Adams

unread,
May 20, 2025, 8:06:14 AMMay 20
to ccppb...@googlegroups.com
O estado "vazio" é válido, ou seja, não precisa validar. No caso da data é uma data válida, no caso de string eh vazio, file é fechado etc..

Até, dá para pensar em algum caso onde o vazio seja inválido. Por exemplo, um objecto que tenha
um id único não nulo e este id já é atribuído na criação.
Então uma "guideline" é sempre em termos gerais.. mas sempre haverá casos específicos.


Virgilio Fornazin

unread,
May 20, 2025, 8:15:54 AMMay 20
to ccppb...@googlegroups.com
std::optional<T> serve para estado 'vazio' ou 'não definido'... usar 0 ou '' como vazio é convenção de código na maioria das vezes

--
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.

Bruno Sanches

unread,
May 20, 2025, 9:03:50 AMMay 20
to ccppb...@googlegroups.com




Em seg., 19 de mai. de 2025 às 19:19, Fabrício Cabral <fabri...@gmail.com> escreveu:
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};

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.

Com não tem diferença?
 
point += deslocamento;
Mais simples e prático de escrever do que:
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 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

Foi só um exemplo. Além disso, você poderia querer validar o path do arquivo, sei lá...

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.
 

 
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?

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)
 


Voce sabe o que é RAII?

Sei, só não entendi no contexto da sua frase.

Você fazer validações e tudo mais no construtor, ao meu ver naõ deixa de ser uma forma de RAII
 

 
Ele pode, mas veja o outro email... complica mais.... e o encapsulamento acaba...

Não entendi porque a encapsulação acaba. Poderia explicar melhor?


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...

T+ 

Bruno Sanches

unread,
May 20, 2025, 9:08:03 AMMay 20
to ccppb...@googlegroups.com
Em seg., 19 de mai. de 2025 às 19:29, Fabrício Cabral <fabri...@gmail.com> escreveu:
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?

O new vai disparar automaticamente. Eu nunca tratei erro de memória, somente em casos bem específicos. Geralmente tem um try / catch em volta do programa todo que vai interceptar a exceção de falha de memória, mostrar o erro e finalizar o programa. Ficar sem memória é uma situação delicada, pois:
- o seu programa vai continuar como? 
- vai tratar o erro e fazer o que? Na máximo tentar gravar algum dado para não ter perda ou tentar fechar uma conexão de forma "graciosa". 

O fato é que faltou memória, a não ser em casos muito específicos, não tem o que fazer. 
 

 
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?

Eu disse que é problema? A pergunta é pq construtor é funcionalidade de OO, se GO nao tem classes, logo, não vai ter construtores.
 


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 dai em todo método do objeto vou ter que ficar checando se o estado dele é válido? Complicação atoa. 
 
T+

Bruno Sanches

unread,
May 20, 2025, 9:11:29 AMMay 20
to ccppb...@googlegroups.com



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?

Pensando num caso bem simples onde fiz um classe só para ler e escrever num arquivo, sim. 
 

 
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?

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
 

Bruno Sanches

unread,
May 20, 2025, 9:15:01 AMMay 20
to ccppb...@googlegroups.com
Chegamos no ponto onde depende do contexto e do que você quer fazer.

Lembremos que estamos numa área onde não existe uma resposta para tudo. Não tem "bala de prata". Eu hoje a não ser que tenha um caso muito específico onde eu precise disso, não vejo sentido o objeto ter um estado "vazio" ou "inválido".

As situações que vocês citaram são válidas, como o variant, também podemos pensar num smart pointer (unique_ptr, shared_ptr, escolha seu favorito...)

Mas por outro lado eu tenho o caso onde eu quero forçar a situação que se determinado objeto construiu, ele vai ser válido e o programador pode chamar os métodos dele sem ficar checando nulo pq se o construtor foi, o objeto se garante.

Bruno Sanches
========================
https://github.com/bcsanches



--
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.

Fabrício Cabral

unread,
May 20, 2025, 10:05:50 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 10:03 AM Bruno Sanches <bcsa...@gmail.com> wrote:

Com não tem diferença?
 
point += deslocamento;
Mais simples e prático de escrever do que:
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 é mais
legí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 dos
objetos 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.


Você fazer validações e tudo mais no construtor, ao meu ver naõ deixa de ser uma forma de RAII

No construtor você pode criar novos objetos, mas abrir um arquivo, fazer uma conexão de rede, etc. já é coisa para os métodos, não para o construtor.
Não consigo ver onde isso impacta no RAII, uma vez que quando o recurso for deixado de ser utilizado, vai chamar o destrutor e este liberar os
recursos alocados (estou certo?).

 
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();

Então, porque não deixa para abrir o arquivo no open()? Pelo que eu entendi, você quer abrir o arquivo no construtor, correto? Eu estou dizendo para fazê-lo
justamente no método open() que como o próprio nome diz, é para abrir o arquivo.


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?

Os motivos que eu listei acima.


E se tenho que chamar o load, antes de fazer leitura e escrita, quebrou o encapsulamento, pois pq preciso fazer isso?

Em nenhum momento eu falei de chamar load() ou init() para inicializar o arquivo para poder utilizá-lo. O que eu disse é que no caso de um arquivo
muito grande, talvez (não conheço usa necessidade) o que você queira é criar um arquivo e fazer um load() para carregar esta grande quantidade
de dados. Foi isso que eu falei.


Abrir o arquivo é problema da classe, não meu.

Sim, deixe ela fazer isso, mas no open() e não no construtor. Esse é o ponto.

 
Claro, isso pensando em um caso de uso bem simples, tudo é discutível e existem n necessidades...

Apresente os casos contrários. Vamos debater!
 
At.te.
--
--fx

Fabrício Cabral

unread,
May 20, 2025, 10:08:28 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 10:11 AM Bruno Sanches <bcsa...@gmail.com> wrote:

Pensando num caso bem simples onde fiz um classe só para ler e escrever num arquivo, sim.

Então pronto, ué. Crie seu arquivo e deixe para abrir o arquivo no open(), não precisa abrí-lo no construtor.
 

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

Concordo. Cada um no seu quadrado. Só não sei onde há quebra do SRP quando você deixa para abrir o arquivo no open() e não no construtor.

 At.te.

--
--fx

Bruno Sanches

unread,
May 20, 2025, 10:09:52 AMMay 20
to ccppb...@googlegroups.com
Em ter., 20 de mai. de 2025 às 11:05, Fabrício Cabral <fabri...@gmail.com> escreveu:
On Tue, May 20, 2025 at 10:03 AM Bruno Sanches <bcsa...@gmail.com> wrote:

Com não tem diferença?
 
point += deslocamento;
Mais simples e prático de escrever do que:
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 é mais
legível do que da outra forma.

Subjetivo, ambos os casos... em C/C++ a gente se acostuma com += -=++ --...
 


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 dos
objetos 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.

refactoring nem sempre é trivial e vale a pena? ISso tem custo...
 


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.

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...
 


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.

Ahm?
 
2. Coloca muita funcionalidade que (talvez) nem seja usada para pelo objeto.

MAs se vc coloca a funcionalidade em outro ponto seu objeto já esta inchado... 
 
3. Diminui drasticamente o tempo de construção do objeto, que deveria ser feito de maneira simples e rápida.

Quem ditou isso?
 
4. Desloca a funcionalidade (inteligência) que deveria estar nos métodos.

Quem ditou isso? Pq?

 

Bruno Sanches

unread,
May 20, 2025, 10:10:46 AMMay 20
to ccppb...@googlegroups.com
Não tem quebra no SRP abrir no open ou no construtor. Mas começar a por na classe arquivo codigo para validar path, validar acesso, ai podemos começar a abusar do SRP
 

 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.

Bruno Sanches

unread,
May 20, 2025, 10:14:45 AMMay 20
to ccppb...@googlegroups.com
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.


Bruno Sanches
========================
https://github.com/bcsanches


Fabrício Cabral

unread,
May 20, 2025, 10:43:43 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 11:09 AM Bruno Sanches <bcsa...@gmail.com> wrote:

Subjetivo, ambos os casos... em C/C++ a gente se acostuma com += -=++ --...

Subjetivo sim, mas têm vários estudos com rigor científico demonstrando por que um é melhor que o outro. Desculpe, mas "a gente se acostuma" não é
um parâmetro válido para mim.


refactoring nem sempre é trivial e vale a pena? ISso tem custo...

Concordo, mas não seria o caso de fazer refactoring em toda a aplicação. Apenas nos gargalos *SE* houver algum problema.


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...

Mas se o cara abrir o arquivo no construtor só para, sei lá, consultar o path do arquivo ele não vai fazer uma coisa desnecessária? É justamente esse o ponto
contra fazer execução de código no construtor que não seja apenas a inicialização do objeto.

Ahm?

O paradigma orientado a objetos deveria ser declarativo. O que muita gente faz é "imperativo disfarçado de orientado a objetos", infelizmente.


MAs se vc coloca a funcionalidade em outro ponto seu objeto já esta inchado... 

Inchado vai estar se você coloca isso no construtor...

 
Quem ditou isso?

E quem ditou que deveria estar no construtor? :)

 
Quem ditou isso? Pq?

Se você tira o teste de validação (por exemplo) de um método e coloca ele no construtor, você está tirando funcionalidade do método, não?

At.te.

--
--fx

Fabrício Cabral

unread,
May 20, 2025, 10:49:15 AMMay 20
to ccppb...@googlegroups.com
On Tue, May 20, 2025 at 11:14 AM Bruno Sanches <bcsa...@gmail.com> wrote:
Um copy e paste da wikipedia:

Sério mesmo que tu tirou da Wikipedia e quer utilizar o que tem lá como argumento? :)

 
In class-based, object-oriented programming, a constructor (abbreviation: ctor) is a special type of function called to create an object.

Não senhor. Construtor não é função. Construtor é construtor, método tem tipo de retorno, construtor não tem. Já começa errado aqui.


It prepares the new object for use, often accepting arguments that the constructor uses to set required member variables.

Certo. Aqui tá ok.

 
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.

Aí já contradiz o que disse lá em cima. Viu só por que eu falei "quer utilizar o que tem lá como argumento"?


 Constructors often have the same name as the declaring class.

Certo.

 
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.

Certo, e de onde tirou isso? Qual a fonte?


Immutable objects must be initialized in a constructor.

Isso é verdadeiro, por que se eu criou um objeto imutável, o único momento que eu vou ter para atribuir valores ao objeto é no construtor.

 At.te.

--
--fx
It is loading more messages.
0 new messages