Use of setters in the builder

Asked

Viewed 257 times

4

I wonder if there’s any difference, semantically speaking, between these two builders:

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.setNota1(n1);
   this.setNota2(n2);
}

and

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.nota = n1;
   this.nota2 = n2;
}

4 answers

5

I don’t know exactly what you meant by semantics, but we can see the question from various perspectives.

Clarity

Use methods Setter can be more confusing because if someone else will read your code.

It may incorrectly assume that the method Setter whether or not it performs any logic within it, so it needs to navigate to the methods and look at what they do.

Note in the other answers that they always end up inferring something or putting a condition. Imagine a system with multiple cases of this and you can extrapolate how much complexity it will add to everyone’s life.

Always use the simplest solution. In this case, always use direct assignment when possible.

I imagine that this may seem "ugly" to some, mainly because when we start using object orientation, we get the impression that any direct manipulation of attributes somehow breaks the encapsulation.

But the scope of the class is owned by itself. A class does not need secrets for itself, or we begin to engage in insanity. We could say that a class that encapsulates itself has multiple personalities?

Effect

Imagining now that the setters only attribute, the final effect would be the same as the assignment. However, this is not always so simple, especially where there is competition involved.

Understand competition as the act of accessing and modifying the same attribute or object from different threads at the same time.

In competing scenarios, you should always use modifiers final or volatile, because they guarantee that the state of the variables will be written in the main memory and all the threads will see the correct value. Otherwise a thread can read the old cache value.

An efficient way to share objects between threads is using immutable objects. In this case, it is recommended to use final in all attributes. Example:

private final String nome;
private final float n1;

In the above example, the attributes final can only be assigned once and this must occur until the constructor is finished. Attributes final shall not be delegated to a Setter.

Maintenance and avoiding silly errors

In addition to attributes, we can also declare the parameters as final, that is, they cannot have the value changed. Example:

public Aluno(final String n, final float n1, final float n2) {...}

How that helps?

First, you avoid silly mistakes like:

public Aluno(String nome, float nota1, float nota2) {
   this.nome = nome;
   this.nota1 = nota1;
   nota2 = nota2;
}

Believe me, I’ve corrected silly mistakes like this one above in production many times. This would be avoided if the parameters were final:

public Aluno(final String nome, final float nota1, final float nota2) {
   this.nome = nome;
   this.nota1 = nota1;
   nota2 = nota2; //erro de compilação aqui
}

This also helps to remember that you should not modify method parameters to reuse it as a variable, as if it would save memory or something like.

Running logic

If there is a need to execute some logic in the method Setter, suggest an alternative:

public Aluno(String nome, float nota1, float nota2) {
   this.nome = nome;
   this.nota1 = verificarNotaValida(nota1);
   this.nota2 = verificarNotaValida(nota2);
}

public void setNota1(float nota1) {
    this.nota1 = verificarNotaValida(nota1);
}

Extracting validation logic allows for more reuse and makes code clear.

3


Thereby:

this.nota = n1;
this.nota2 = n2;

You are accessing the variables directly. Already these two are methods that can do anything:

this.setNota1(n1);
this.setNota2(n2);

In case setNota1 be it so:

public setNota1(float n1) {
   this.nota = n1;
}

So I think it’s redundant to create a method just to set a variable, better stick with the first one same:

public Aluno(String n, float n1, float n2) {
   this.nome = n;
   this.nota = n1;
   this.nota2 = n2;
}

In case you will only use the setNota1 and setNota2 when you want to change only the notes, this I mean out of the method, so:

Foo test = new Aluno("João", 6, 6.5);

//Aqui se a condição for true ele irá mudar apenas a nota1:
if (minha condição) {
    test.setNota1(8);
}

I recommend you read:

2

Depends on what the methods setNota1() and setNota2() do. If they only assign the value of the parameter to nota and nota2 then there is no difference. Obviously if the methods do anything different, no matter how small, then there is difference.

1

Not because the attributes are all of the same class. Unless the set methods do something other than assign value to the attribute.

Browser other questions tagged

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