¿Es mejor Show () + Hide () o SetVisible (bool visible)?

59

¿Qué es mejor y por qué? (Desde el punto de vista del diseño de la interfaz):

a) Tener dos Show()y Hide()funciones

b) Tener una SetVisible(bool visible)función

EDITAR: Por ejemplo, algún objeto tiene estado de visibilidad y esta función se utiliza para cambiarlo.

c) tener los tres Show(), Hide(), SetVisible(bool visible)funciones

usuario3123061
fuente
44
¿En que contexto? Generalmente no importa
Aviv Cohn
66
¿Por qué no tenerlos a todos públicos? Hay casos en los que sabe que siempre se mostrarán u ocultarán y hay casos en los que desearía mostrar u ocultar condicionalmente.
favor el
@Pllee: Ese es probablemente un muy buen punto.
user3123061
44
En java, sería setVisible, hide y show sin la letra mayúscula inicial.
Pierre Arlaud

Respuestas:

81

Prefiero SetVisible(bool visible), porque me permite escribir código de cliente como este:

SetVisible(DetermineIfItShouldBeVisible());

en lugar de tener que escribir

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

El SetVisibleenfoque también puede permitir una implementación más fácil. Por ejemplo, si una clase concreta en particular simplemente delega el método a sus clases compuestas, SetVisiblesignifica un método menos para implementar.

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}
Josh Kelley
fuente
25
De manera equivalente, también puede hacer que Visible sea una propiedad, suponiendo que su idioma lo admita. MyObject.Visible = false;me parece aún más intuitivo queMyObject.SetVisible(false);
Brian
99
@Brian Para mí es menos legible y depurable, porque oculta el comportamiento del programa a mis ojos, la llamada al método subyacente, pero esa es otra historia. Java no admite esa sintaxis, de todos modos es una cuestión de preferencia y entrenamiento visual.
ignis
10
SetVisible()no sugiere (para mí) que en realidad esté mostrando algo. Se lee más como si estuviera configurando la propiedad de visibilidad de un objeto, posiblemente dejándolo en un método Refresh()o Redisplay()método correspondiente para verificar el valor de esta propiedad para determinar si el objeto debe mostrarse u ocultarse.
TMN
1
Desafortunadamente, Java no admite propiedades como C #, solo captadores y establecedores que ve más arriba.
theGreenCabbage
1
@ TMN: esperaría que, en ausencia de otros factores que impidan la visibilidad (orden Z, visibilidad principal, ubicación, etc.), se setVisible(true)pondría en marcha un proceso en el que el objeto se dibujaría cuando el sistema estuviera inactivo la próxima vez, si no antes. Esperaría que refreshpudiera ser útil para acelerar la visualización del objeto, pero que el objeto eventualmente se dibujaría independientemente (a menos que, por ejemplo, su visibilidad fuera establecida falseantes de que eso ocurriera).
supercat
35

No estoy de acuerdo con todos los carteles que sugieren que múltiples funciones para hacer lo mismo es algo bueno. Mientras tres funciones en lugar de uno pueden no parecer mucho, hinchazón, recuerde que su clase es probable que terminan con muchas de esas funciones (por ejemplo setEnabled, enable, disable) y por lo tanto este enfoque va a terminar con una gran interfaz de la clase más grande. Además, es probable que termines con un montón de funciones / propiedades de sonido similares / lo que sea en tu clase y la multiplicación de funciones oscurecerá aún más cuál va con qué.

En los lenguajes que admiten propiedades, estos deberían ser preferidos, pero como Java o C ++ no lo hacen, supongo que es un punto discutible.

Creo que setVisible()debería preferirse por estos motivos:

  1. Es inmediatamente obvio cuál es la función inversa. Para revertir setVisible(false)tu llamada, setVisible(true)mientras que lo contrario de hide()podría ser fácilmente reveal().
  2. Es programáticamente más simple siempre que esté determinando qué estado debería tomar en el código, es decir, puede llamar en setVisible(wantToSee)lugar de usar una ifdeclaración.
  3. Una vez que tiene múltiples funciones similares, el setX()formato se generaliza para que pueda tener un conjunto de funciones consistentes, mientras que el enfoque verbed genera una serie de funciones que pueden ser difíciles de localizar si no sabe lo que está buscando. La consistencia en las API las hace considerablemente más fáciles de aprender y recordar.
Jack Aidley
fuente
3
C ++ no tiene propiedades, pero tiene funciones libres, por lo que puede ampliar la interfaz de clase sin agregar nuevas funciones miembro, es decir, con un menor grado de acoplamiento.
phresnel
Qt a menudo proporciona los tres como una conveniencia para que hide () y show () puedan conectarse directamente a otros eventos usando el sistema de señal / ranura. Sin embargo, esto es realmente una limitación del sistema de tragamonedas: si usara algo más como boost :: funciones, el argumento verdadero / falso podría vincularse al punto de configurar la devolución de llamada.
1
"En los lenguajes que admiten propiedades, deberían preferirse, pero como Java o C ++ no lo hacen, supongo que es un punto discutible". no necesariamente. ¿Prefiere getters / setters? Si. Pero set_visible no es realmente un setter.
Miles Rout
19

Depende de qué mostrar y ocultar significa en el contexto. Primero, desea averiguar cuál es su "camino principal" y centrarse en desarrollar eso:

  • Razones para escoger setVisible(bool)
    • Es solo un simple giro de bits, o su objeto está principalmente en estado de retención
    • Su objeto va a pasar la mayor parte de su tiempo en un marco CRUD
    • Hay mucho código fácil de compartir entre mostrar y ocultar
  • Razones para escoger show()yhide()
    • Se están ejecutando importantes efectos secundarios o mucha lógica, como cuando el objeto tiene que verificar todos sus contenedores para ver su estado de visibilidad o desencadenar una animación de transición.
    • ¿Es parte de un modelo de dominio donde es importante expresar la intención?

Bien, ahora que ha codificado el núcleo del "estándar de oro", debe averiguar si vale la pena agregar métodos de conveniencia delgados en el otro estilo, para facilitar la vida de quien vaya a usar su objeto.

  • Conveniencia de setVisible(bool)
    • Le permite evitar declaraciones if que tienen condiciones triviales y solo afectan la visibilidad (ej. setVisible(a==b))
    • Puede conectarse a ciertos marcos getter / setter, si eso es algo que espera que suceda
  • Conveniencia de show()yhide()
    • Útil en un lenguaje con funciones y devoluciones de llamada de primera clase (ej. onSuccess(widget.show))
    • Mucho más fácil de leer con rastros de pila y perfiles de rendimiento, ya que puede ver rápidamente lo que el programa estaba tratando de hacer.

TLDR: descubra cuál es el más importante, impleméntelo y luego pregúntese si vale la pena agregar el otro estilo como métodos convenientes.

Darien
fuente
11

Yo diría "los tres".

Show()y Hide()tienden a ser más fáciles de asimilar que SetVisible(true)y SetVisible(false). Sin embargo, cuando desea establecer la visibilidad de forma lógica, es mejor tener un método que tome boolun ifentorno en lugar de construirlo bool.

Puede admitir los tres sin duplicar la lógica y un mínimo repetitivo:

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

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

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

Alternativamente, si las cosas que está envolviendo tienen una SetVisibleAPI más -ish:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}
Garry Shutler
fuente
40
Microsoft usa este enfoque para iniciar y detener System.Windows.Forms.Timer. Personalmente, me parece confuso. Cuando veo ambos Showy SetVisible, mi primera inclinación es preguntarme si hay alguna diferencia importante entre las dos funciones.
Brian
1
Sin embargo, puede documentarlos fácilmente para eliminar esa confusión. No lo hice, ya que este era un simple ejemplo.
Garry Shutler
20
Entonces, ¿ahora necesito pasar X minutos adicionales leyendo la documentación antes de sentirme cómodo usando la clase? ¿O, alternativamente, necesito perder X minutos adicionales de tiempo confundiéndome (o introduciendo errores)? Claro, X es bastante pequeño para este tipo de cosas, pero definitivamente no es cero. Ofrecer las 3 opciones significa ofrecer tres veces más funciones que las necesarias, lo que significa que gasta más trabajo documentando y yo paso más trabajo aprendiendo cómo usar la clase. Además, presenta una forma más para que diferentes desarrolladores sean inconsistentes al usar su clase.
Brian
55
Esta es una clara violación del principio de segregación de interfaz, uno de los principios SÓLIDOS. Otra opinión en contra de su enfoque es la de jaroslav tulach, diseñador de netbeans, que insiste muchas veces en proporcionar solo una forma de hacer una cosa dentro de una API en el diseño práctico de API de su libro.
AlfredoCasado
@AlfredoCasado Estoy de acuerdo. ¿Qué pasa si SetVisible estaba protegido ? Puede acceder desde una subclase, pero la llamada a una entidad determinada con esta interfaz (como una API) tendría que ser Ocultar / Mostrar.
Pierre Arlaud
5

Prefiero show () y hide (), de hecho, cada método que recibe un booleano se puede cambiar por dos métodos para expresar mejor la intención de la API. Por ejemplo, Robert Martin en código limpio recomienda métodos preferidos con cero argumentos sobre métodos con un argumento.

Otro argumento importante para mí es la legibilidad, en mi opinión, un buen código se puede leer como prosa, es una prosa realmente extraña, algo así como "main_window setVisible false" en lugar de "main_window hide", ¿escribe o habla así normalmente ?, ¿por qué usar este extraño? ¿La construcción del lenguaje en programas de software cuando es perfectamente posible utilizar un lenguaje más natural?

AlfredoCasado
fuente
1
¿No es suficiente la prosa de ensamblador?
Alexander
Esperaría que la secuencia it.setVisible(false); it.setVisible(true);no afectara la visibilidad de los padres del control, ni debería afectar el orden Z o la ubicación del control. Por el contrario hide(); show(); podría forzar de manera plausible que el padre de un control sea visible, moverlo sobre otros controles y limitar su posición a un lugar que pueda verse. En algunos casos, es útil tener un medio para asegurarse de que algo sea realmente visible (como con lo mencionado anteriormente show(), pero en otros casos es útil cambiar la bandera de visibilidad sin cambiar nada más.)
supercat
En una API orientada a objetos no hay "indicadores", OO se trata de mensajes, se trata de decirle a otro objeto que realice alguna tarea, no de cambiar "indicadores" que son el estado del objeto. Está haciendo muchas suposiciones sobre el control, los padres, el orden z y las cosas que USTED espera basadas probablemente en su experiencia previa con otras API, es una muy mala idea diseñar una API basada en sentimientos y suposiciones personales sobre un dominio.
AlfredoCasado
5

Creo que cuanto más expresivo sea el método, más legible y, en consecuencia, sostenible, será el código. Considere los siguientes dos casos:

Caso 1:

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

Caso 2:

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

En el primer caso, está claro qué está haciendo la función "setVisible", pero si desea leerla, diría:

configure el panel del cliente como visible si el cliente está habilitado o configúrelo como oculto si el cliente está deshabilitado.

Si bien es más descriptivo decir:

  • verificar el estado del cliente:
    • si el cliente está habilitado, muestre el panel del cliente
    • de lo contrario, escóndelo

que cambiará la función "Caso 1" a la siguiente:

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

Produce más código, pero es más legible.

El segundo caso tiene una falla obvia, que ya sabe que desea mostrar el panel, entonces, ¿por qué no usar la función "Mostrar"?

No estoy diciendo que usar "setVisible" sea absolutamente incorrecto, pero se vuelve confuso cuando intentas leer el código que no escribiste a lo largo del tiempo, y no se ajusta a la regla "Una función debe realizar una sola operación".

OKAN
fuente
Yo diría: show customer panel iff the user/customer is enabled. Estoy de acuerdo en que puede haber muchas condiciones más complejas que no son tan fáciles de leer como su ejemplo, sin embargo, en esos casos, dividiría esas condiciones en diferentes líneas.
ComFreek
5

Creo que la alternativa Hide()/ Show()es atractiva porque es más fácil de entender lo que está sucediendo que con SetVisible(true), mientras que tener una sola función es preferible porque evita muchos condicionales.

Si ese es el caso, sugiero usar una enumeración como entrada para SetVisibleque obtenga SetVisible(Visibility.Visible)o SetVisible(Visibility.Hidden). Tiene una única función: puede leer instantáneamente qué acción se está tomando.

Usando las convenciones de nomenclatura de Java, tendría quizás setVisible(Visibility.VISIBLE)o setVisible(Visibility.HIDDEN).

Gabe
fuente
3

Estoy de acuerdo con la respuesta de Darien, pero quería agregar un punto de vista desde la perspectiva de los programadores de C #.

Cuando veo un código que dice 'setXXX', lo leo para decir que está estableciendo un valor en una cosa, no espero que tenga efectos secundarios en esa cosa que no sea establecer ese valor, y espero que esto sea idempotente (es decir, puedo seguir configurándolo con el mismo valor y está bien). Es más bien como acceder a un campo. En general, también esperaría ver un método 'getXXX' junto con un 'setXXX'.

No sé si esto es lo que esperas en Java y C ++, pero eso es lo que esperaría en C #, aunque en C # hay una pequeña mano para esto llamada Propiedades. Y aquí hay una buena guía sobre cómo usar Propiedades ( http://msdn.microsoft.com/en-us/library/ms182181.aspx ).

Dada esta vista, la interfaz que elegiría depende únicamente de si hay algún efecto secundario (además de cambiar el valor de ese campo):

Si realizar la acción tiene efectos secundarios, por ejemplo, se muestra un cuadro de diálogo, iría con "Mostrar ()" y "Ocultar ()".

Si no tiene efectos secundarios, digamos que estoy configurando la visibilidad de un "widget" y algo más representa ese widget dependiendo de su estado, entonces usaría setVisibility o setIsVisible. (No lo llamaría SetVisible).

En C # (no estoy seguro acerca de Java) es bastante común adoptar un patrón de observador, donde un marco de la interfaz de usuario escuchará los cambios en los objetos y volverá a representar automáticamente la interfaz de usuario cuando cambie una propiedad como Visibilidad. Eso significa que establecer el valor al llamar a setIsVisible parece tener efectos secundarios, pero en mi definición no lo tiene. El contrato del widget se cumple estableciendo su valor de campo que representa "IsVisible".

Dicho de otra manera, está bien para mí alternar la visibilidad de una etiqueta en un formulario antes de que se muestre el formulario. Es decir, label.getIsVisible == verdadero, pero el formulario no se muestra.

No está bien que llame a Hide () cuando no se muestra el formulario.

Daniel James Bryars
fuente
1
Su descripción getXXX()y setXXX()métodos como una forma de acceder a un campo sin efectos secundarios suena como Java y no C #. Esta es la forma en que debe hacerlo en Java porque no tiene propiedades. Si vi un código así en C #, supongo que fue escrito por un desarrollador de Java que aún no había aprendido sobre las propiedades en C #.
gilly3
+1 para SetVisibility.
akaltar
@ gilly3 - Sí, por supuesto. Y, "Propiedades" no existen en el CLR, C # se traduce en llamadas a métodos get_XXX y set_YYY en IL. Mi punto es: en el contexto de la pregunta, si vio setXXX, getXXX en Java, esperaría que funcione con la misma semántica que las propiedades en C #. Siendo cierto, creo que las mismas pautas para las propiedades en C # son aplicables a los pares de setXXX y getXXX en Java. Estoy de acuerdo con las pautas a las que me refiero en la publicación, y por lo tanto estoy abogando por esas mismas pautas para su uso en este escenario en Java al definir la interfaz.
Daniel James Bryars
1
Puede ser útil aclarar que cuando quiere decir "efectos secundarios", quiere decir "distintos de los asociados con ser una cosa" observable ". La regla que prefiero es decir que si una getXXllamada tiene un setXXmétodo correspondiente , setYYno debería afectarlo, pero puede afectar una getZZllamada que no tiene un setZZmétodo.
supercat
2

Sugeriría una interfaz ligeramente modificada:

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

Mejores nombres

Estos nombres de métodos ayudan al desarrollador a decidir qué método usar en función de lo que debe hacerse. Mientras que SetVisible(bool visible)puede confundir a un desarrollador porque transmite el mismo significado semántico que Show()e Hide(), Toggle()implica la existencia de una condición que determina la acción. Por lo tanto, se vuelve intuitivo para el desarrollador cuándo usar cada método.

Redundancia de código reducida

El beneficio de tener múltiples métodos en su interfaz es que simplifica el código de llamada. Podrías exponer Show()y Hide(), pero:

  • Probablemente requiera algún tipo de SetVisible()método privado para hacer el trabajo real detrás de escena (o escribir código redundante para Show()y Hide()).
  • El código de llamada puede tener muchos bloques if / else redundantes solo para elegir qué método usar. Esto hincha el código en mi opinión.
  • Si yo fuera el consumidor, probablemente escribiría mi propia función de envoltura que hace lo que SetVisible()(o Toggle()) ya hace para evitar la acumulación de código (odio el código redundante). Por lo tanto, duplicar un método que probablemente ya existe como método privado en la implementación.
gilly3
fuente
1
La duplicación del método suena razonable, aunque no lo haría yo mismo. Por otro lado, no estoy de acuerdo en que toggleVisible (bool) sea intuitivo. Para mí, significa que debería alternar si lo aprobado en bool es cierto, lo que sería bastante extraño, pero he visto algo extraño. No supondría que es realmente una función establecida disfrazada.
Patrick M
0

Sugeriría usar, SetVisible(bool)si lo hubiera, solo si alterna la visibilidad dos veces (mostrar y volver a ocultar, u ocultar y volver a mostrar) dejaría las cosas esencialmente en el mismo estado que antes de que se realizara la operación (está bien si se muestra y se vuelve a ocultar algo o viceversa deja objetos que necesitan un redibujo, siempre que se pueda esperar que suceda "automáticamente"). Si esconder y mostrar un objeto no tendrá otro efecto que cambiar un bit de estado, entonces tendría sentido para el código externo tener algunos métodos que acepten un parámetro de visibilidad, y la escritura de dicho código se facilitará SetVisible.

Si ocultar y volver a mostrar un objeto puede tener efectos secundarios, como cambiar el orden Z, es más probable que tales acciones se realicen por métodos separados. En tales casos, la utilidad de los métodos externos que aceptan un parámetro de "visibilidad" será limitada y, por lo tanto, habrá pocas ventajas para facilitarlos. Además, un SetVisiblemétodo sugerirá (erróneamente) que los cambios en la visibilidad de los objetos se pueden lograr sin efectos secundarios.

Super gato
fuente