L'interface List est-elle une abstraction qui fuit?

9

Si j'ai une variable contenant un, Listil pourrait contenir des objets de nombreux types différents, par exemple ArrayListou LinkedList. La différence entre a LinkedListet an ArrayListest assez grande. Le grand comportement O des méthodes diffère considérablement. Par exemple, trier le List, puis l'utiliser pour effectuer des recherches binaires est parfaitement correct pour un, ArrayListmais n'aurait aucun sens avec un LinkedList.

Palissade
la source
Que signifie "le grand O"?
Tulains Córdova

Réponses:

25

Je ne dirais pas ça.

Une abstraction qui fuit est celle qui vous oblige à traiter les détails d'implémentation qu'elle est censée supprimer. Mais les performances diffèrent toujours entre les implémentations, donc si vous considérez cela comme une fuite, il n'y a pas d'abstractions qui ne fuient pas.

Si quelque chose est déclaré comme Listsans documentation supplémentaire, il faut comprendre qu'il n'y a tout simplement aucune garantie sur les performances, et si vous allez faire quoi que ce soit de sensible aux performances, vous devez en faire une copie et travailler avec.

En outre, ne pas oublier qu'il ya une interface encore plus générale qui est souvent suffisante dans la fonctionnalité et ne vous tente pas de faire autant d'hypothèses sur les performances: Collection.

Michael Borgwardt
la source
9
Il existe une interface encore plus générale qui est souvent suffisante dans la fonctionnalité: Iterable.
emory
Des différences de performances entre les différentes implémentations sont attendues. Par exemple, il existe des différences entre Vector et ArrayList, mais une opération get sur une LinkedList semble tout simplement étrange.
Paling
17

Toutes les abstractions non triviales, dans une certaine mesure, sont fuyantes. Cela dit, je ne suis pas vraiment sûr que cela s'applique ici. :-)

Les abstractions concernent le comportement. À moins que le comportement ne spécifie des performances particulières (ce que Java Listne fait pas), c'est un détail d'implémentation - c'est-à-dire non pertinent.

Java ne vous permet pas de spécifier des performances minimales pour les interfaces en dehors de la documentation, et je ne connais aucun langage qui le fasse - il serait incroyablement difficile (impossible?) Pour le compilateur de vérifier. Je peux voir quelques options si les performances sont un problème:

  1. Documentez-le dans la classe / interface à laquelle l'instance de liste appartiendra.
  2. Créez une nouvelle interface - par exemple BinarySearchPerformantList(beurk!) - qui spécifie les exigences de performance des différentes méthodes.

L'option 2 est probablement la meilleure abstraction, mais elle s'accompagne d'une surcharge supplémentaire.

vaughandroid
la source
1
+1. Techniquement oui, une liste est une abstraction qui fuit , mais il en va de même pour l'objet pour masquer la complexité liée à l'utilisation equalspour comparer des objets.
Neil
2
@Neil Je pense que c'est discutable ... Puisque l'abstraction ne mentionne pas la performance, je ne pense pas que cela échoue dans ce cas (comme je l'ai soutenu). Je dirais que si vous pensez à la performance, vous avez besoin d'une abstraction différente / plus étroite. Éditera pour le mentionner.
vaughandroid
Cela dépend de ce que vous cachez, je suppose. La complexité est-elle dans l'utilisation ou est-ce dans l'utilisation et l'implémentation de la mémoire? Parce que s'il s'agit d'une classe abstraite, une ou plusieurs de ces complexités se cachent d'une manière ou d'une autre.
Neil
J'ai joué il y a plusieurs années la mise en œuvre d' une variante de l' option 2 en utilisant des interfaces marqueurs comme LinearSpaceet LogarithmicTimepuis déclarer des classes comme public class BinarySearch : ISearchStrategy<T>, LogarithmicTime. D'autres classes pourraient prendre des paramètres comme public T find<T, S>(IList<T> list, S strategy) where S : ISearchStrategy<T>, LogarithmicTime { }pour imposer des contraintes de performances.
Lucas
2
Si nous nous basons sur l'article de Joel Spolsky, je pense qu'il est "dans une certaine mesure, qui fuit". Voir la citation suivante de l'article: "Si vous étiez courtois avec les administrateurs système de votre entreprise et qu'ils vous punissaient en vous branchant sur un concentrateur surchargé, seuls certains de vos paquets IP passeraient et TCP fonctionnerait, mais tout fonctionnerait être vraiment lent "Je pense que cela s'applique
Amish Programmer
4

En Java, il existe une interface RandomAccess qui est définie comme une liste avec un temps d'accès aléatoire généralement constant (O (1) get, put etc.). Si vous pensez que votre module nécessite une liste avec ces caractéristiques de performances, pensez à utiliser à la RandomAccessplace de List. Si vous ne ressentez pas le besoin d'apporter ce changement (et peu le font), alors peut-être que List n'est pas si fuit.

MikeFHay
la source
1

Vous avez raison, une liste est une abstraction qui fuit. La STL utilise l'idée de concepts pour modéliser ce problème spécifique. Pour utiliser votre exemple, un ArrayListmodèle un itérateur à accès aléatoire tandis qu'un LinkedList modélise un itérateur avancé . Différents concepts ont des exigences de performances différentes, ce qui les rend appropriés pour différents algorithmes .

Matthew Finlay
la source