Est-ce que better Show () + Hide () ou SetVisible (bool visible)?

59

Quoi de mieux et pourquoi? (Du point de vue de la conception de l'interface):

a) Avoir deux Show()et Hide()fonctions

b) Avoir une SetVisible(bool visible)fonction

EDIT: Par exemple, certains objets ont un état de visibilité et cette fonction est utilisée pour le changer.

c) Pour avoir tous les trois Show(), Hide(), SetVisible(bool visible)fonctions

utilisateur3123061
la source
4
Dans quel contexte? En général, cela n'a pas d'importance
Aviv Cohn
6
Pourquoi ne pas les avoir tous publics? Dans certains cas, vous savez qu'ils seront toujours affichés ou masqués, et dans d'autres, vous voudrez peut-être les afficher ou les masquer de manière conditionnelle.
Pllee
@ pllee: C'est probablement un très bon point.
user3123061
4
En Java, ce serait setVisible, masquer et montrer sans la lettre majuscule de départ.
Pierre Arlaud

Réponses:

81

Je préfère SetVisible(bool visible), car cela me permet d'écrire le code client comme ceci:

SetVisible(DetermineIfItShouldBeVisible());

au lieu d'avoir à écrire

if (DetermineIfItShouldBeVisible()) {
    Show();
} else {
    Hide();
}

L' SetVisibleapproche peut également permettre une mise en œuvre plus facile. Par exemple, si une classe concrète particulière délègue simplement la méthode à ses classes composites, cela SetVisiblesignifie une méthode de moins à implémenter.

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}
Josh Kelley
la source
25
De manière équivalente, vous pouvez également rendre Visible une propriété, à condition que votre langue le prenne en charge. MyObject.Visible = false;me semble encore plus intuitif queMyObject.SetVisible(false);
Brian
9
@Brian Pour moi, c'est moins lisible et moins corrigible, car cela cache le comportement du programme à mes yeux - l'appel de méthode sous-jacent - mais c'est une autre histoire. Java ne supporte pas cette syntaxe, de toute façon, c'est une question de préférence et d'entraînement visuel.
Ignis
10
SetVisible()ne suggère pas (à moi) que vous affichez réellement quelque chose. Cela se lit plutôt comme si vous définissiez la propriété de visibilité d'un objet, en laissant éventuellement le soin à une méthode Refresh()ou correspondante Redisplay()de vérifier la valeur de cette propriété afin de déterminer si l'objet doit être affiché ou masqué.
TMN
1
Malheureusement, Java ne supporte pas les propriétés comme C #, mais uniquement les accesseurs et les setters que vous voyez ci-dessus.
theGreenCabbage
1
@TMN: Je suppose qu'en l'absence d'autres facteurs empêchant la visibilité (ordre Z, visibilité parent, emplacement, etc.) setVisible(true), un processus serait créé selon lequel l'objet serait dessiné lorsque le système serait inactif, voire avant. Je pense que cela refreshpourrait être utile pour hâter l'affichage de l'objet, mais que l'objet serait finalement dessiné indépendamment (sauf si, par exemple, sa visibilité était définie falseavant).
Supercat
35

Je suis en désaccord avec toutes les affiches suggérant que plusieurs fonctions pour faire la même chose est une bonne chose. Alors que trois fonctions au lieu d'un peut ne pas sembler beaucoup ballonnement, rappelez - vous que votre classe est susceptible de se retrouver avec beaucoup de ces fonctions (par exemple setEnabled, enable, disable) et donc cette approche va se retrouver avec une grande interface plus grande classe. De plus, il est probable que vous obtiendrez un tas de fonctions / propriétés / similaires similaires dans votre classe et que la multiplication de fonctions obscurcira davantage le choix.

Dans les langages qui supportent les propriétés, celles-ci devraient être préférées, mais comme ni Java ni C ++ ne le font, je suppose que c'est un point discutable.

Je pense que setVisible()devrait être préféré pour ces raisons:

  1. La fonction inverse est immédiatement évidente. Pour inverser setVisible(false)votre appel setVisible(true)alors que le contraire de hide()pourrait être facilement reveal().
  2. C'est plus simple, du point de vue du programme, à chaque fois que vous déterminez quel état il doit recevoir en code, c'est-à-dire que vous pouvez appeler setVisible(wantToSee)plutôt que d'utiliser une ifinstruction.
  3. Une fois que vous avez plusieurs fonctions similaires, le setX()format se généralise afin que vous puissiez avoir un ensemble de fonctions cohérentes, tandis que l’approche verbed engendre une foule de fonctions qui peuvent être difficiles à localiser si vous ne savez pas ce que vous recherchez. La cohérence des API facilite considérablement leur apprentissage et leur mémorisation.
Jack Aidley
la source
3
C ++ n'a pas de propriétés, mais il a des fonctions libres. Vous pouvez donc étendre l'interface de classe sans ajouter de nouvelles fonctions membres, c'est-à-dire avec un degré de couplage plus faible.
phresnel
Qt fournit souvent ces trois options pour que hide () et show () puissent être connectés directement à d’autres événements à l’aide du système signal / slot. Cependant, il s’agit là d’une limitation du système de machines à sous: s’il utilisait quelque chose de plus similaire à boost :: functions, l’argument true / false pourrait être lié au moment de la configuration du rappel.
1
"Dans les langages qui prennent en charge les propriétés, celles-ci devraient être préférées, mais comme ni Java ni C ++ ne le font, je suppose que c'est un point discutable." pas nécessairement. De préférence aux getters / setters? Oui. Mais set_visible n'est pas réellement un passeur.
Miles Rout
19

Cela dépend de ce que montrer et cacher signifie dans le contexte. D'abord, vous voulez savoir lequel est votre "voie principale" et vous concentrer sur le développement de cela:

  • Raisons pour choisir setVisible(bool)
    • Il ne s'agit que d'un simple basculement, ou votre objet est principalement en attente
    • Votre objet va passer le plus clair de son temps dans un cadre CRUD
    • Il y a beaucoup de code facile à partager entre l'affichage et le masquage
  • Raisons pour choisir show()ethide()
    • Il y a des effets secondaires importants ou beaucoup de logique en cours d' exécution, comme lorsque l'objet doit vérifier tous ses conteneurs pour leur état de visibilité, ou déclenche une animation de transition.
    • Fait-il partie d'un modèle de domaine où l'expression de l' intention est importante

OK, alors maintenant que vous avez codé le noyau «standard d’or», vous devez déterminer s’il vaut la peine d’ajouter des méthodes simples dans l’autre style, afin de faciliter la vie de ceux qui vont utiliser votre objet.

  • Commodité de setVisible(bool)
    • Vous permet d'éviter les instructions si qui ont des conditions triviales et n'affectent que la visibilité (ex. setVisible(a==b))
    • Peut être connecté à certains frameworks getter / setter, si vous vous attendez à quelque chose
  • Commodité de show()ethide()
    • Utile dans une langue avec des fonctions de première classe et des rappels (ex. onSuccess(widget.show))
    • Beaucoup plus facile à lire avec les traces de pile et le profilage de performance, car vous pouvez rapidement voir ce que le programme essayait de faire

TLDR: Trouvez lequel est le plus important, mettez-le en œuvre, puis demandez-vous s'il vaut la peine d'ajouter l'autre style en tant que méthodes simples.

Darien
la source
11

Je dirais "tous les trois".

Show()et Hide()ont tendance à être plus facile à parler que SetVisible(true)et SetVisible(false). Toutefois, lorsque vous souhaitez définir la visibilité de manière logique, il est préférable d’avoir une méthode utilisant une méthode boolplutôt qu’une construction ifautour de celle-ci bool.

Vous pouvez prendre en charge les trois sans dupliquer la logique et le passe-partout minimal:

void Show() {
    foo.Show();
    bar.Show();
}

void Hide() {
    foo.Hide();
    bar.Hide();
}

void SetVisible(bool visible) {
    if (visible) {
        Show();
    } else {
        Hide();
    }
}

Alternativement, si les choses que vous enveloppez ont une SetVisibleAPI plus rapide:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}
Garry Shutler
la source
40
Microsoft utilise cette approche pour démarrer et arrêter System.Windows.Forms.Timer. Personnellement, je trouve cela déroutant. Quand je vois les deux Showet SetVisible, ma première tendance est de me demander s’il existe une différence importante entre les deux fonctions.
Brian
1
Vous pouvez facilement les documenter pour éliminer cette confusion. Je n'ai pas comme c'était un exemple simple.
Garry Shutler
20
Alors maintenant, je dois passer X minutes supplémentaires à lire la documentation avant de me sentir à l'aise avec le cours? Ou encore, dois-je perdre X minutes supplémentaires de temps à confondre (ou à introduire des bugs)? Bien sûr, X est assez petit pour ce genre de chose, mais ce n'est certainement pas zéro. Offrir les trois options signifie offrir trois fois plus de fonctions que nécessaire, ce qui signifie que vous passez plus de temps à documenter et que je consacre plus de temps à apprendre à utiliser la classe. En outre, il présente un autre moyen d'incohérence pour différents développeurs lors de l'utilisation de votre classe.
Brian
5
Ceci est une violation claire du principe Interface Segregation, l'un des principes SOLID. Un autre avis contre votre approche est celui de jaroslav tulach, concepteur de netbeans, qui insiste souvent pour ne fournir qu'un seul moyen de faire une chose au sein d'une API dans la conception de son livre, une API pratique.
AlfredoCasado
@ AlfredoCasado Je suis d'accord. Et si SetVisible était protégé ? Vous pouvez y accéder à partir d'une sous-classe, mais l'appel à une entité donnée avec cette interface (telle qu'une API) doit être Hide / Show.
Pierre Arlaud
5

Je préfère show () et hide (). En fait, chaque méthode qui reçoit un booléen peut être modifiée pour deux méthodes mieux exprimer l'intention de l'API. Par exemple, Robert Martin, dans un code épuré, recommande de préférer les méthodes avec zéro argument aux méthodes avec un seul argument.

Un autre argument important pour moi est la lisibilité. À mon avis, un bon code peut être lu comme une prose, c'est une prose vraiment étrange du genre "main_window setVisible false" au lieu de "main_window hide", vous écrivez ou parlez comme ça normalement ?, pourquoi utiliser cet étrange construction du langage dans les logiciels quand est-il parfaitement possible d'utiliser un langage plus naturel?.

AlfredoCasado
la source
1
Assembler n'est-il pas suffisant en prose?
Alexander
Je m'attendrais à ce que la séquence it.setVisible(false); it.setVisible(true);n'affecte pas la visibilité du parent d'un contrôle, ni son ordre Z ni son emplacement. En revanche, hide(); show(); plausiblement pourrait forcer le parent d'un contrôle à être visible, le déplacer au-dessus des autres contrôles et limiter sa position à un endroit visible. Dans certains cas, il est utile de disposer d'un moyen de s'assurer que quelque chose est réellement visible (comme avec ce qui précède show(), mais dans d'autres cas, il est utile de modifier l'indicateur de visibilité sans rien changer d'autre.
supercat
Dans une API orientée objet, il n'y a pas d '"indicateur", OO concerne la messagerie. Il est également recommandé d'indiquer à un autre objet certaines tâches à effectuer, et non de changer les "indicateurs" qui sont l'état de l'objet. Vous faites beaucoup d’hypothèses sur les contrôles, les parents, le z-ordering et les choses que VOUS attendez de votre expérience antérieure avec d’autres API, c’est une très mauvaise idée de concevoir une API basée sur des sentiments personnels et des hypothèses sur un domaine.
AlfredoCasado
5

Je pense que plus la méthode est expressive, plus le code sera lisible et, par conséquent, maintenable. Considérons les deux cas suivants:

Cas 1:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  customerPanel.setVisible(customer.isCustomerEnabled());
}

Cas 2:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  //always show customer panel
  customerPanel.setVisible(true);
}

Dans le premier cas, la fonction "setVisible" est claire, mais si vous voulez la lire, vous diriez:

définissez le panneau client sur visible si le client est activé ou définissez-le sur masqué si le client est désactivé.

Bien qu'il soit plus descriptif de dire:

  • vérifier le statut du client:
    • si le client est activé, affichez le panneau du client
    • sinon, cachez-le

ce qui modifiera la fonction "Cas 1" comme suit:

void showCustomerData(customerId){
  Customer customer = getCustomer(CustomerId);
  if(customer.isCustomerEnabled()){
    customerPanel.Show();
  }
  else{
    customerPanel.Hide();
  }
}

il produit plus de code, mais est plus lisible.

Le second cas a un défaut évident: vous savez déjà que vous souhaitez afficher le panneau, alors pourquoi ne pas utiliser la fonction "Afficher"?

Je ne dis pas que l'utilisation de "setVisible" est absolument fausse, mais cela devient confus lorsque vous essayez de lire du code que vous n'avez pas écrit au fil du temps et qu'il n'est pas conforme à la règle "Une fonction ne doit effectuer qu'une seule opération".

OKAN
la source
Je dirais: show customer panel iff the user/customer is enabled. Je conviens qu'il peut y avoir beaucoup de conditions plus complexes qui ne sont pas aussi faciles à lire que votre exemple, cependant, dans ces cas, je séparerais ces conditions en différentes lignes.
ComFreek
5

Je crois que la Hide()/ Show()alternative est intéressante , car il est plus facile de comprendre ce qui se passe qu'avec SetVisible(true), tout en ayant une seule fonction est préférable car il évite beaucoup de conditionals.

Si c'est le cas, je suggère d'utiliser une énumération comme entrée SetVisible, afin que vous obteniez l'un SetVisible(Visibility.Visible)ou l' autre SetVisible(Visibility.Hidden). Vous avez une seule fonction que vous pouvez lire instantanément quelle action est entreprise.

En utilisant les conventions de nommage de Java, vous auriez peut-être setVisible(Visibility.VISIBLE)ou setVisible(Visibility.HIDDEN).

Gabe
la source
3

Je suis d'accord avec la réponse de Darien, mais je voulais ajouter un point de vue du point de vue des programmeurs C #.

Quand je vois du code qui dit 'setXXX', je lis cela pour dire qu'il donne une valeur à une chose, je ne m'attends pas à ce que cela ait des effets secondaires sur cette chose à part définir cette valeur, et je pense que ce sera idempotent. (c.-à-d. que je peux continuer à le régler avec la même valeur et ce n'est pas grave). C'est un peu comme accéder à un champ. Généralement, je m'attendrais aussi à voir une méthode 'getXXX' avec un 'setXXX'.

Je ne sais pas si c'est ce à quoi vous vous attendiez en Java et en C ++, mais c'est ce à quoi je m'attendrais en C #, bien qu'en C #, il existe un raccourci pour cela appelé Propriétés. Et voici quelques conseils utiles sur l'utilisation des propriétés ( http://msdn.microsoft.com/en-us/library/ms182181.aspx ).

Compte tenu de ce point de vue, l'interface que je choisirais dépend uniquement des effets secondaires (autres que la modification de la valeur de ce champ):

Si cette action a des effets secondaires, par exemple si une boîte de dialogue est affichée, alors je choisirais "Show ()" et "Hide ()".

S'il n'a pas d'effets secondaires, si je règle la visibilité d'un "widget" et si un autre rendu le rend en fonction de son état, j'utiliserais setVisibility ou setIsVisible. (Je n'appellerais pas cela SetVisible).

En C # (pas sûr de Java), il est assez courant d’adopter un motif observateur, dans lequel un cadre d’interface utilisateur écoute les modifications apportées aux objets et restitue automatiquement l’interface utilisateur lorsqu’une propriété, telle que Visibility, change. Cela signifie que définir la valeur en appelant setIsVisible apparaît comme si elle avait des effets secondaires, mais pas dans ma définition. Le contrat du widget est rempli en définissant sa valeur de champ représentant "IsVisible".

En d'autres termes, je peux activer / désactiver la visibilité d'une étiquette sur un formulaire avant que celui-ci ne soit affiché. C'est-à-dire label.getIsVisible == true, mais le formulaire n'est pas affiché.

Je ne peux pas appeler Hide () lorsque le formulaire n'est pas affiché.

Daniel James Bryars
la source
1
Votre description getXXX()et vos setXXX()méthodes comme moyen d’accéder à un champ sans effets secondaires sonne comme en Java et non en C #. C'est la façon dont vous devez le faire en Java car il n'a pas de propriétés. Si je voyais un code comme celui-ci en C #, je suppose qu'il avait été écrit par un développeur Java qui n'avait pas encore appris à propos des propriétés en C #.
gilly3
+1 pour SetVisibility.
Akaltar
@ gilly3 - Oui, bien sûr. Et, "Les propriétés" n'existent pas dans le CLR, C # est traduit en appels de méthodes get_XXX et set_YYY en IL. Mon argument est le suivant: dans le contexte de la question, si vous voyiez setXXX, getXXX en Java, vous vous attendriez à ce qu’il fonctionne avec la même sémantique que les propriétés en C #. Cela étant vrai, j’ai donc raison de penser que les mêmes instructions pour les propriétés en C # s’appliquent aux paires setXXX et getXXX en Java. Je suis d’accord avec les directives citées dans le post, et j’encourage donc ces mêmes directives à utiliser dans ce scénario en Java lors de la définition de l’interface.
Daniel James Bryars
1
Il peut être utile de préciser que, lorsque vous parlez d '"effets secondaires", vous voulez dire "autres que ceux associés au fait d'être" observable ". La règle que je privilégie est de dire que si un getXXappel a une setXXméthode correspondante , cela setYYne devrait pas l’affecter, mais cela peut affecter un getZZappel qui n’a pas de setZZméthode.
Supercat
2

Je suggérerais une interface légèrement modifiée:

Show();
Hide();
ToggleVisible();
ToggleVisible(bool visible);

Meilleurs noms

Ces noms de méthodes aident le développeur à choisir la méthode à utiliser en fonction de ce qui doit être fait. Considérant que SetVisible(bool visible)peut confondre un développeur, car il transmet la même signification sémantique que Show()et Hide(), Toggle()implique l'existence d'une condition qui détermine l'action. Il devient donc intuitif pour le développeur d’utiliser chaque méthode.

Redondance de code réduite

L'avantage d'avoir plusieurs méthodes dans votre interface est que cela simplifie le code d'appel. Vous pouvez simplement exposer Show()et Hide(), mais:

  • Vous auriez probablement besoin d'une sorte de SetVisible()méthode privée pour faire le vrai travail dans les coulisses (ou écrire du code redondant pour Show()et Hide()).
  • Le code appelant peut contenir de nombreux blocs if / else redondants pour choisir la méthode à utiliser. Cela gonfle le code à mon avis.
  • Si j'étais le consommateur, j'écrirais probablement juste ma propre fonction wrapper qui fait ce SetVisible()(ou Toggle()) déjà déjà afin d'éviter le gonflement du code (je déteste le code redondant). On duplique ainsi une méthode qui existe probablement déjà en tant que méthode privée dans la mise en œuvre.
gilly3
la source
1
La duplication de la méthode semble raisonnable, même si je ne le ferais pas moi-même. D'autre part, je ne suis pas d'accord pour dire que toggleVisible (bool) est intuitif. Pour moi, cela signifie que cela devrait basculer si la valeur transmise dans bool est vraie, ce qui serait plutôt étrange, mais j'ai déjà vu un étranger. Cela ne supposerait pas qu'il s'agisse vraiment d'une fonction définie déguisée.
Patrick M
0

Je suggérerais d'utiliser le SetVisible(bool)cas échéant uniquement si le fait de changer la visibilité deux fois (afficher et masquer, ou masquer et afficher à nouveau) laisserait les choses dans le même état qu'avant l'opération (c'est bien si afficher et masquer Quelque chose ou vice-versa laisse des objets nécessitant un redessin, à condition que l'on peut s'attendre à ce qu'il se produise "automatiquement"). Si masquer et afficher un objet n'aura d'autre effet que de changer un bit d'état, il serait logique que du code extérieur ait des méthodes acceptant un paramètre de visibilité, et l'écriture de ce code sera facilitée SetVisible.

Si le fait de cacher et de montrer à nouveau un objet peut avoir des effets secondaires, tels que la modification de l'ordre des Z, ces actions doivent probablement être effectuées par des méthodes distinctes. Dans de tels cas, l'utilité des méthodes extérieures qui acceptent un paramètre de "visibilité" sera limitée, de sorte qu'il sera peu avantageux de les faciliter. De plus, une SetVisibleméthode suggérera (à tort) que des changements dans la visibilité des objets peuvent être accomplis sans effets secondaires.

supercat
la source