Multiplication des interfaces ou usage immodéré des UnsupportedOperationException
7 réponses
MattBan
Bonjour.
Je suis tr=E8s fier de mon titre. Je vous explique mon probl=E8me. J'=E9cris
des interfaces et des classes, et certaines classes n'impl=E9mentent
certaines fonctionnalit=E9s de mes interfaces. Dois-je donc ajouter des
interfaces pour ces classes ou autoriser que mon impl=E9mentation
balance un UnsupportedOperationException.
Explication sur un exemple concret.
Le package java.util contient une interface Iterator qui comprend une
m=E9thode 'remove()'. Cette m=E9thode n'est cependant pas autoris=E9e par
toutes les impl=E9mentations. Voir la doc :
=AB
Throws:
UnsupportedOperationException - if the remove operation is not
supported by this Iterator.
=BB
Mais moi, je trouve =E7a super inqui=E9tant. =C7a veut dire que si j'utilise
un it=E9rateur sur une collection g=E9n=E9r=E9(e) par une impl=E9mentation
tierce, je dois (dans le meilleur des cas) regarder la doc pour
v=E9rifier si la m=E9thode est autoris=E9e, et dans le pire des cas croiser
les doigts. On pourra me r=E9pondre que le fait d'avoir le droit de
supprimer l'=E9l=E9ment d=E9rive logiquement de la d=E9finition de la class=
e,
mais je ne suis pas d'accord et puis =E7a n=E9cessite de toute fa=E7on une
gymnastique intellectuelle non n=E9gligeable. Bref, je trouve =E7a peu
pratique.
L'autre approche serait de cr=E9er une interface UnmodifiableIterator,
=E9tendue par Iterator, qui ne requiert que l'impl=E9mentation de next()
et hasNext(). En plus, =E7a permet de d=E9grader facilement les
possibilit=E9s de l'utilisateur de votre code puisque vous pouvez
renvoyer un UnmodifiableIterator qui est en fait un Iterator, alors
que dans l'impl=E9mentation actuelle il faut passer par
Collections.unmodifiableCollection(Collection c).iterator(). Je vois
bien les probl=E8mes de cette seconde approche : on cr=E9e un grand nombre
d'interface suppl=E9mentaires, notamment si on a un grand nombre de
m=E9thodes qui peuvent ind=E9pendamment =EAtre support=E9es ou pas.
Quel est votre avis sur le sujet ? Faut-il privil=E9gier la seconde
approche quand on a peu de m=E9thodes qui posent probl=E8me ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Black Myst
Bonjour.
(...)
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde approche quand on a peu de méthodes qui posent problème ?
Je pense que dans ce cas précis, tu aborde le problème par le mauvais coté. Pour ce qui est de la gestion des collections en Java, on peut dire que dans 99% des cas, le développeur à besoin d'une liste modifiable.
En fait, je ne vois qu'un seul cas ou on veut rendre une liste immuable, c'est lorsque l'on fait de la programmation défensive, pour ne pas exposer la représentation interne de notre classe à l'extérieur et que l'on souhaite éviter le clone pour des questions de performance.
Dans le cas de programmation défensive, il suffira de préciser dans la doc que la liste renvoyée est immuable. Par défaut on considérera toutes collection mutable.
Pour en revenir à ta question, je dirais que que cela dépends du cas général. Si ton interface définie une méthode suffisamment particulières et que tu sais pertinemment que la plupart des impléms ne pourront pas y répondre, alors il faut peut-être envisager de découper en plusieurs interfaces.
De l'autre coté, il arrive parfois d'avoir des solutions optimisés pour implémenter ton interface, mais qui rendes certaine action impossible. Dans ce cas, un bon commentaire et un UnsupportedOperationException peuvent être une solution tout à fait pertinente.
Une dernière possibilité peut être de donner le moyen à l'implémentation, au travers de l'interface, de dire qi elle est capable de gérer certaine fonctionnalité
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde
approche quand on a peu de méthodes qui posent problème ?
Je pense que dans ce cas précis, tu aborde le problème par le mauvais
coté. Pour ce qui est de la gestion des collections en Java, on peut
dire que dans 99% des cas, le développeur à besoin d'une liste modifiable.
En fait, je ne vois qu'un seul cas ou on veut rendre une liste immuable,
c'est lorsque l'on fait de la programmation défensive, pour ne pas
exposer la représentation interne de notre classe à l'extérieur et que
l'on souhaite éviter le clone pour des questions de performance.
Dans le cas de programmation défensive, il suffira de préciser dans la
doc que la liste renvoyée est immuable. Par défaut on considérera toutes
collection mutable.
Pour en revenir à ta question, je dirais que que cela dépends du cas
général. Si ton interface définie une méthode suffisamment particulières
et que tu sais pertinemment que la plupart des impléms ne pourront pas y
répondre, alors il faut peut-être envisager de découper en plusieurs
interfaces.
De l'autre coté, il arrive parfois d'avoir des solutions optimisés pour
implémenter ton interface, mais qui rendes certaine action impossible.
Dans ce cas, un bon commentaire et un UnsupportedOperationException
peuvent être une solution tout à fait pertinente.
Une dernière possibilité peut être de donner le moyen à
l'implémentation, au travers de l'interface, de dire qi elle est capable
de gérer certaine fonctionnalité
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde approche quand on a peu de méthodes qui posent problème ?
Je pense que dans ce cas précis, tu aborde le problème par le mauvais coté. Pour ce qui est de la gestion des collections en Java, on peut dire que dans 99% des cas, le développeur à besoin d'une liste modifiable.
En fait, je ne vois qu'un seul cas ou on veut rendre une liste immuable, c'est lorsque l'on fait de la programmation défensive, pour ne pas exposer la représentation interne de notre classe à l'extérieur et que l'on souhaite éviter le clone pour des questions de performance.
Dans le cas de programmation défensive, il suffira de préciser dans la doc que la liste renvoyée est immuable. Par défaut on considérera toutes collection mutable.
Pour en revenir à ta question, je dirais que que cela dépends du cas général. Si ton interface définie une méthode suffisamment particulières et que tu sais pertinemment que la plupart des impléms ne pourront pas y répondre, alors il faut peut-être envisager de découper en plusieurs interfaces.
De l'autre coté, il arrive parfois d'avoir des solutions optimisés pour implémenter ton interface, mais qui rendes certaine action impossible. Dans ce cas, un bon commentaire et un UnsupportedOperationException peuvent être une solution tout à fait pertinente.
Une dernière possibilité peut être de donner le moyen à l'implémentation, au travers de l'interface, de dire qi elle est capable de gérer certaine fonctionnalité
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde approche quand on a peu de méthodes qui posent problème ?
Je suis tout à fait d'accord avec toi, et regrette également l'apparition de méthodes susceptibles d'envoyer cet "unsupported" dans le jdk.
Moi je l'utilise lorsque je ne sais pas très bien comment définir une interface ou une classe, avec toute sa parentée ; j'y mets alors des Unsupported, en me disant que si je tombe dessus, je l'écrirai. Netbeans fonctionne aussi quelque fois comme ça, quand on lui demande de générer des classes automatiquement, il remplit le bloc avec un Unsupported ; je trouve ça bien.
Je l'utilise donc plutôt pour faciliter le refactoring. Normalement, à la livraison, il n'y en a plus :-)
-- Hervé AGNOUX http://www.diaam-informatique.com
MattBan wrote:
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde
approche quand on a peu de méthodes qui posent problème ?
Je suis tout à fait d'accord avec toi, et regrette également l'apparition de
méthodes susceptibles d'envoyer cet "unsupported" dans le jdk.
Moi je l'utilise lorsque je ne sais pas très bien comment définir une
interface ou une classe, avec toute sa parentée ; j'y mets alors des
Unsupported, en me disant que si je tombe dessus, je l'écrirai. Netbeans
fonctionne aussi quelque fois comme ça, quand on lui demande de générer des
classes automatiquement, il remplit le bloc avec un Unsupported ; je trouve
ça bien.
Je l'utilise donc plutôt pour faciliter le refactoring. Normalement, à la
livraison, il n'y en a plus :-)
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde approche quand on a peu de méthodes qui posent problème ?
Je suis tout à fait d'accord avec toi, et regrette également l'apparition de méthodes susceptibles d'envoyer cet "unsupported" dans le jdk.
Moi je l'utilise lorsque je ne sais pas très bien comment définir une interface ou une classe, avec toute sa parentée ; j'y mets alors des Unsupported, en me disant que si je tombe dessus, je l'écrirai. Netbeans fonctionne aussi quelque fois comme ça, quand on lui demande de générer des classes automatiquement, il remplit le bloc avec un Unsupported ; je trouve ça bien.
Je l'utilise donc plutôt pour faciliter le refactoring. Normalement, à la livraison, il n'y en a plus :-)
-- Hervé AGNOUX http://www.diaam-informatique.com
Maxime Daniel
On 8 juin, 20:34, Hervé AGNOUX informatique.com.zz> wrote:
MattBan wrote:
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde approche quand on a peu de méthodes qui posent problème ?
Je suis tout à fait d'accord avec toi, et regrette également l'appari tion de méthodes susceptibles d'envoyer cet "unsupported" dans le jdk. Hervé, je crois pour ma part que cette introduction vient de la
volonté de faire un arbitrage assez fin entre le design propre et bien général du besoin, qui introduit les "méthodes naturelles" sur l'interface considérée, et une implémentation partielle possible pour assurer l'implémentation d'une qualité de service différente (on sacrifie alors l'implémentation complète de l'interface pour fournir une classe plus rapide ou moins gourmande en mémoire ou les deux). L'emploi de ce pattern avec cet objectif nécessite à mon avis une grande maturation du design, beaucoup de recul, et ne devrait pas être envisagé sans être prêt à itérer sur la conception. C'est d'une certaine façon une approche qui, a posteriori, retire des implémentations de méthodes jugées trop dispendieuses.
On 8 juin, 20:34, Hervé AGNOUX <herve.xx.agn...@diaam-
informatique.com.zz> wrote:
MattBan wrote:
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde
approche quand on a peu de méthodes qui posent problème ?
Je suis tout à fait d'accord avec toi, et regrette également l'appari tion de
méthodes susceptibles d'envoyer cet "unsupported" dans le jdk.
Hervé, je crois pour ma part que cette introduction vient de la
volonté de faire un arbitrage assez fin entre le design propre et bien
général du besoin, qui introduit les "méthodes naturelles" sur
l'interface considérée, et une implémentation partielle possible pour
assurer l'implémentation d'une qualité de service différente (on
sacrifie alors l'implémentation complète de l'interface pour fournir
une classe plus rapide ou moins gourmande en mémoire ou les deux).
L'emploi de ce pattern avec cet objectif nécessite à mon avis une
grande maturation du design, beaucoup de recul, et ne devrait pas être
envisagé sans être prêt à itérer sur la conception. C'est d'une
certaine façon une approche qui, a posteriori, retire des
implémentations de méthodes jugées trop dispendieuses.
On 8 juin, 20:34, Hervé AGNOUX informatique.com.zz> wrote:
MattBan wrote:
Quel est votre avis sur le sujet ? Faut-il privilégier la seconde approche quand on a peu de méthodes qui posent problème ?
Je suis tout à fait d'accord avec toi, et regrette également l'appari tion de méthodes susceptibles d'envoyer cet "unsupported" dans le jdk. Hervé, je crois pour ma part que cette introduction vient de la
volonté de faire un arbitrage assez fin entre le design propre et bien général du besoin, qui introduit les "méthodes naturelles" sur l'interface considérée, et une implémentation partielle possible pour assurer l'implémentation d'une qualité de service différente (on sacrifie alors l'implémentation complète de l'interface pour fournir une classe plus rapide ou moins gourmande en mémoire ou les deux). L'emploi de ce pattern avec cet objectif nécessite à mon avis une grande maturation du design, beaucoup de recul, et ne devrait pas être envisagé sans être prêt à itérer sur la conception. C'est d'une certaine façon une approche qui, a posteriori, retire des implémentations de méthodes jugées trop dispendieuses.
Hervé AGNOUX
Maxime Daniel wrote:
Hervé, je crois pour ma part que cette introduction vient de la volonté de faire un arbitrage assez fin entre le design propre et bien général du besoin, qui introduit les "méthodes naturelles" sur l'interface considérée, et une implémentation partielle possible pour assurer l'implémentation d'une qualité de service différente (on sacrifie alors l'implémentation complète de l'interface pour fournir une classe plus rapide ou moins gourmande en mémoire ou les deux). L'emploi de ce pattern avec cet objectif nécessite à mon avis une grande maturation du design, beaucoup de recul, et ne devrait pas être envisagé sans être prêt à itérer sur la conception. C'est d'une certaine façon une approche qui, a posteriori, retire des implémentations de méthodes jugées trop dispendieuses.
Oui, il faut faire des compromis. Mais, là où tu parles de "arbitrage assez fin", je parlerais, moi, de "arbitrage assez grossier" :-)
Il est vrai que c'est une technique pour définir les interfaces : on y met tous les possibles, prétendument assuré d'avoir ainsi réponse à tout. Je n'aime pas beaucoup cette approche, y préférant celle qui consiste à proposer une organisation de ces possibles, organisation qui prend le risque d'être mauvaise.
J'admets que le paquetage des collections est plutôt dans la seconde approche (proposer une organisation) que dans la première, donc c'est bon.
-- Hervé AGNOUX http://www.diaam-informatique.com
Maxime Daniel wrote:
Hervé, je crois pour ma part que cette introduction vient de la
volonté de faire un arbitrage assez fin entre le design propre et bien
général du besoin, qui introduit les "méthodes naturelles" sur
l'interface considérée, et une implémentation partielle possible pour
assurer l'implémentation d'une qualité de service différente (on
sacrifie alors l'implémentation complète de l'interface pour fournir
une classe plus rapide ou moins gourmande en mémoire ou les deux).
L'emploi de ce pattern avec cet objectif nécessite à mon avis une
grande maturation du design, beaucoup de recul, et ne devrait pas être
envisagé sans être prêt à itérer sur la conception. C'est d'une
certaine façon une approche qui, a posteriori, retire des
implémentations de méthodes jugées trop dispendieuses.
Oui, il faut faire des compromis. Mais, là où tu parles de "arbitrage assez
fin", je parlerais, moi, de "arbitrage assez grossier" :-)
Il est vrai que c'est une technique pour définir les interfaces : on y met
tous les possibles, prétendument assuré d'avoir ainsi réponse à tout. Je
n'aime pas beaucoup cette approche, y préférant celle qui consiste à
proposer une organisation de ces possibles, organisation qui prend le
risque d'être mauvaise.
J'admets que le paquetage des collections est plutôt dans la seconde
approche (proposer une organisation) que dans la première, donc c'est bon.
Hervé, je crois pour ma part que cette introduction vient de la volonté de faire un arbitrage assez fin entre le design propre et bien général du besoin, qui introduit les "méthodes naturelles" sur l'interface considérée, et une implémentation partielle possible pour assurer l'implémentation d'une qualité de service différente (on sacrifie alors l'implémentation complète de l'interface pour fournir une classe plus rapide ou moins gourmande en mémoire ou les deux). L'emploi de ce pattern avec cet objectif nécessite à mon avis une grande maturation du design, beaucoup de recul, et ne devrait pas être envisagé sans être prêt à itérer sur la conception. C'est d'une certaine façon une approche qui, a posteriori, retire des implémentations de méthodes jugées trop dispendieuses.
Oui, il faut faire des compromis. Mais, là où tu parles de "arbitrage assez fin", je parlerais, moi, de "arbitrage assez grossier" :-)
Il est vrai que c'est une technique pour définir les interfaces : on y met tous les possibles, prétendument assuré d'avoir ainsi réponse à tout. Je n'aime pas beaucoup cette approche, y préférant celle qui consiste à proposer une organisation de ces possibles, organisation qui prend le risque d'être mauvaise.
J'admets que le paquetage des collections est plutôt dans la seconde approche (proposer une organisation) que dans la première, donc c'est bon.
-- Hervé AGNOUX http://www.diaam-informatique.com
Maxime Daniel
On 9 juin, 12:03, Hervé AGNOUX informatique.com.zz> wrote: ...
Oui, il faut faire des compromis. Mais, là où tu parles de "arbitrage assez fin", je parlerais, moi, de "arbitrage assez grossier" :-) ...
Je viens de relire la classe Iterator de Java 1.5 et je maintiens le 'assez fin'. Iterator a les méthodes hasNext, next et remove. hasNext et next constituent un noyau dur de la fonctionnalité (on pourrait se passer de hasNext, mais le pattern classique propose hasNext et les développeurs qui adhèrent aux thèses de Meyer sur les prérequis préfèrent n'appeler next qu'à coup sûr, plutôt que de traiter une exception). remove est très désirable par une prolongation naturelle du design minimaliste. A posteriori cependant, on se rend compte que les implémentations les plus efficaces pour certaines structures de données sont incapables de fournir remove, et on décide donc de le rendre facultatif. L'alternative est alors de créer une interface héritière MutableIterator et de supprimer remove de Iterator, ou bien de trouver une astuce pour autoriser certaines implémentations à ne pas implémenter remove. La décision qui a été prise (seconde approc he) s'appuie sur des jugements de valeur quant à l'équilibre général de l'API, son nombre de classes et d'interfaces, la granularité des interfaces les plus utilisées, etc. Elle n'est forcément pas exempte de reproches, mais résulte de l'examen poussé de notions subtiles. C'est donc un arbitrage 'assez fin'...
On 9 juin, 12:03, Hervé AGNOUX <herve.xx.agn...@diaam-
informatique.com.zz> wrote:
...
Oui, il faut faire des compromis. Mais, là où tu parles de "arbitrage assez
fin", je parlerais, moi, de "arbitrage assez grossier" :-)
...
Je viens de relire la classe Iterator de Java 1.5 et je maintiens le
'assez fin'. Iterator a les méthodes hasNext, next et remove. hasNext
et next constituent un noyau dur de la fonctionnalité (on pourrait se
passer de hasNext, mais le pattern classique propose hasNext et les
développeurs qui adhèrent aux thèses de Meyer sur les prérequis
préfèrent n'appeler next qu'à coup sûr, plutôt que de traiter une
exception). remove est très désirable par une prolongation naturelle
du design minimaliste. A posteriori cependant, on se rend compte que
les implémentations les plus efficaces pour certaines structures de
données sont incapables de fournir remove, et on décide donc de le
rendre facultatif. L'alternative est alors de créer une interface
héritière MutableIterator et de supprimer remove de Iterator, ou bien
de trouver une astuce pour autoriser certaines implémentations à ne
pas implémenter remove. La décision qui a été prise (seconde approc he)
s'appuie sur des jugements de valeur quant à l'équilibre général de
l'API, son nombre de classes et d'interfaces, la granularité des
interfaces les plus utilisées, etc. Elle n'est forcément pas exempte
de reproches, mais résulte de l'examen poussé de notions subtiles.
C'est donc un arbitrage 'assez fin'...
On 9 juin, 12:03, Hervé AGNOUX informatique.com.zz> wrote: ...
Oui, il faut faire des compromis. Mais, là où tu parles de "arbitrage assez fin", je parlerais, moi, de "arbitrage assez grossier" :-) ...
Je viens de relire la classe Iterator de Java 1.5 et je maintiens le 'assez fin'. Iterator a les méthodes hasNext, next et remove. hasNext et next constituent un noyau dur de la fonctionnalité (on pourrait se passer de hasNext, mais le pattern classique propose hasNext et les développeurs qui adhèrent aux thèses de Meyer sur les prérequis préfèrent n'appeler next qu'à coup sûr, plutôt que de traiter une exception). remove est très désirable par une prolongation naturelle du design minimaliste. A posteriori cependant, on se rend compte que les implémentations les plus efficaces pour certaines structures de données sont incapables de fournir remove, et on décide donc de le rendre facultatif. L'alternative est alors de créer une interface héritière MutableIterator et de supprimer remove de Iterator, ou bien de trouver une astuce pour autoriser certaines implémentations à ne pas implémenter remove. La décision qui a été prise (seconde approc he) s'appuie sur des jugements de valeur quant à l'équilibre général de l'API, son nombre de classes et d'interfaces, la granularité des interfaces les plus utilisées, etc. Elle n'est forcément pas exempte de reproches, mais résulte de l'examen poussé de notions subtiles. C'est donc un arbitrage 'assez fin'...
Hervé AGNOUX
Maxime Daniel wrote:
interfaces les plus utilisées, etc. Elle n'est forcément pas exempte de reproches, mais résulte de l'examen poussé de notions subtiles. C'est donc un arbitrage 'assez fin'...
Je n'ai pas accès à toutes les considérations des équilibres généraux des apis etc. L'équilibre général du paquetage des collections est assez bien fait, donc la méthode employée pour y parvenir a des chances d'être bonne.
Pour ce qui concerne le remove, j'observe que, la plupart du temps, je ne l'emploie pas. (je crois pouvoir dire que je ne l'emploie jamais). De plus, comme principe général, je ne modifie pas une liste en même temps que je la parcours.
Donc, pour moi, ce remove est maladroit, parce qu'il facilite une forme de traitement qui me parait mauvaise.
Cependant il existe des exceptions, bien sûr, heureusement. Il y a des listes qu'il vaut mieux modifier directement pendant le parcours. Il s'agit souvent de listes où l'accés est distant. Par exemple, JDBC donne la possibilité de modifier un curseur.
Ces listes sont cependant très particulières, dans leur mode d'accés, et il me semble qu'il aurait été bon d'en approfondir les caractéristiques, pour mieux les décrire et les utiliser, au lieu de placer un simple "remove".
D'ailleurs, le ResultSet, qui parcourt des listes de base de données, cas dans lequel je peux concevoir que le remove (ici "deleteRow") soit justifié, n'est pas relié au paquetage des collections.
Bug dans l'arbitrage fin ?...
-- Hervé AGNOUX http://www.diaam-informatique.com
Maxime Daniel wrote:
interfaces les plus utilisées, etc. Elle n'est forcément pas exempte
de reproches, mais résulte de l'examen poussé de notions subtiles.
C'est donc un arbitrage 'assez fin'...
Je n'ai pas accès à toutes les considérations des équilibres généraux des
apis etc. L'équilibre général du paquetage des collections est assez bien
fait, donc la méthode employée pour y parvenir a des chances d'être bonne.
Pour ce qui concerne le remove, j'observe que, la plupart du temps, je ne
l'emploie pas. (je crois pouvoir dire que je ne l'emploie jamais). De plus,
comme principe général, je ne modifie pas une liste en même temps que je la
parcours.
Donc, pour moi, ce remove est maladroit, parce qu'il facilite une forme de
traitement qui me parait mauvaise.
Cependant il existe des exceptions, bien sûr, heureusement. Il y a des
listes qu'il vaut mieux modifier directement pendant le parcours. Il s'agit
souvent de listes où l'accés est distant. Par exemple, JDBC donne la
possibilité de modifier un curseur.
Ces listes sont cependant très particulières, dans leur mode d'accés, et il
me semble qu'il aurait été bon d'en approfondir les caractéristiques, pour
mieux les décrire et les utiliser, au lieu de placer un simple "remove".
D'ailleurs, le ResultSet, qui parcourt des listes de base de données, cas
dans lequel je peux concevoir que le remove (ici "deleteRow") soit
justifié, n'est pas relié au paquetage des collections.
interfaces les plus utilisées, etc. Elle n'est forcément pas exempte de reproches, mais résulte de l'examen poussé de notions subtiles. C'est donc un arbitrage 'assez fin'...
Je n'ai pas accès à toutes les considérations des équilibres généraux des apis etc. L'équilibre général du paquetage des collections est assez bien fait, donc la méthode employée pour y parvenir a des chances d'être bonne.
Pour ce qui concerne le remove, j'observe que, la plupart du temps, je ne l'emploie pas. (je crois pouvoir dire que je ne l'emploie jamais). De plus, comme principe général, je ne modifie pas une liste en même temps que je la parcours.
Donc, pour moi, ce remove est maladroit, parce qu'il facilite une forme de traitement qui me parait mauvaise.
Cependant il existe des exceptions, bien sûr, heureusement. Il y a des listes qu'il vaut mieux modifier directement pendant le parcours. Il s'agit souvent de listes où l'accés est distant. Par exemple, JDBC donne la possibilité de modifier un curseur.
Ces listes sont cependant très particulières, dans leur mode d'accés, et il me semble qu'il aurait été bon d'en approfondir les caractéristiques, pour mieux les décrire et les utiliser, au lieu de placer un simple "remove".
D'ailleurs, le ResultSet, qui parcourt des listes de base de données, cas dans lequel je peux concevoir que le remove (ici "deleteRow") soit justifié, n'est pas relié au paquetage des collections.