2010-09-10 3 views
4

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 :-)

+0

Il semble que votre objet 'Exporter' est vraiment un objet DTO: http://en.wikipedia.org/wiki/Data_transfer_object – Sjoerd

+0

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 –

Répondre

1

En regardant un extrait de code court apparaîtra naturellement simpliste et ne nécessiterait pas une telle encapsulation. À mesure que la taille du programme augmente, je peux voir cette approche gagner du temps lors de la maintenance. Je n'ai pas beaucoup d'expérience avec cette approche, donc je suis incapable de donner une réponse définitive, mais je pense que cela peut fournir suffisamment d'avantages pour être utile d'essayer et de mesurer les résultats.

Pour la lisibilité, je pense que cette approche présente certains avantages par rapport aux getters/setters. Supposons que vous voulez afficher l'horaire de travail de l'employé sous forme de tableau.En utilisant l'approche « constructeur », le code de haut niveau reste essentiellement inchangé:

ScheduleDisplay display = new TableScheduleDisplay(); 
employee.Export(display); 
display.Render(); 

Ceci est beaucoup plus facile à lire qu'une liste d'instructions dont le but principal est d'extraire des données à partir d'un objet et le placer dans un autre objet . Je sais d'un coup d'oeil que ce code affiche le calendrier sous forme de tableau.

3

Je pense que les accesseurs (getters et setters) sont bien meilleurs, du moins dans votre exemple. Je ne vois aucun avantage à utiliser le pattern DTO ici, et le plus important, le code devient illisible. Un sur la clé pour écrire un bon logiciel est la simplicité: plus le code est simple, plus il est lisible et maintenable. Le motif, en général, devrait être utilisé quand il résout un problème. Donc, vous devez d'abord détecter un problème puis le résoudre en appliquant le modèle le plus simple pour résoudre le problème. Le choix d'utiliser le modèle DTO devrait être supporté par le fait qu'il résout un problème spécifique.

+0

D'accord complètement. Les propriétés semblent beaucoup plus familier je pense. Règles de lisibilité :) – dmitko

Questions connexes