是更好的Show()+ Hide()或SetVisible(bool可见)?


59

有什么更好的,为什么?(从界面设计的角度来看):

a)具有两个Show()Hide()函数

b)具有一项SetVisible(bool visible)功能

编辑:例如,某些对象具有可见性状态,并且可以使用此功能对其进行更改。

c)向有三个Show()Hide()SetVisible(bool visible)功能


4
在什么情况下?通常没关系
Aviv Cohn 2014年


6
为什么不将它们全部公开?在某些情况下,您知道它们将始终显示或隐藏,并且在某些情况下,您需要有条件地显示或隐藏。
2014年

@pllee:那可能是非常好的一点。
user3123061 2014年

4
在Java中,它将设置为setVisible,隐藏和显示,而不以大写字母开头。
皮埃尔·阿劳德

Answers:


81

我更喜欢SetVisible(bool visible),因为它可以让我这样编写客户端代码:

SetVisible(DetermineIfItShouldBeVisible());

不必写

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

SetVisible方法还可以允许更容易地实现。例如,如果特定的具体类仅将方法委托给其复合类,则SetVisible意味着要实现的方法要少一些。

void ButtonWithALabel::SetVisible(bool visible) {
    myButton.SetVisible(visible);
    myLabel.SetVisible(visible);
}

25
同样,假设您的语言支持,也可以将Visible设置为属性。 MyObject.Visible = false;在我看来是一个更加直观的比MyObject.SetVisible(false);
布赖恩·

9
@Brian对我来说,它的可读性和调试性较差,因为它使程序的行为对我而言是隐藏的-底层的方法调用-但这是另一回事了。Java不支持该语法,无论如何,这都是偏好和眼神训练的问题。
ignis 2014年

10
SetVisible()并没有(对我)暗示您实际上在显示任何东西。它读起来就像是在设置对象的可见性属性一样,可能将其留给相应的Refresh()Redisplay()方法来检查此属性的值以确定该对象是显示还是隐藏。
TMN 2014年

1
不幸的是,Java不支持C#所支持的属性,仅支持您在上面看到的getter和setter。
theGreenCabbage 2014年

1
@TMN:我希望在没有其他因素阻止可见性的情况下(Z顺序,父级可见性,位置等),setVisible(true)可以启动一个过程,在该过程中,如果下一次系统空闲,则对象将在下次空闲时被绘制。我希望这refresh可能有助于加快对象的显示,但是无论如何对象最终都会被绘制(除非它的可见性设置为false发生之前)。
超级猫

35

我不同意所有张贴者的意见,认为张贴者具有多种功能可以做同一件事。虽然三大功能,而不是一个可以看起来不多膨胀,记住,你的类是很有可能最终与很多这样的功能(例如setEnabledenabledisable),因此这种做法将结束与一个较大的类接口。此外,您可能最终会在类中得到一堆类似的听起来功能/属性/所有内容,而函数的乘法将进一步模糊哪一个与什么一起使用。

在支持属性的语言中,应该首选这些属性,但是由于Java和C ++都不支持,所以我想这是有争议的。

我认为,setVisible()出于以下原因,应首选:

  1. 显而易见,反函数是什么。为了扭转setVisible(false)你打电话setVisible(true),而相反hide()可以很容易地reveal()
  2. 无论何时确定代码应采用哪种状态,它在编程上都更加简单,例如,您可以调用setVisible(wantToSee)而不是使用if语句。
  3. 一旦具有多个相似的函数,该setX()格式即会泛化,因此您可以拥有一组一致的函数,而动词方法会产生许多函数,如果您不知道要查找的内容,这些函数可能很难定位。API的一致性使它们易于学习和记忆。

3
C ++没有属性,但是它具有自由函数,因此您可以扩展类接口而无需添加新的成员函数,即具有较低的耦合度。
phresnel 2014年

Qt通常会提供所有这三个方便,以便可以使用信号/插槽系统将hide()和show()直接连接到其他事件。但是,这实际上是对插槽系统的限制-如果它使用的是boost :: functions之类的东西,则可以在设置回调时绑定true / false参数。

1
“在支持属性的语言中,应该首选这些属性,但是由于Java和C ++都不支持,所以我想这是有争议的。” 不必要。优先于吸气剂/设置者?是。但是set_visible实际上不是setter。
Miles Rout 2014年

19

这取决于在上下文中显示和隐藏的含义。首先,您想弄清楚哪一种是您的“主要方式”,然后着重开发:

  • 选择理由 setVisible(bool)
    • 这只是一个简单的翻转,或者您的对象主要处于保持状态
    • 您的对象将花费大部分时间在CRUD框架中
    • 显示和隐藏之间有很多易于共享的代码
  • 原因挑选show()hide()
    • 有重要的副作用或大量的逻辑正在运行,例如当对象必须检查其所有容器可见性状态或触发过渡动画时。
    • 表达意图的领域模型的一部分是否重要

好的,现在您已经编码了它的“黄金标准”核心,您需要弄清楚它是否值得添加其他样式的便捷方法,以使使用对象的人更轻松。

  • 方便 setVisible(bool)
    • 让您避免有琐碎的条件,不仅影响能见度if语句(前。setVisible(a==b)
    • 可以连接到某些getter / setter框架中,如果您希望发生这种情况
  • show()和的便利hide()
    • 在具有一流功能和回调的语言中很有用(例如onSuccess(widget.show)
    • 借助堆栈跟踪和性能分析,它更容易阅读,因为您可以快速查看程序试图执行的操作

TLDR:找出最重要的一种,实施它,然后问自己是否值得添加另一种样式作为简便方法。


11

我会说“全部三个”。

Show()并且Hide()往往比SetVisible(true)和更容易被欺骗SetVisible(false)。但是,当您想在逻辑上设置可见性时,最好采用一个采用a的方法,bool而不是构造一个if围绕that的方法bool

您可以支持所有这三个,而无需重复逻辑和简化模板:

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

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

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

或者,如果您要包装的东西具有更多的SetVisible-ish API:

void Show() {
    SetVisible(true);
}

void Hide() {
    SetVisible(false);
}

void SetVisible(bool visible) {
    foo.SetVisible(visible);
    bar.SetVisible(visible);
}

40
Microsoft使用此方法来启动和停止System.Windows.Forms.Timer。我个人觉得这很令人困惑。当我同时看到Show和时SetVisible,我的第一个倾向是想知道这两个函数之间是否存在一些重要的区别。
布莱恩(Brian)

1
您可以轻松地记录它们,以消除这种混乱。我不是,因为这只是一个简单的例子。
Garry Shutler 2014年

20
因此,现在我需要花X分钟的时间阅读文档,然后才开始使用该类?或者,或者,我需要浪费X额外的几分钟的时间来混淆(或引入错误)?当然,对于这种事情,X很小,但是绝对不是零。提供所有3个选项意味着提供所需功能的三倍,这意味着您花费更多的工作文档,而我花费更多的工作来学习如何使用该类。此外,它还为使用类的不同开发人员引入了另一种不一致的方法。
布莱恩(Brian)

5
这明显违反了SOLID原则之一的接口隔离原则。反对您的方法的另一种观点是netbeans设计师jaroslav tulach的观点,他坚持在他的实用API设计书中多次提出只提供一种在API中执行某件事的方法。
AlfredoCasado 2014年

@AlfredoCasado我同意。如果SetVisible 受保护怎么办?您可以从子类访问它,但是使用此接口(例如API)调用给定实体必须是Hide / Show。
皮埃尔·阿劳德

5

我更喜欢show()和hide(),实际上,可以将每个接收一个布尔值的方法更改为两种,以便更好地表达API的意图。例如,罗伯特·马丁(Robert Martin)在干净代码中建议带零参数的方法比带一个参数的方法更受欢迎。

对我来说,另一个重要的论据是可读性,在我看来,好的代码可以像散文一样阅读,其真正奇怪的散文如“ main_window setVisible false”而不是“ main_window hide”,您通常会像这样写或说话吗?软件程序中的语言构造何时完全有可能使用更自然的语言?


1
汇编器散文不够吗?
亚历山大

我希望序列it.setVisible(false); it.setVisible(true);不会影响控件父级的可见性,也不会影响控件的Z顺序或位置。相比之下,hide(); show(); 可能会迫使控件的父控件可见,将其移到其他控件上方,并将其位置限制在可以看到的位置。在某些情况下,有一种确保某种东西实际可见的方式很有用(与前面提到的一样show(),但在其他情况下,更改可见性标志而不更改其他任何方式都是有用的
。– supercat

在面向对象的API中,没有“标志”,OO是关于消息传递的,它是关于告诉其他对象执行某些任务的,而不是更改作为对象状态的“标志”。您正在对控件,父项,z顺序以及您可能期望的事情做出许多假设,这可能是基于您以前使用其他API的经验,这是一个非常糟糕的主意,要根据个人对领域的看法和假设来设计API。
AlfredoCasado 2014年

5

我的确相信,该方法表达性越强,代码就越易读,因此更易于维护。请考虑以下两种情况:

情况1:

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

情况2:

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

在第一种情况下,很明显函数“ setVisible”正在做什么,但是如果您想阅读它,您会说:

如果启用了客户,则将客户面板设置为可见;如果禁用了客户,则将其设置为隐藏。

虽然更具描述性地说:

  • 检查客户的状态:
    • 如果启用了客户,则显示客户面板
    • 否则,将其隐藏

这会将“案例1”功能更改为以下内容:

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

它产生更多的代码,但更具可读性。

第二种情况有一个明显的缺陷,那就是,您已经知道要显示面板,那么为什么不使用“显示”功能呢?

我并不是说使用“ setVisible”是绝对错误的,但是当您尝试读取一段时间以来您自己编写的代码时,它会造成混乱,并且它不符合“一个函数应仅执行一个操作”规则。


我会说:show customer panel iff the user/customer is enabled。我确实同意,可能有很多更复杂的条件不像您的示例那么容易理解,但是,在那种情况下,我会将这些条件分成不同的行。
ComFreek

5

我相信Hide()/ Show()替代方法很有吸引力,因为比起使用SetVisible(true),它更容易理解正在发生的事情,而具有单个函数是可取的,因为它避免了很多条件。

如果是这种情况,那么我建议使用枚举作为输入SetVisible,因此您将获得SetVisible(Visibility.Visible)SetVisible(Visibility.Hidden)。您只有一个功能,可以立即读取正在执行的操作。

使用Java的命名约定,您可能会有setVisible(Visibility.VISIBLE)setVisible(Visibility.HIDDEN)


3

我同意Darien的回答,但想从C#程序员的角度来补充一点观点。

当我看到说“ setXXX”的代码时,我读到它是在为某事物设置值,我不希望这会在该事物上产生副作用,除了设置该值,而且我希望这是幂等的(即我可以继续将其设置为相同的值,这没关系)。这就像访问一个字段。通常,我也希望看到一个“ getXXX”方法以及一个“ setXXX”。

我不知道这是否是您在Java和C ++中所期望的,但这就是我在C#中所期望的,尽管在C#中有一个简称为Properties。这是有关如何使用属性的一些不错的指导(http://msdn.microsoft.com/zh-cn/library/ms182181.aspx)。

给定此视图,那么我选择的接口将完全取决于是否存在任何副作用(除了更改该字段值之外):

如果执行该操作有副作用,例如,它显示一个对话框,那么我将使用“ Show()”和“ Hide()”。

如果没有副作用,例如说我正在设置“窗口小部件”的可见性,并且其他部件根据其状态渲染该窗口小部件,那么我将使用setVisibility或setIsVisible。(我不会将其称为SetVisible)。

在C#(不确定Java)中,采用观察者模式非常普遍,其中UI框架将侦听对象的更改,并在诸如Visibility之类的属性发生更改时自动重新呈现UI。这意味着通过调用setIsVisible设置值似乎具有副作用,但在我的定义中没有。通过设置代表“ IsVisible”的字段值来实现小部件的合同。

换句话说,我可以在显示表单之前切换标签在表单上的可见性。即label.getIsVisible == true,但是未显示该表单。

当表单不显示时,我不能调用Hide()。


1
您作为一种没有副作用的访问字段的方法的描述getXXX()setXXX()方法听起来像Java,而不是 C#。这是您在Java中必须执行的方法,因为它没有属性。如果我在C#中看到类似的代码,我猜它是由尚未了解C#属性的Java开发人员编写的。
gilly3 2014年

为+1 SetVisibility
阿卡塔尔

@ gilly3-是的,当然。而且,CLR中不存在“属性”,C#转换为IL中的方法调用get_XXX和set_YYY。我的观点是:在问题的上下文中,如果您在Java中看到过setXXX,getXXX,则希望它与C#中的属性具有相同的语义。没错,那么我认为C#中相同的属性准则适用于Java中的setXXX和getXXX对。我碰巧同意我在帖子中引用的指南,因此,在定义接口时,我主张在Java中用于该场景的相同指南。
Daniel James Bryars 2014年

1
这可能有助于澄清,当您指的是“副作用”时,您的意思是“与成为“可观察的”事物有关的那些事物以外的事物”。我赞成的规则是说,如果getXX调用具有相应的setXX方法,则setYY不应影响它,但可能会影响getZZ没有setZZ方法的调用。
超级猫2014年

2

我建议稍微修改一下界面:

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

更好的名字

这些方法名称可帮助开发人员根据需要完成的工作来决定使用哪种方法。鉴于SetVisible(bool visible)开发人员传达的语义与Show()和相同,可能会使开发人员感到困惑Hide(),这Toggle()意味着存在确定操作的条件。因此,开发人员何时使用每种方法都变得直观。

减少代码冗余

在界面中具有多个方法的好处是它简化了调用代码。您可以公开Show()Hide(),但是:

  • 您可能需要某种SetVisible()私有方法来进行幕后的实际工作(或为Show()和编写冗余代码Hide())。
  • 调用代码可能有许多多余的if / else块,只是为了选择要使用的方法。我认为这会使代码膨胀。
  • 如果我是消费者,我可能会写我自己的包装函数,该函数可以执行SetVisible()(或Toggle())已经执行的操作以避免代码膨胀(我讨厌冗余代码)。因此,复制了可能已经在实现中作为私有方法存在的方法。

1
方法重复听起来很合理,尽管我自己不会这样做。另一方面,我不同意toggleVisible(bool)是直观的。对我来说,这意味着如果传入的布尔值是true,则应该切换,这很奇怪,但是我见过陌生人。它不会假设它实际上是一个变相的集合函数。
Patrick M

0

我建议SetVisible(bool)仅在两次切换可见性(显示并重新隐藏,或隐藏并重新显示)的情况下使用(如果有的话),这会使事物基本上保持与执行操作之前相同的状态(如果显示并重新隐藏则很好)反之亦然,如果需要“自动”发生,则需要重新绘制对象。如果隐藏和显示对象只改变一个状态就没有其他效果,那么对外部代码来说,拥有一些可以接受可见性参数的方法是有意义的,并且可以简化此类代码的编写SetVisible

如果隐藏和重新显示对象可能有副作用,例如更改Z顺序,则应更可能通过单独的方法执行此类操作。在这种情况下,接受“可见性”参数的外部方法的实用性将受到限制,因此简化这些方法的好处很小。此外,一种SetVisible方法将(错误地)建议可以无副作用地完成对对象可见性的更改。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.