Are getters and setters an illusion of encapsulation?

Asked

Viewed 3,366 times

51

It is common to teach that it is right to leave the class attributes private and create getters and setters for them, all because of the encapsulation.

Isn’t that the same thing as making everything public, since you can change and get the value freely? Doesn’t this create just an illusion of encapsulation? Is it recommended or not its use? Why?

  • 8

    In theory, a Setter not only set the value of a variable, but also treat at least the basic input value as well as validate it. Also, through a Setter you have, depending on the language, typing.

  • 2
  • 1

    It is only a "spirit", a good practice of programming given the paradigm itself. It would be complicated if everyone could deliberately tamper with my limbs/organs. So the getter’s and Setter’s come to affirm this idea that we must "ask" to define or access something that belongs to us (objects).

  • Worth reading: http://www.javaworld.com/article/2073723/core-java/why-getter-and-setter-methods-are-evil.html

  • @Cold, is that a "bad practice" you mean? Getter and Setter without any purpose only complicates the code, in practice I have never seen one of them that treats anything in entities or in Vos, nobody is crazy to put logic in there, in anemic domains, the rules stay in the layer of "Service". I only use them when I am "forced" by some "framework" that has bad practices.

4 answers

39


I agree with all the answers. Getters and setters are essential.

But the point is, they are at all times necessary?

What really needs to be accessed?

It happens that it is common practice to create getters and setters for all the properties of a class. It is not reflected on the real need nor on the possible side effects of this.

Many methods are created unnecessarily, thinking perhaps that they may be necessary some day, but are never used. This only makes the code more error-prone.

And the interface?

Although setters and getters is a type of encapsulation of the attribute, the signature of the public method is part of its interface, being a type of "contract" with the other classes.

The attribute may be encapsulated, but in no way are you free to change the implementations, since any change in attribute will probably also affect the signature of some method.

And the complex objects?

For example, if my class has a list:

public class Turma {
    private List<Aluno> alunos; 
}

What to do? Putting one setAlunos?

public class Turma {
    private List<Aluno> alunos; 
    public void setAlunos(List<Aluno> alunos) {
        this.alunos = alunos;
    }
}

Or manage the list internally?

public class Turma {
    private List<Aluno> alunos = new ArrayList<Aluno>(); 
    public void addAluno(Aluno aluno) {
        alunos.add(aluno);
    }
}

There are several situations where it is better not to have the method Setter.

In the first example, the list is "exposed". It is possible that the list implementation passed by another developer does not have any method used internally implemented. For example, if our class adds students at some point, but the past list is immutable.

Immutable Objects

In scenarios where a business object is shared between several threads concurrently, setters can cause undesirable effects. Immutable objects (without setters) are much safer and efficient in this regard, as they cannot end up in an inconsistent state due to competition.

In addition, if an object is passed to various routines and services, the setters may be inadvertently called by some routine leaving the object in an inconsistent state. Suppose you have already applied all the validation rules, but before writing the database data one of the routines calls a set. Then you need to "hunt" who was responsible for the change.

One more point, is that some objects could benefit from cache information. For example, if one of the attributes is calculated from several others. But the various setters leave this implementation much more complex.

Creating an immutable object is not difficult. One way is to allow setting values through the constructor and to have no methods set. Example:

public class Turma {
    private List<Aluno> alunos; 
    public Turma(List<Aluno> alunos) throws ListaDeProblemasException {
        this.alunos = alunos;
        //valida e processa alunos como bem quiser
        //sabe-se que não irá mudar depois
    }

    public List<Aluno> getAlunos() {
        return alunos;
    }
}

Validation in the September?

Use setters for validation is interesting to some extent.

This can actually become a problem in cases where one attribute depends on another. Imagine, for example, that you have a method setCPF and other method setCNPJ. Both can only be called, respectively, if the person’s type is F or J. And if anyone decides to call those before these?

In addition, it becomes much more difficult to treat this type of error to, for example, display the list of errors to the user on the screen.

Completion

Getters and setters can be, yes, an illusion of encapsulation in many cases, mainly because the public methods of a class increase the coupling and the "commitment" in maintaining all those methods.

It’s not that it’s an illusion in itself, but it occurs in the minds of programmers who think encapsulamento = getter + setter. They will later discover "strange" behaviors in the program because in fact there is nothing "hidden".

Minimal public method implementation makes code more "secure" and flexible.

  • You’re right about setters not always being needed. And I liked the hint about immutable objects, but the question of their use is that by design principle the attributes of such an object will not need to be changed after their creation. If this is not the case, the use of setters still ensures encapsulation. I also do not see so much distinction in coupling between having a Setter (even simple) and a directly public attribute. The dependence on the property will be virtually the same. continue...

  • ... So I just disagree about them being an illusion. Even in the example of the students (complex object), the first option is practically equivalent to leaving the public list, and so there is simply no encapsulation.

  • @Luizvieira Really. It’s not that I think it’s an illusion in itself, but it occurs in the minds of programmers who think that encapsulamento = getter + setter. Then they later discover "strange" behaviors in the program because in fact there is nothing "hidden".

  • 1

    I understood, so the fundamental point of your answer is that leaving public unnecessarily is nonsense (whether one way or another), because encapsulation begins in keeping hidden what does not need/should be changed. Fantastic, but how about changing your current conclusion to your last comment? Personally I think it looks much better. :)

  • 1

    @Luizvieira Good suggestion. Done.

31

Use a Setter is not an illusion of encapsulation because the idea is that the class itself has all control over the alteration of its properties.

If a property is naturally public, this control is simply non-existent and there is no encapsulation. Any external source can, at any time, change the property with any value of the appropriate type, and lead the object to an inappropriate state (considering what was planned by the designer).

Having a Setter method for this, the object can - faced with an upgrade attempt - make necessary validations, update other dependent properties, etc., and thus ensure that the state is always correct according to the projected.

  • This reply gives an example of what has been explained here.

  • Best answer, +1! I understood just reading the first part.

  • I thought of a percentage calculation as an example: public void SetPorcentagem(var qtade)&#xA; {&#xA; this.porcentagem = (qtade * valor) * 0,01;&#xA; }

  • 1

    @Marconi Thanks. :) About the example, it is very good, but it has a detail: if the idea is to encapsulate the percentage, the method should be called SetQuantidade (because then the calculation and internal use of the percentage will be encapsulated even semantically and conceptually).

18

The advantage of using getters and setters is the possibility of validating or modifying data when using this Pattern.

For example, suppose you have a class Produto with the attribute preco that takes values. Clearly, a negative value would be invalid. Hence, the setPreco(int preco) could behave as follows:

public void setPreco(int preco) {
    if (preco < 0) {
        this.preco = 0;
    } else {
        this.preco = preco;
    }
}

or:

public void setPreco(int preco) {
    if (preco < 0) {
        // exceção do tipo runtime
        throw new NumberFormatException("Preco deve ser maior do que zero.");
    }
    this.preco = preo;
}

Note that in the first example, the wrong value was simply corrected, while in the second one RuntimeException (supposing that we are using java).

For getters, the logic is the same, if the value of the property to be recovered is not adequate for any reason, it must be adjusted when returning the client class.

18

At first it may seem that it makes no difference between leaving your attribute public or leaving private with getters and setters without validations, because your access is free for modifications of both ways.

However, if one day you realize that you must validate the attribute before assigning its value you will notice the difference of having opted for one of the two cases mentioned above. If you already have getter and Setter you can validate within your class without changing the classes that depend on them, but if you had set your attribute as public and you switch to private you will break all the external classes that accessed the attribute freely.

Open-closed principle

According to the Open-Closed principle your code must be open to extension and closed to modifications, and by modifying your attribute from public to private you have broken the principle, because you can cause other classes not even compile when trying to access the attribute; If you fix your class by validating the value before assigning it you didn’t get to hurt the principle, that’s right, you did make a modification in your code, but based on Meyer’s OCP this is acceptable as you are correcting what you can-if calling errors, and the classes that depend on it will still work, of course the behavior can change since the value used when calling the set() method can be different from the one assigned within the Setter implementation.

See two examples of open-closed principle applications, one used in Polimorphic OCP and the other Meyer OCP: Open/closed principle - how to understand this?

  • stay calm that day will never come => "However if one day you realize that you must validate the attribute before assigning its value you will realize the difference of having opted for one of the two cases mentioned above. " And if it does, do something very, very simple => "Create another Entity for the new purpose!"

Browser other questions tagged

You are not signed in. Login or sign up in order to post.