In general object orientation it is advisable to avoid the use of setters. The usual justification for this is that logic that modifies the state of an object must be encapsulated in the object. Therefore, the ideal is the object to expose behaviors, and these behaviors have as a side effect their state modification.
The traditional example is a class representing a bank account. Instead of using a setter to modify the balance, the balance is modified as a side effect of transactions such as transfers. It would be something like
public class ContaBancaria
{
public Saldo { get; private set; }
public bool Transfere(decimal valor, ContaBancaria conta)
{
// Logica de transferencia
}
}
It turns out that in some cases it is easy to identify the state change as a side effect of an object behavior. In the case of the account, the balance is modified when banking operations are performed. In the case of a product that has its quantity controlled in the stock, the quantity would be modified in processes of purchase and sale, etc.
The problem is that it has situations that it is really complicated to identify the state change in this way.
Some examples: a class that models a client, a class that models a user, a class that models a company.
In general these classes are part of the domain . They are concepts of the problem space, are terms of the ubiquitous language and are necessary for the operations of the domain. More than that, in general these classes have several properties.
For example: a customer has a name, has a CPF, has an associated email address, has a phone, an address, etc.
And that confuses me. Why you need to expose features to modify this state: change the name, the CPF, the email, the phone, the address, etc.
The problem is: what behavior is responsible for these changes? I think a lot and do not have it. When trying to name the method that changes the name for example, I have no idea what it would be.
If I go this way, I'll end up creating a ModificaNome
method, but this is totally equivalent to a setter.
In these cases, where we can not initially identify a behavior responsible for the state change of a set of properties, how can we avoid using setters and get good object-oriented design?