È meglio Mostra () + Nascondi () o ImpostaVisibile (bool visibile)?

58

Cosa è meglio e perché? (Dal punto di vista della progettazione dell'interfaccia):

a) Per avere due Show() e Hide() funzioni

b) Per avere una funzione SetVisible(bool visible)

EDIT: Ad esempio alcuni oggetti hanno lo stato di visibilità e questa funzione è usata per cambiarlo.

c) Per avere tutte e tre le funzioni Show() , Hide() , SetVisible(bool visible)

    
posta user3123061 20.03.2014 - 17:00
fonte

10 risposte

82

Preferisco SetVisible(bool visible) , perché mi consente di scrivere codice client come questo:

SetVisible(DetermineIfItShouldBeVisible());

invece di dover scrivere

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

L'approccio SetVisible può anche consentire un'implementazione più semplice. Ad esempio, se una determinata classe concreta semplicemente delega il metodo alle sue classi composite, quindi SetVisible significa un metodo in meno da implementare.

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}
    
risposta data 20.03.2014 - 17:09
fonte
34

Non sono d'accordo con tutti i poster che suggeriscono più funzioni per fare la stessa cosa è una buona cosa. Sebbene tre funzioni anziché una non sembrino molto gonfie, ricorda che la tua classe probabilmente finirà con molte di queste funzioni (ad esempio setEnabled , enable , disable ) e quindi questo approccio finirà con un < em> molto interfaccia di classe più grande. Inoltre, è probabile che ti ritroverai con una serie di funzioni / proprietà / qualsiasi suono simili nella tua classe e la moltiplicazione delle funzioni oscurerà ulteriormente qual è il tuo obiettivo.

Nelle lingue che supportano le proprietà, queste dovrebbero essere preferite ma poiché né Java né C ++ lo fanno, immagino che sia un punto controverso.

Penso che setVisible() debba essere preferito per questi motivi:

  1. È immediatamente evidente quale sia la funzione inversa. Per invertire setVisible(false) chiami setVisible(true) mentre il contrario di hide() potrebbe facilmente essere reveal() .
  2. È più semplice a livello di codice ogni volta che determini quale stato deve assumere il codice, ad esempio puoi chiamare setVisible(wantToSee) anziché utilizzare un'istruzione if .
  3. Una volta che hai più funzioni simili, il formato setX() si generalizza in modo da poter avere un insieme di funzioni coerenti mentre l'approccio verbed genera una serie di funzioni che possono essere difficili da localizzare se non sai cosa stai cercando per. La coerenza delle API li rende notevolmente più facili da imparare e ricordare.
risposta data 21.03.2014 - 00:08
fonte
18

Dipende da cosa mostrare e nascondere significa nel contesto. Prima di tutto, vuoi capire qual è la tua "via principale" e concentrarti sullo sviluppo di questo:

  • Motivi per selezionare setVisible(bool)
    • È solo un semplice capovolgimento, o il tuo oggetto ha principalmente lo stato
    • Il tuo oggetto trascorrerà la maggior parte del suo tempo in un framework CRUD
    • C'è un sacco di codice facilmente condiviso tra mostrare e nascondere
  • Motivi per selezionare show() e hide()
    • Ci sono importanti effetti collaterali o molta logica in esecuzione, come quando l'oggetto deve controllare tutti i suoi contenitori per il loro stato di visibilità, o innesca un'animazione di transizione.
    • Fa parte di un modello di dominio in cui esprimere intento è importante

OK, ora che hai codificato il nucleo del "gold standard", devi capire se valga la pena di aggiungere metodi di convenienza nell'altro stile, per rendere la vita più semplice a chiunque stia per usare il tuo oggetto.

  • Convenienza di setVisible(bool)
    • Consente di evitare le if-statement che presentano condizioni insignificanti e influiscono solo sulla visibilità (ad esempio setVisible(a==b) )
    • Può essere cablato in determinati framework getter / setter, se è questo che ti aspetti che succeda
  • Convenienza di show() e hide()
    • Utile in una lingua con funzioni e callback di prima classe (ad esempio onSuccess(widget.show) )
    • Molto più facile da leggere con stack-trace e performance profiling, dal momento che puoi vedere rapidamente cosa stava cercando di fare il programma

TLDR: Scopri qual è il più importante, implementalo e poi chiediti se vale la pena aggiungere l'altro stile come metodo di convenienza sottile.

    
risposta data 20.03.2014 - 22:10
fonte
10

Direi "tutti e tre".

Show() e Hide() tendono ad essere più facili da trovare rispetto a SetVisible(true) e SetVisible(false) . Tuttavia, quando vuoi impostare la visibilità logicamente è meglio avere un metodo che prende un bool invece di costruire un if attorno a quel bool .

È possibile supportare tutti e tre gli elementi senza duplicare la logica e il boilerplate minimo:

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

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

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

In alternativa, se le cose che stai tagliando hanno una API SetVisible -ish:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}
    
risposta data 20.03.2014 - 18:50
fonte
4

Preferisco show () e hide (), infatti, ogni metodo che riceve un booleano può essere modificato per due metodi tan express meglio l'intenzione dell'API. Ad esempio, Robert Martin nel codice pulito consiglia di preferire i metodi con zero argomenti rispetto ai metodi con un argomento.

Un altro argomento importante per me è la leggibilità, secondo me un buon codice può essere letto come la prosa, la sua prosa davvero strana, qualcosa come "main_window setVisible false" invece di "main_window hide", scrivi o parli così normalmente ?, perché usare questa strana costruzione linguistica nei programmi software quando è perfettamente possibile usare un linguaggio più naturale?

    
risposta data 20.03.2014 - 23:03
fonte
4

Credo che più il metodo sia espressivo, più leggibile e, di conseguenza, mantenibile il codice. Considera i seguenti due casi:

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);
}

Nel primo caso, è chiaro che cosa sta facendo la funzione "setVisible", ma se vuoi leggerlo, diresti:

set the customer panel to visible if the customer is enabled or set it to hidden if the customer is disabled.

Mentre è più descrittivo per dire:

  • check the status of the customer:
    • if the customer is enabled then show the customer's panel
    • otherwise, hide it

che cambierà la funzione "Caso 1" nel seguente:

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

produce più codice, ma è più leggibile.

Il secondo caso ha un difetto evidente, ovvero, sai già che vuoi mostrare il pannello, quindi perché non usare la funzione "Mostra"?

Non sto dicendo che usare "setVisible" sia assolutamente sbagliato, ma diventa confuso quando si tenta di leggere il codice non scritto da te nel tempo, e non è conforme alla regola "Una funzione dovrebbe eseguire solo una operazione" .

    
risposta data 21.03.2014 - 00:25
fonte
4

Credo che l'alternativa Hide() / Show() sia interessante perché è più facile capire cosa sta succedendo che con SetVisible(true) , mentre è preferibile una singola funzione perché evita molti condizionali.

Se è così, ti suggerisco di utilizzare un'enumerazione come input per SetVisible , quindi ottieni SetVisible(Visibility.Visible) o SetVisible(Visibility.Hidden) . Hai una singola funzione che puoi leggere istantaneamente quale azione viene intrapresa.

Utilizzando le convenzioni di denominazione di Java, potresti avere setVisible(Visibility.VISIBLE) o setVisible(Visibility.HIDDEN) .

    
risposta data 23.03.2014 - 06:37
fonte
2

Suggerirei un'interfaccia leggermente modificata:

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

Nomi migliori

Questi nomi di metodi aiutano lo sviluppatore a decidere quale metodo utilizzare in base a ciò che deve essere fatto. Mentre SetVisible(bool visible) può confondere uno sviluppatore perché trasmette lo stesso significato semantico di Show() e Hide() , Toggle() implica l'esistenza di una condizione che determina l'azione. Diventa quindi intuitivo per lo sviluppatore quando utilizzare ciascun metodo.

Ridondanza ridondata del codice

Il vantaggio di avere più metodi nell'interfaccia è che semplifica il codice chiamante. Potresti semplicemente esporre Show() e Hide() , ma:

  • Probabilmente avrai bisogno di una sorta di metodo SetVisible() privato per eseguire il vero lavoro dietro le quinte (o scrivere codice ridondante per Show() e Hide() ).
  • Il codice chiamante potrebbe avere molti blocchi ridondanti se / else solo per scegliere quale metodo utilizzare. A mio parere, questo blocca il codice.
  • Se fossi il consumatore, probabilmente scriverò semplicemente la mia funzione wrapper che fa ciò che SetVisible() (o Toggle() ) già fa per evitare che il codice si gonfia (io odio il codice ridondante). Quindi duplicando un metodo che probabilmente esiste già come metodo privato nell'implementazione.
risposta data 21.03.2014 - 18:04
fonte
2

Sono d'accordo con la risposta di Darien, ma volevo aggiungere un punto di vista da una prospettiva di programmatori C #.

Quando vedo il codice che dice 'setXXX' leggo che per dire che sta impostando un valore su una cosa, non mi aspetto che questo abbia effetti collaterali in quella cosa oltre a impostare quel valore, e mi aspetto questo essere idempotente (cioè posso continuare a impostarlo con lo stesso valore e va bene). È piuttosto come accedere a un campo. In genere mi aspetto anche di vedere un metodo 'getXXX' insieme a un 'setXXX'.

Non so se questo è quello che ti aspetti da Java e C ++, ma è quello che mi aspetterei in C #, anche se in C # c'è una mano breve per questo chiamato Proprietà. Ecco alcune utili indicazioni su come utilizzare Proprietà ( link ).

Dato questo punto di vista, l'interfaccia che selezionerei dipende puramente se ci sono effetti collaterali (oltre a cambiare il valore del campo):

Se l'azione ha effetti collaterali, ad esempio mostra una finestra di dialogo, quindi andrei con "Mostra ()" e "Nascondi ()".

Se non ha effetti collaterali, diciamo che sto impostando la visibilità di un "widget" e qualcos'altro restituisce quel widget a seconda del suo stato, quindi userei setVisibility o setIsVisible. (Non lo chiamerei SetVisible).

In C # (non sono sicuro di Java) è piuttosto comune adottare un pattern di osservatore, in cui un framework dell'interfaccia utente ascolterà le modifiche agli oggetti e re-render automaticamente l'interfaccia quando una proprietà come Visibility cambia. Ciò significa che l'impostazione del valore chiamando setIsVisible appare come se avesse effetti collaterali, ma nella mia definizione non lo fa. Il contratto del widget è soddisfatto impostando il suo valore di campo che rappresenta "IsVisible".

In altre parole, per me è giusto abilitare la visibilità di un'etichetta su un modulo prima che venga visualizzato il modulo. IE label.getIsVisible == true, ma il modulo non è mostrato.

Non è corretto per me chiamare Hide () quando il modulo non viene mostrato.

    
risposta data 22.03.2014 - 06:30
fonte
0

Suggerirei di usare SetVisible(bool) se solo se si attiva la visibilità due volte (mostra e si ri-nasconde, o si nasconde e si ripresenta) lascerebbe le cose nello stesso stato di prima dell'operazione (va bene se mostra e nasconde qualcosa o viceversa lascia oggetti che necessitano di un ridisegno, a condizione che ci si possa aspettare che accada "automaticamente"). Se nascondere e mostrare un oggetto non avrà alcun effetto se non quello di cambiare un bit di stato, allora avrebbe senso per codice esterno avere alcuni metodi che accettano un parametro di visibilità, e la scrittura di tale codice sarà facilitata da SetVisible .

Se nascondere e ri-mostrare un oggetto potrebbe avere effetti collaterali come cambiare l'ordine Z, tali azioni dovrebbero essere più probabilmente eseguite con metodi separati. In questi casi, l'utilità dei metodi esterni che accettano un parametro di "visibilità" sarà limitata, e quindi ci sarà un piccolo vantaggio nel facilitare loro. Inoltre, un metodo SetVisible suggerirà (erroneamente) che le modifiche alla visibilità degli oggetti possano essere apportate senza effetti collaterali.

    
risposta data 23.03.2014 - 01:55
fonte

Leggi altre domande sui tag