Du point de vue des principes SOLIDES , la réponse de Jgauffin est logique. Cependant, vous ne devez pas oublier les principes généraux de conception, par exemple le masquage d'informations .
Je vois plusieurs problèmes avec l'approche donnée:
- Comme vous l'avez souligné vous-même, les gens ne s'attendent pas à utiliser le mot-clé «nouveau», lorsque l'objet créé ne gère aucun état . Votre conception reflète son intention. Les utilisateurs de votre classe peuvent être confus quant à l'état dans lequel ils sont gérés et si les appels ultérieurs à la méthode peuvent entraîner un comportement différent.
- Du point de vue de la personne qui utilise la classe, l'état intérieur est bien caché, mais lorsque vous voulez apporter des modifications à la classe ou simplement la comprendre, vous complexifiez les choses. J'ai déjà beaucoup écrit sur les problèmes que je vois avec les méthodes de fractionnement juste pour les rendre plus petites , en particulier lors du déplacement de l'état dans la portée de la classe. Vous modifiez la façon dont votre API doit être utilisée juste pour avoir des fonctions plus petites! À mon avis, cela va certainement trop loin.
Quelques références liées
Peut - être un point essentiel de l' argumentation réside dans la façon dont la mesure d'étirer la responsabilité unique principe . "Si vous allez à l'extrême et que vous construisez des classes qui ont une raison d'exister, vous pouvez vous retrouver avec une seule méthode par classe. Cela entraînerait une grande prolifération de classes pour les processus les plus simples, ce qui entraînerait difficile à comprendre et difficile à changer. "
Une autre référence pertinente concernant ce sujet: "Divisez vos programmes en méthodes qui effectuent une tâche identifiable. Conservez toutes les opérations d'une méthode au même niveau d'abstraction ." - Kent Beck Key est ici "le même niveau d'abstraction". Cela ne signifie pas «une chose», comme cela est souvent interprété. Ce niveau d'abstraction dépend entièrement du contexte pour lequel vous concevez.
Quelle est donc la bonne approche?
Sans connaître votre cas concret d'utilisation, c'est difficile à dire. Il y a un scénario dans lequel j'utilise parfois (pas souvent) une approche similaire. Lorsque je souhaite traiter un ensemble de données, sans vouloir rendre cette fonctionnalité disponible pour l'ensemble de la portée de la classe. J'ai écrit un blog à ce sujet, comment les lambdas peuvent encore améliorer l'encapsulation . J'ai également commencé une question sur le sujet ici sur les programmeurs . Ce qui suit est un dernier exemple où j'ai utilisé cette technique.
new TupleList<Key, int>
{
{ Key.NumPad1, 1 },
...
{ Key.NumPad3, 16 },
{ Key.NumPad4, 17 },
}
.ForEach( t =>
{
var trigger = new IC.Trigger.EventTrigger(
new KeyInputCondition( t.Item1, KeyInputCondition.KeyState.Down ) );
trigger.ConditionsMet += () => AddMarker( t.Item2 );
_inputController.AddTrigger( trigger );
} );
Étant donné que le code très «local» dans le ForEach
n'est réutilisé nulle part ailleurs, je peux simplement le conserver à l'emplacement exact où il est pertinent. Décrire le code de telle manière que le code qui dépend les uns des autres est fortement regroupé le rend plus lisible à mon avis.
Alternatives possibles
- En C #, vous pouvez utiliser des méthodes d'extension à la place. Opérez donc directement sur l'argument que vous passez à cette méthode «une chose».
- Vérifiez si cette fonction n'appartient pas à une autre classe.
- Faites-en une fonction statique dans une classe statique . C'est probablement l'approche la plus appropriée, comme le reflètent également les API générales que vous avez mentionnées.
bool arrayContainsSomestring = new List<string>(stringArray).Contains("somestring");
quand tout ce qui m'intéressait était cette information particulière et les méthodes d'extension LINQ ne sont pas disponibles. Fonctionne bien et s'adapte à l'intérieur d'uneif()
condition sans avoir besoin de sauter à travers des cerceaux. Bien sûr, vous voulez un langage récupéré si vous écrivez du code comme ça.