É melhor Show () + Hide () ou SetVisible (bool visible)?

58

O que é melhor e por quê? (Do ponto de vista do design de interface):

a) Para ter duas funções Show() e Hide()

b) Para ter uma função SetVisible(bool visible)

EDIT: Por exemplo, algum objeto tem estado de visibilidade e esta função é usada para alterá-lo.

c) Para ter todas as três Show() , Hide() , SetVisible(bool visible) functions

    
por user3123061 20.03.2014 / 17:00
fonte

10 respostas

82

Eu prefiro SetVisible(bool visible) , porque me permite escrever o código do cliente assim:

SetVisible(DetermineIfItShouldBeVisible());

em vez de ter que escrever

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

A abordagem SetVisible também pode permitir uma implementação mais fácil. Por exemplo, se uma determinada classe concreta simplesmente delega o método a suas classes compostas, então SetVisible significa um método a menos para implementar.

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}
    
por 20.03.2014 / 17:09
fonte
34

Eu não concordo com todos os pôsteres que sugerem múltiplas funções para fazer a mesma coisa é uma coisa boa. Embora três funções, em vez de uma, possam não parecer muito inchadas, lembre-se de que sua classe provavelmente terá muitas dessas funções (por exemplo, setEnabled , enable , disable ) e, portanto, essa abordagem terminará com um < em> muito interface de classe maior. Além disso, é provável que você acabe com um monte de funções / propriedades semelhantes a sons semelhantes em sua classe e a multiplicação de funções obscurecerá ainda mais o que se combina com o que.

Em linguagens que suportam propriedades, elas devem ser preferidas, mas como nem o Java nem o C ++, acho que é um ponto discutível.

Acho que setVisible() deve ser preferido por estas razões:

  1. É imediatamente óbvio qual é a função inversa. Para reverter setVisible(false) , chame setVisible(true) , enquanto o oposto de hide() poderia facilmente ser reveal() .
  2. É programaticamente mais simples sempre que você está determinando o estado que deve ter no código, ou seja, você pode chamar setVisible(wantToSee) em vez de usar uma instrução if .
  3. Depois de ter várias funções semelhantes, o formato setX() generaliza para que você possa ter um conjunto de funções consistentes, enquanto a abordagem verbed gera uma série de funções que podem ser difíceis de localizar se você não sabe o que está procurando para. A consistência nas APIs torna-as consideravelmente mais fáceis de aprender e lembrar.
por 21.03.2014 / 00:08
fonte
18

Depende do que mostra e oculta significa no contexto. Primeiro você quer descobrir qual é o seu "caminho principal" e focar no desenvolvimento disso:

  • Razões para escolher setVisible(bool)
    • É apenas um simples bit-flip, ou o seu objeto está principalmente no estado
    • Seu objeto passará a maior parte do tempo em uma estrutura CRUD
    • Há muito código compartilhado entre mostrar e ocultar
  • Razões para escolher show() e hide()
    • Há importantes efeitos colaterais ou muitas lógicas sendo executadas, como quando o objeto precisa verificar todos os seus contêineres para o estado de visibilidade deles ou aciona uma animação de transição.
    • É parte de um modelo de domínio em que expressar intenção é importante

OK, agora que você codificou o núcleo "padrão ouro", é necessário descobrir se vale a pena adicionar métodos de conveniência finos no outro estilo, para facilitar a vida de quem quer que seja que vai usar seu objeto.

  • Conveniência de setVisible(bool)
    • Permite que você evite declarações que tenham condições triviais e afetem apenas a visibilidade (ex. setVisible(a==b) )
    • Pode ser conectado a determinadas estruturas getter / setter, se isso for algo que você espera que aconteça
  • Conveniência de show() e hide()
    • Útil em um idioma com funções de primeira classe e retornos de chamada (ex. onSuccess(widget.show) )
    • Muito mais fácil de ler com rastreamentos de pilha e perfil de desempenho, pois você pode ver rapidamente o que o programa estava tentando fazer

TLDR: Descubra qual é o mais importante, implemente-o e, em seguida, pergunte a si mesmo se vale a pena adicionar o outro estilo como métodos de conveniência simples.

    
por 20.03.2014 / 22:10
fonte
10

Eu diria "todos os três".

Show() e Hide() tendem a ser mais fáceis de obter do que SetVisible(true) e SetVisible(false) . No entanto, quando você deseja definir a visibilidade logicamente, é melhor ter um método que use bool em vez de criar um if em torno desse bool .

Você pode suportar todos os três sem duplicar a lógica e o mínimo de clichê:

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

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

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

Como alternativa, se as coisas que você está envolvendo tiverem mais uma API SetVisible -ish:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}
    
por 20.03.2014 / 18:50
fonte
4

Eu prefiro show () e hide (), na verdade, todo método que recebe um booleano pode ser alterado por dois métodos tan expressar melhor a intenção da API. Por exemplo, Robert Martin em código limpo recomenda métodos preferidos com zero argumentos sobre métodos com um argumento.

Outro argumento importante para mim é a legibilidade, na minha opinião um código bom pode ser lido como prosa, sua prosa realmente estranha algo como "main_window setVisible false" em vez de "main_window hide", você escreve ou fala assim normalmente? usar esta construção de linguagem estranha em programas de software quando é perfeitamente possível usar uma linguagem mais natural?.

    
por 20.03.2014 / 23:03
fonte
4

Eu acredito que quanto mais o método for expressivo, mais legível e, conseqüentemente, passível de manutenção, o código será. Considere os dois casos a seguir:

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

No primeiro caso, está claro o que a função "setVisible" está fazendo, mas se você quiser ler, você diria:

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

Embora seja mais descritivo dizer:

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

que mudará a função "Caso 1" para o seguinte:

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

produz mais código, mas é mais legível.

O segundo caso tem uma falha óbvia, ou seja, você já sabe que quer mostrar o painel, então porque não usar a função "Show"?

Não estou dizendo que o uso de "setVisible" esteja totalmente errado, mas fica confuso quando você tenta ler o código não escrito por você com o tempo e não está de acordo com a regra "Uma função deve executar apenas uma operação" .

    
por 21.03.2014 / 00:25
fonte
4

Eu acredito que a alternativa Hide() / Show() é atraente porque é mais fácil entender o que está acontecendo do que com SetVisible(true) , enquanto ter uma única função é preferível porque evita muitos condicionais.

Se esse for o caso, sugiro usar uma enumeração como entrada para SetVisible , para obter SetVisible(Visibility.Visible) ou SetVisible(Visibility.Hidden) . Você tem uma única função que pode ler instantaneamente qual ação está sendo tomada.

Usando as convenções de nomenclatura do Java, você teria talvez setVisible(Visibility.VISIBLE) ou setVisible(Visibility.HIDDEN) .

    
por 23.03.2014 / 06:37
fonte
2

Eu sugeriria uma interface ligeiramente modificada:

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

Melhores nomes

Esses nomes de métodos ajudam o desenvolvedor a decidir qual método usar com base no que precisa ser feito. Considerando que SetVisible(bool visible) pode confundir um desenvolvedor porque transmite o mesmo significado semântico que Show() e Hide() , Toggle() implica a existência de uma condição que determina a ação. Assim, torna-se intuitivo para o desenvolvedor quando usar cada método.

Redução do código reduzido

O benefício de ter vários métodos em sua interface é que simplifica o código de chamada. Você pode expor apenas Show() e Hide() , mas:

  • Você provavelmente exigiria algum tipo de método SetVisible() private para realizar o trabalho real nos bastidores (ou escrever código redundante para Show() e Hide() ).
  • O código de chamada pode ter muitos blocos if / else redundantes apenas para escolher o método a ser usado. Isso incita o código na minha opinião.
  • Se eu fosse o consumidor, provavelmente apenas escreveria minha própria função de wrapper que faz o que SetVisible() (ou Toggle() ) já faz para evitar o excesso de código (eu odeio código redundante). Assim, duplicando um método que provavelmente já existe como um método privado na implementação.
por 21.03.2014 / 18:04
fonte
2

Concordo com a resposta de Darien, mas queria adicionar um ponto de vista de uma perspectiva de programadores C #.

Quando vejo código que diz "setXXX" eu leio isso para dizer que ele está definindo um valor em uma coisa, eu não espero que isso tenha efeitos colaterais naquela coisa além de definir esse valor, e eu espero que isso para ser idempotente (ou seja, eu posso continuar configurando com o mesmo valor e está tudo bem). É como acessar um campo. Geralmente eu também esperaria ver um método 'getXXX' junto com um 'setXXX'.

Eu não sei se isso é o que você espera em Java e C ++, mas é isso que eu esperaria em C #, embora em C # há uma mão curta para este chamado Propriedades. E aqui estão algumas boas orientações sobre como usar as Propriedades ( link ).

Dada essa visão, a interface que escolheria depende apenas se houver efeitos colaterais (além de alterar o valor desse campo):

Se a ação tiver efeitos colaterais, por exemplo, se estiver mostrando uma caixa de diálogo, eu usarei "Show ()" e "Hide ()".

Se não houver efeitos colaterais, digamos que estou definindo a visibilidade de um "widget" e algo mais renderiza esse widget dependendo do estado, use o setVisibility ou o setIsVisible. (Eu não chamaria isso de SetVisible).

Em C # (não tenho certeza sobre Java), é muito comum adotar um padrão de observador, onde uma estrutura de UI irá escutar alterações nos objetos e automaticamente renderizar novamente a UI quando uma propriedade como Visibility for alterada. Isso significa que definir o valor chamando setIsVisible aparece como se tivesse efeitos colaterais, mas na minha definição isso não acontece. O contrato do widget é cumprido configurando seu valor de campo representando "IsVisible".

Por outras palavras, não há problema em alterar a visibilidade de um marcador em um formulário antes que o formulário seja exibido. Ou seja, label.getIsVisible == true, mas o formulário não é mostrado.

Não há problema em chamar o Hide () quando o formulário não está sendo exibido.

    
por 22.03.2014 / 06:30
fonte
0

Eu sugeriria usar SetVisible(bool) apenas se alternar a visibilidade duas vezes (mostrar e re-ocultar ou ocultar e mostrar novamente) deixaria as coisas essencialmente no mesmo estado de antes da operação ser executada (está tudo bem se mostrando e re-escondendo alguma coisa ou vice-versa, os objetos precisam de um redesenho, desde que se espere que isso aconteça "automaticamente". Se ocultar e mostrar um objeto não terá efeito além de alterar um bit de estado, então, faz sentido que o código externo tenha alguns métodos que aceitam um parâmetro de visibilidade, e a gravação desse código será facilitada por SetVisible .

Se ocultar e mostrar novamente um objeto pode ter efeitos colaterais, como alterar a ordem Z, essas ações provavelmente devem ser executadas por métodos separados. Em tais casos, a utilidade de métodos externos que aceitem um parâmetro de "visibilidade" será limitada e, portanto, haverá pouca vantagem em facilitá-los. Além disso, um método SetVisible (erroneamente) sugere que mudanças na visibilidade dos objetos podem ser realizadas sem efeitos colaterais.

    
por 23.03.2014 / 01:55
fonte