12
In object orientation, one way to ensure encapsulation is to maintain the attributes of the private classes and modify their state via methods. In addition, to ensure the integrity of objects, it is common to require that data essential to the existence of the object be passed in the constructor.
In classes with few attributes this works well. It turns out that in classes with a very large number of attributes, it starts to get a little strange. An example of this is this class PessoaJuridica
(that I recognize not to be very good):
public class PessoaJuridica
{
public string NomeFantasia { get; set; }
public string RazaoSocial { get; set; }
public string Endereco { get; set; }
public string Bairro { get; set; }
public string Cidade { get; set; }
public string Estado { get; set; }
public int CEP { get; set; }
public int Telefone1 { get; set; }
public int Telefone2 { get; set; }
public int Fax { get; set; }
public int CNPJ { get; set; }
public int InscricaoEstadual { get; set; }
public int InscricaoMunicipal { get; set; }
public DateTime DataConstituicao { get; set; }
public DateTime DataCadastro { get; set; }
public string Observacoes { get; set; }
}
The class has several attributes. Going through all this in the constructor is unviable, and even choosing a subset to pass would still be bad. Also building a method for each attribute would not have much advantage over what is already there. So I thought of the following improvement:
I looked in the class at some things that make sense grouped together. For example:
- Address, Neighborhood, City, State, Zip Code collectively form the Company Address
- Phone1, Phone2 and Fax are types of phones
- CNPJ, Registracaoestadual, Inscricaomunicipal and Dataconstituticao form a company documentation
That’s why I coded a struct Endereco
with properties "Street, Number, Neighborhood, City, State, ZIP code", a struct Telefone
with properties "DDD, Numero, Tipotelefone" being "Tipotelefone" an Enum that can be "Fixed" or "Fax". I finally coded a struct DocumentacaoEmpresa
with attributes "Razaosocial, CNPJ, Inscribed State, Inscribed Community and Date Constitution". With this I stayed with the class
public class PessoaJuridica
{
public string NomeFantasia { get; private set; }
public Endereco Endereco { get; private set; }
public IList<Telefone> Telefones { get; private set; }
public DocumentacaoEmpresa Documentacao { get; private set; }
public string Observacoes { get; set; }
}
And then it becomes easier to use methods and the builder to deal with this class. What I did was I took a class with multiple attributes, grouped those attributes into concepts that make sense and encoded those concepts. In addition, you now have a phone list to obey the Open/Closed principle.
What I’d like to know is: is this a common practice in object orientation? The construction of these structs was not made because they were domain concepts, but rather to improve the writing of a class. Is there any Pattern design, or anything like that?
I know you don’t need a Pattern design for something to be valid, but I wanted to know if it’s common and if there’s more information about it to see if it’s a good idea to do this sort of thing.
Thank you for the reply @bigown. What I said about Open/Closed was in the following sense: at the time of coding there are two telephones and a fax. Later it may be necessary to add another telephone, or a second fax. As it was it would be necessary to modify the code, in the new way it is possible to add the functionality without modifying: just add a new number to the list. That’s the idea of Open/Closed isn’t it? Being able to add things without modifying what already exists. Maybe I misunderstood Open/Closed.
– SomeDeveloper
I don’t follow these principles. I even follow by coincidence. I happen to do something that fits some of them, but I don’t pursue them. There are situations that simply need to change the class, it would be ridiculous to keep raising a daughter class every time it needs a change. So I have my doubts whether the principle applies in this case. Anyway I think it talks more about behavior. Although technically properties are behaviors, deep down they are just proxies for the state. So I don’t know if it’s right or not. But me I wouldn’t worry about it. I wouldn’t apply it
– Maniero
The phone is not the only problem. You mean you can’t place a new property? Because if O/C is that, the systems are extremely inflexible. Your concern with the phone makes sense, as I show in the answer, but I think it is independent of the O/C problem that is a widespread problem. Another thing that I was thinking that the O/C problem only actually appears when there is inheritance. Classes that have daughters should be frozen anyway. I understand that any change can generate undesirable effects but it is impracticable to modify certain classes.
– Maniero
One of the reasons to avoid inheritance is to avoid these principles that even valid. They try to solve the problem that object orientation possesses. They show you the path you must follow to avoid what is known that will bring trouble. So some think that the default of classes should be sealed, which cannot be inherited. The moment you raise daughters of the class you have responsibilities and commitments. As in real life, this is not always desirable. You lose the freedom to do whatever you want with the class under pain of breaking the daughters.
– Maniero
Not fully related but it shows the problem of these principles and "Good practices": http://sklivvz.com/posts/i-dont-love-the-single-responsibility-principle. In general these things are almost arbitrary. That’s why I prefer more general things that give a general idea of what to do. When it gets very specific, it pleases people more because they tell them that they don’t know what to do, even though this is stupid. They are created to sell books, consultancies, etc. It is Snake oil. Their intention and foundation are good but the result is disastrous.
– Maniero