37 votes

Surcharge des méthodes. Peut-on en abuser ?

Quelle est la meilleure pratique pour définir plusieurs méthodes qui renvoient la même forme de données avec des filtres différents ? Des noms de méthodes explicites ou des méthodes surchargées ?

Par exemple. Si j'ai des produits et que je les tire d'une base de données

de manière explicite :

public List<Product> GetProduct(int productId) {    // return a List    }
public List<Product> GetProductByCategory(Category category) {    // return a List    }
public List<Product> GetProductByName(string Name ) {    // return a List    }

de manière surchargée :

public List<Product> GetProducts() {    // return a List of all products    }
public List<Product> GetProducts(Category category) { // return a List by Category }
public List<Product> GetProducts(string searchString ) { // return a List by search string }

Je me rends compte que vous risquez d'avoir un problème avec signatures similaires Mais si vous passez des objets au lieu de types de base (string, int, char, DateTime, etc.), le problème se posera moins. Alors... est-ce une bonne idée de surcharger une méthode pour réduire le nombre de méthodes et pour plus de clarté, o devrait chaque méthode qui filtre les données d'une manière différente ont un nom de méthode différent ?

44voto

Bevan Points 20976

Oui, la surcharge peut facilement être utilisée de manière excessive.

J'ai découvert que la clé pour déterminer si une surcharge est justifiée ou non est de prendre en compte le public - pas le compilateur, mais le programmeur de maintenance qui arrivera dans quelques semaines/mois/années et qui doit comprendre ce que le code essaie de réaliser.

Un nom de méthode simple comme GetProducts() est clair et compréhensible, mais il laisse beaucoup de choses en suspens.

Dans de nombreux cas, si les paramètres passés à GetProducts() sont bien nommés, le responsable de la maintenance sera en mesure de comprendre ce que fait la surcharge - mais cela dépend d'une bonne discipline de nommage au point d'utilisation, que vous ne pouvez pas imposer. Ce que vous pouvez imposer, c'est le nom de la méthode qu'ils appellent.

La ligne directrice que je suis est de ne surcharger les méthodes que si elles sont interchangeables, c'est-à-dire si elles font la même chose. De cette façon, je ne me soucie pas de la version invoquée par le consommateur de ma classe, puisqu'elles sont équivalentes.

Pour illustrer mon propos, j'utiliserais volontiers des surcharges pour la méthode DeleteFile() :

void DeleteFile(string filePath);
void DeleteFile(FileInfo file);
void DeleteFile(DirectoryInfo directory, string fileName);

Toutefois, pour vos exemples, j'utiliserais des noms distincts :

public IList<Product> GetProductById(int productId) {...}
public IList<Product> GetProductByCategory(Category category) {...}
public IList<Product> GetProductByName(string Name ) {...}

Le fait d'avoir les noms complets rend le code plus explicite pour le responsable de la maintenance (qui pourrait bien être moi). Cela évite les problèmes de collisions de signatures :

// No collisions, even though both methods take int parameters
public IList<Employee> GetEmployeesBySupervisor(int supervisorId);
public IList<Employee> GetEmployeesByDepartment(int departmentId);

Il est également possible d'introduire une surcharge pour chaque objectif :

// Examples for GetEmployees

public IList<Employee> GetEmployeesBySupervisor(int supervisorId);
public IList<Employee> GetEmployeesBySupervisor(Supervisor supervisor);
public IList<Employee> GetEmployeesBySupervisor(Person supervisor);

public IList<Employee> GetEmployeesByDepartment(int departmentId);
public IList<Employee> GetEmployeesByDepartment(Department department);

// Examples for GetProduct

public IList<Product> GetProductById(int productId) {...}
public IList<Product> GetProductById(params int[] productId) {...}

public IList<Product> GetProductByCategory(Category category) {...}
public IList<Product> GetProductByCategory(IEnumerable<Category> category) {...}
public IList<Product> GetProductByCategory(params Category[] category) {...}

Le code est lu beaucoup plus souvent qu'il n'est écrit - même si vous ne revenez jamais au code après l'enregistrement initial dans le contrôle de la source, vous lirez toujours cette ligne de code quelques dizaines de fois pendant que vous écrivez le code qui suit.

Enfin, à moins que vous n'écriviez du code jetable, vous devez permettre à d'autres personnes d'appeler votre code à partir d'autres langages. Il semble que la plupart des systèmes d'entreprise restent en production bien au-delà de leur date limite d'utilisation. Il se peut que le code qui utilise votre classe en 2016 soit écrit en VB.NET, C# 6.0, F# ou quelque chose de complètement nouveau qui n'a pas encore été inventé. Il se peut que le langage ne prenne pas en charge les surcharges.

16voto

Elie Points 7628

Pour autant que je sache, il n'y aura pas moins de méthodes, mais moins de noms. Je préfère généralement le système de désignation des méthodes surchargées, mais je ne pense pas que cela fasse une grande différence tant que vous commentez et documentez bien votre code (ce que vous devriez faire dans les deux cas).

15voto

stephenbayer Points 5548

Peut-on en abuser ? Oui, c'est vrai.

Cependant, les exemples que vous avez donnés sont des exemples parfaits de l'utilisation de la surcharge des méthodes. Elles exécutent toutes la même fonction, pourquoi leur donner des noms différents simplement parce que vous leur passez des types différents.

La règle principale est de faire ce qui est le plus clair et le plus facile à comprendre. N'utilisez pas la surcharge juste pour être malin ou intelligent, faites-le quand c'est logique. D'autres développeurs peuvent également travailler sur ce code. Vous devez faire en sorte qu'il soit aussi facile que possible pour eux de prendre et de comprendre le code et d'être en mesure de mettre en œuvre des changements sans implémenter de bogues.

11voto

Jeremy Reagan Points 681

J'aime surcharger mes méthodes afin de ne pas avoir plus tard dans l'intellisense un million de la même méthode. Et il me semble plus logique de la surcharger plutôt que de la nommer différemment une douzaine de fois.

5voto

Joe Points 60749

Il faut savoir qu'il n'est pas possible d'exposer des méthodes surchargées en tant que contrats d'opération dans un service Web WCF. Par conséquent, si vous pensez avoir besoin de le faire un jour, ce serait un argument en faveur de l'utilisation de noms de méthodes différents.

Un autre argument en faveur de noms de méthodes différents est qu'ils peuvent être plus facilement repérables à l'aide d'intellisense.

Mais il y a des avantages et des inconvénients pour l'un ou l'autre choix - toute conception est un compromis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X