Delphi 为什么从代码中调用eventhandler是一种不好的做法?

Delphi 为什么从代码中调用eventhandler是一种不好的做法?,delphi,vb6,coding-style,realbasic,Delphi,Vb6,Coding Style,Realbasic,假设您有一个菜单项和一个按钮来执行相同的任务。 为什么将任务的代码放入一个控件的操作事件中,然后从另一个控件调用该事件是不好的做法? Delphi和vb6一样允许这样做,但realbasic不允许,并说您应该将代码放入一个方法中,然后由菜单和按钮调用该方法,因为您应该将内部逻辑与其他函数分离,并调用此函数 从两个事件处理程序 如果需要,请与代码分开 这是一个更优雅的解决方案,更易于维护。显然更整洁。但易用性和生产力当然也始终很重要 在Delphi中,我通常不会在严肃的应用程序中使用它,但我会在小

假设您有一个菜单项和一个按钮来执行相同的任务。 为什么将任务的代码放入一个控件的操作事件中,然后从另一个控件调用该事件是不好的做法?
Delphi和vb6一样允许这样做,但realbasic不允许,并说您应该将代码放入一个方法中,然后由菜单和按钮调用该方法,因为您应该将内部逻辑与其他函数分离,并调用此函数

  • 从两个事件处理程序
  • 如果需要,请与代码分开

  • 这是一个更优雅的解决方案,更易于维护。

    显然更整洁。但易用性和生产力当然也始终很重要

    在Delphi中,我通常不会在严肃的应用程序中使用它,但我会在小程序中调用EventHandler。如果小东西以某种方式演变成更大的东西,我会清理它,通常同时增加逻辑UI分离


    但我知道,在拉扎勒斯/德尔福,这并不重要。其他语言可能会将更特殊的行为附加到EventHandler。

    关注点分离。类的私有事件应该封装在该类中,而不是从外部类调用。如果对象之间有强大的接口,并尽量减少多个入口点的出现,这将使您的项目更容易更改。

    假设在某个时候,您认为菜单项不再有意义,并且希望删除菜单项。如果只有一个控件指向菜单项的事件处理程序,这可能不是什么大问题,您可以将代码复制到按钮的事件处理程序中。但是,如果您有几种不同的调用代码的方法,那么您将不得不做很多更改


    就我个人而言,我喜欢Qt处理这个问题的方式。有一个QAction类,它自己的事件处理程序可以挂接,然后QAction与需要执行该任务的任何UI元素相关联。

    为什么这是一种不好的做法?因为当代码没有嵌入到UI控件中时,重用代码要容易得多


    为什么不能用REALbasic做呢?我怀疑有任何技术原因;这可能只是他们做出的设计决定。当然,它确实加强了更好的编码实践。

    假设您在某个时候决定菜单应该做一些稍微不同的事情。也许这种新的变化只发生在某些特定的情况下。你忘记了按钮,但现在你也改变了它的行为


    另一方面,如果你调用一个函数,你不太可能改变它的功能,因为你(或下一个家伙)知道这会产生不良后果。

    这是一个如何组织程序的问题。在您描述的场景中,菜单项的行为将根据按钮的:

    procedure TJbForm.menuitem1单击(发送方:TObject);
    开始
    //三种不同的写作方式,有着微妙的不同
    //解读方式:
    按钮1单击(发送者);
    // 1. “调用其他函数。名称表明它是
    //还处理按钮单击的函数。”
    按钮1.OnClick(发送方);
    // 2. “单击按钮时,调用我们调用的任何方法。”
    //(希望财产不是零!)
    按钮1.点击;
    // 3. “假装按钮已单击。”
    结束;
    
    这三种实现中的任何一种都可以工作,但是为什么菜单项如此依赖于按钮?按钮有什么特别之处,它应该定义菜单项?如果一个新的UI设计去掉了按钮,菜单会发生什么变化?更好的方法是考虑事件处理程序的操作,使其独立于所附加的控件。有几种方法可以做到这一点:

  • 一种方法是完全放弃
    MenuItem1Click
    方法,并将
    按钮1click
    方法指定给
    MenuItem1.OnClick
    事件属性。为菜单项的事件指定按钮来命名方法是令人困惑的,因此您需要重命名事件处理程序,但这没关系,因为与VB不同,Delphi的方法名称不定义它们处理的事件。只要签名匹配,就可以将任何方法分配给任何事件处理程序。两个组件的OnClick事件都属于
    TNotifyEvent
    类型,因此它们可以共享一个实现指定方法的名称,而不是它们所属的名称。

  • 另一种方法是将按钮的事件处理程序代码移动到单独的方法中,然后从两个组件的事件处理程序调用该方法:

    procedure HandleClick;
    开始
    //做点什么。
    结束;
    程序TJbForm.Button1Click(发送者:ToObject);
    开始
    手舔;
    结束;
    程序TJbForm.MenuItem1单击(发送方:ToObject);
    开始
    手舔;
    结束;
    
    这样,真正起作用的代码就不会直接绑定到这两个组件,让您可以更轻松地更改这些控件,例如重命名它们,或者用不同的控件替换它们。将代码与组件分离将我们引向第三种方式:

  • delphi4中引入的
    TAction
    组件是专门为您所描述的情况而设计的,在这种情况下,同一命令有多个UI路径。(其他语言和开发环境提供了类似的概念;它不是Delphi独有的。)将事件处理代码放入
    TAction
    OneExecute
    事件处理程序中,然后将该操作分配给按钮和菜单项的
    action
    属性

    procedure TJbForm.Action1Click(发送方:TObject);
    开始
    //做点什么
    //(取决于此事件的行为与
    //操纵其余的UI控件,可能会
    //保持我上面提到的HandleClick函数的意义。)
    结束;
    
    想再加一个吗