Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Porquê usar uma Propriedade Vazia ao invés de um campo Publico?

public string Titular
{
    get;
    set;
}
//  vs
public string Titular

Se não há uma regra no setter ou getter, porque nesse exemplo em especifico foi usado assim?

Eu sei que poderíamos usar um private set para tornar algo apenas pra leitura, por exemplo. mas n consigo ver a diferença neste exemplo descrito acima

3 respostas

É questão de convenção estética, imagina que em um mesmo projeto vc tenha atributos públicos e privados, se vc faz todos da mesma forma (quase como que convencionando) fica mais fácil/agradável de se ler/editar etc

solução!

Acredito que a discussão vá além do uso prático e também de convenções e pode se estender aos tradicionais getters e setters. Acho que a resposta mais simples seria a de que você está violando o encapsulamento da sua classe e está expondo um detalhe de implementação. Mas uma resposta dessas é basicamente dizer "Porque sim!". A questão de fato é o do porquê isso é um problema ou porque isso pode se tornar um problema.

Um outro ponto importante antes da discussão é de que o simples fato de se usar uma Propriedade vazia (auto-property) ou um getter e setter vazio, não necessariamente é a melhor escolha de design para uma classe, como apontando em algumas referencias:

Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details. [1]

Ou seja, tanto os getters e setters (aqui o exemplo também estende-se as Properties vazias) quanto atributos públicos são igualmente perigosos: ambos expõe acesso externo a detalhes de implementação, muitas vezes ferindo o princípio Tell-Don't-Ask[2][3]. Basicamente, no momento que eu uso um acesssor (get/getter) que retorna o dado de um determinado atributo, eu estou "pedindo" o dado que pertence àquele objeto ao invés de "dizer" ao objeto para fazer algo com aquele dado. Um exemplo chulo seria: ao invés de chamar o get da property nome e get da property sobrenome para concatenar e retornar um nome completo do objeto pessoa, eu poderia simplesmente chamar o método nomeCompleto. Em um futuro onde eu tivesse o nome do meio da pessoa como requisito, eu não precisaria me preocupar em cada ponto do sistema que preciso do nome completo, adicionar o get do atributo do nomeDoMeio concatenado com o nome e sobrenome.

Mesmo assim, ainda é possível levantar alguns pontos do porquê as properties ou os getters e setters vazios são menos problemáticos:

1- Já foi comentado na pergunta, mas é importante ressaltar, com properties é possível definir níveis de acesso a determinado atributo.

public string Titular { get; private set; }

ou até mesmo transformá-la em somente leitura:

public string Titular { get; }

Criar métodos acessores somente ao que for de fato usado é uma boa prática de OO (Orientação a Objetos) e deve ser usado com parcimônia para não violar o Tell-Don't-Ask.

2- As propriedades vazias (auto-property) podem a qualquer momento mudar para propriedades normais, caso seja necessário. Essa mudança pode ser feita sem alteração na assinatura. Por exemplo: para uma mudança de requisito onde seja necessário fazer alguma validação de valor para determinado atributo, caso o mesmo tenha properties, basta alterar o comportamento da própria property para fazer a validação necessária, em um único ponto. O trabalho é muito maior quando você acessa diretamente um atributo público, onde para cada local de atribuição, é necessário fazer a validação (talvez esse seja o exemplo clássico de uso de métodos acessores, mas não é justificável por si só). Uma discussão datada mas interessante é a [4].

3- Herança. Como apontado na resposta escolhida da discussão [5], propriedades são herdadas mas atributos não. Você pode usar o atributo de uma classe herdada, mas não pode alterar seu comportamento. No exemplo dado:

public class Foo {
  public virtual int MyField = 1; // Inválido. Não pode ser feito

  public virtual int Bar {get; set; }
}

public class MyDerive : Foo {
  public override MyField; // Inválido. Não pode ser feito

  public override int Bar {
    get {
      //do something;
    }
    set; }
}

Ou seja, caso seja necessário alterar o comportamento de acesso de algum atributo, basta fazer a sobrescrita da property.

4- Interface. Como apontado na segunda resposta da discussão [5] e quarta resposta da discussão [8], é possível definir propriedades na interface, coisa que não é possível com os atributos. Caso exista uma situação onde haja um grupo de classes que espera-se que contenha determinada property, pode-se definir uma interface como segue abaixo:

public interface ITitular
{
    string Titular { get; }
}

Existem inúmeros outros pontos que de certa forma justificarão o uso de properties/getters&setter ao invés de expor publicamente um atributo. Mas no final das contas isso acaba sendo um decisão de design, com alguns tradeoffs, como mencionado antes. Acredito que seja um consenso que não basta ter getters e setters para ter capsulamento e baixo acoplamento, e que o bom design de classes vai muito além disso (ex. imutabilidade, SOLID, Tell-Don't-Ask...), da mesma forma que atributos públicos,para situações muito específicas (citação do Joshua Bloch e Uncle Bob no artigo [10]) não são abomináveis da forma que estamos acostumados a vê-los. No final das contas, é interessante saber que isso é uma discussão que acontece há muito tempo, de diversas formas (getters/setters e Properties), permeiando diversas linguagens, diversos paradigmas e diversas tecnologias.

Referências:

[1]https://www.javaworld.com/article/2073723/why-getter-and-setter-methods-are-evil.html

[2]https://martinfowler.com/bliki/TellDontAsk.html

[3]https://pragprog.com/articles/tell-dont-ask

[4]https://blog.codinghorror.com/properties-vs-public-variables/

[5]https://stackoverflow.com/questions/1876197/why-have-empty- get-set-properties-instead-of-using-a-public-member-variable

[6]https://stackoverflow.com/questions/4948816/getters-setters-and-properties-best-practices-java-vs-c-sharp

[7]https://stackoverflow.com/questions/653536/difference-between-property-and-field-in-c-sharp-3-0

[8]https://stackoverflow.com/questions/1180860/public-fields-versus-automatic-properties

[9]https://blogs.msdn.microsoft.com/abhinaba/2006/04/11/changing-a-field-to-a-property/

[10]https://dev.to/scottshipp/avoid-getters-and-setters-whenever-possible-c8m