J'ai un problème de conception sur lequel je pourrais utiliser quelques conseils. Disons que nous avons besoin (comment original ...) Employés dans notre nouvelle application. Ce que je normalement faire est quelque chose comme ceci:Utilisation d'accesseurs: bon ou mauvais?
public interface IEmployee
{
string EmployeeId { get; }
string Name { get; }
void Update(string newName, ...);
...
}
public class Employee : IEmployee
{
public Employee(string id, string name, ...)
{
}
...
}
Cette obtient les employés de la source de données
public class SqlEmployeeRepository : IEmployeeRepository
{
...
public IEmployee GetEmployee(string id)
{
...
IEmployee employee = new Employee(id, name, ...);
return employee
}
public IEmployee SaveEmployee(IEmployee employee)
{
// Execute SQL command.
}
}
Visualizing ressemblerait à quelque chose comme ceci:
TextBox nameTextBox = new TextBox();
...
nameTextBox.Text = employee.Name;
Et sauver regarderait comme ceci:
string name = nameTextBox.Text;
employee.Update(name, ...);
myEmployeeRepository.Save(employee);
Jusqu'ici, tout va bien. Mais alors j'ai couru this et this article et ils m'ont fait me demander ce que l'application ressemblerait (statiquement et dynamiquement) sans les getters, donc j'ai essayé d'implémenter l'application ci-dessus sans getter en utilisant la technique décrite dans le deuxième article. Je suis venu avec ceci:
public interface IEmployee
{
public interface Importer
{
string ProvideId();
string ProvideName();
...
}
public interface Exporter
{
void AddId();
void AddName();
...
}
void Export(IExporter exporter)
...
}
public class Employee : IEmployee
{
private string _id;
private string _name;
public Employee(IEmployee.Importer importer)
{
_id = importer.ProvideId();
_name = importer.ProvideName();
...
}
public void Export(IEmployee.Exporter exporter)
{
exporter.AddId(_id);
exporter.AddName(_name);
...
}
}
Ensuite, le dépôt devient:
public class SqlEmployeeExporter : IEmployee.Exporter
{
...
public void Save() { ... }
}
public class SqlEmployeeRepository : IEmployeeRepository
{
...
public IEmployee GetEmployee(string id)
{
IEmployee.Importer importer = new SqlEmployeeImporter(id);
IEmployee employee = new Employee(importer);
return employee
}
public IEmployee SaveEmployee(IEmployee employee)
{
SqlEmployeeExporter exporter = new SqlEmployeeExporter();
employee.Export(exporter);
exporter.Save();
}
}
Visualizing devient:
EmployeeNameTextBoxExporter exporter = new EmployeeNameTextBoxExporter();
employee.Export(exporter);
exporter.Render();
Et quelque chose similair pour économiser.
Bien que cette dernière implémentation ait supprimé la nécessité pour les getters sur Employee
et constitue ainsi la meilleure forme d'encapsulation de données, elle semble également un peu trop lourde et trop complexe. Quelle est votre opinion sur ce sujet? Ai-je manqué ou mal interprété quelque chose dans les articles? Quelle est votre opinion générale sur l'utilisation des getters (et setters)?
Cette petite expérience me donne tendance à utiliser l'approche accesseur pour le moment. Peut-être que vous pouvez changer d'avis :-)
Il semble que votre objet 'Exporter' est vraiment un objet DTO: http://en.wikipedia.org/wiki/Data_transfer_object – Sjoerd
Les articles auxquels vous faites référence sont plutôt controversés (en particulier le titre) et devraient être pris avec une pincée de sel :-) La compréhension commune est, ils ne sont pas contre les getters/setters en général, seulement contre exposer _ getecessary getters/setters. Cela a déjà été discuté sur SO, par ex. http://stackoverflow.com/questions/2747721/getters-and-setters-are-bad-oo-design, http://stackoverflow.com/questions/565095/java-are-getters-and-setters-evil –