按钮点击事件的编码规范
Coding Standards for button click event
在将代码附加到默认按钮单击事件时,我试图遵循良好的编码标准。两个选项是: 在 Click 事件处理程序中包含几行代码 或 包含一个最终与这些代码行执行相同操作的方法。
什么是软件设计原则,或者我会使用一种或另一种方式的具体原因?
[此外,它是一个现有的标准 winforms 应用程序,只是得到了一些扩展。]
选项A:
private void btnExport_Click(object sender, EventArgs e)
{
var FileName = getFileName(reportPrefix);
if (fileName == null)
{
return;
}
SaveFile(fileName, QueryString);
}
选项 B:
private void btnExport_Click(object sender, EventArgs e)
{
DoExport();
}
private void DoExport()
{
var FileName = getFileName(reportPrefix);
if (fileName == null)
{
return;
}
SaveFile(fileName, QueryString);
}
我会推荐选项 B,原因如下:
关注分离:处理事件 (EventHandler) 或委托的代码与 分离完成实际工作并封装在另一个方法中的实际实现逻辑。
方法 DoExport
的意图从它的名字就很清楚了。如果有人阅读你的代码,它会被解释为
选项B: "When button is clicked Do export."
选项 A: "单击按钮时读取文件名,如果文件名是
清空然后 return,否则保存文件。"
哪个听起来更容易阅读?出于可读性目的,选项 B 提供了一种清晰简洁的方式来表达您的意图。
如果您决定将 button
更改为另一个控件,如锚点、链接按钮、标签或任何其他控件,则无需将事件处理程序与实现细节绑定。就像 DoExport
方法不应该依赖于 EventArgs' or the
sender` 对象。
将来,需要从代码中的其他地方调用导出功能 (DoExport
)。然后,您可以轻松调用 DoExport
方法。
测试: 如果你有这个方法 public 并且你想测试它。测试方法比编写代码引发事件然后测试功能要容易得多。
都不是,但是 B 比 A 更近:
SRP(单一职责原则)建议您将业务逻辑与 UI 分开,不仅是在方法级别,而且 至少是 class 级别(命名空间 and/or 库级别分隔也可能有用)。这是因为 UI 可能会独立于导出逻辑的变化而变化。
包含 btnExport_Click
的 UI class 负责驱动 UI,向用户显示数据并将点击等用户交互路由回业务逻辑.
和另外一个class完全一样,最好后面有一个抽象,理想的是一个接口(DIP,Dependency Inversion Principle),负责导出:
public class YouUIClass
{
IExporter exporter;
private void btnExport_Click(object sender, EventArgs e)
{
var fileName = GetFileName(reportPrefix);
if (fileName == null)
{
return;
}
exporter.DoExport(fileName);
}
}
public class Exporter : IExporter
{
public void DoExport(string fileName)
{
SaveFile(fileName, queryString);
}
}
(您可能需要将一些参数,例如 filename
或 queryString
从 UI 传递到导出器方法,正如我所演示的那样,因为我假设 GetFileName
是UI).
一个巨大的优势是您可以测试驱动业务逻辑,而无需 UI 参与。然后手动测试只是检查 UI 是否将事件正确转发到后续层。
当谈到以这种方式解耦 UI 时,您可以遵循一些模式而不是自己动手,例如 MVC、MVP 和 MVVM 等模式。
在将代码附加到默认按钮单击事件时,我试图遵循良好的编码标准。两个选项是: 在 Click 事件处理程序中包含几行代码 或 包含一个最终与这些代码行执行相同操作的方法。
什么是软件设计原则,或者我会使用一种或另一种方式的具体原因?
[此外,它是一个现有的标准 winforms 应用程序,只是得到了一些扩展。]
选项A:
private void btnExport_Click(object sender, EventArgs e)
{
var FileName = getFileName(reportPrefix);
if (fileName == null)
{
return;
}
SaveFile(fileName, QueryString);
}
选项 B:
private void btnExport_Click(object sender, EventArgs e)
{
DoExport();
}
private void DoExport()
{
var FileName = getFileName(reportPrefix);
if (fileName == null)
{
return;
}
SaveFile(fileName, QueryString);
}
我会推荐选项 B,原因如下:
关注分离:处理事件 (EventHandler) 或委托的代码与 分离完成实际工作并封装在另一个方法中的实际实现逻辑。
方法
DoExport
的意图从它的名字就很清楚了。如果有人阅读你的代码,它会被解释为选项B: "When button is clicked Do export."
选项 A: "单击按钮时读取文件名,如果文件名是 清空然后 return,否则保存文件。"哪个听起来更容易阅读?出于可读性目的,选项 B 提供了一种清晰简洁的方式来表达您的意图。
如果您决定将
button
更改为另一个控件,如锚点、链接按钮、标签或任何其他控件,则无需将事件处理程序与实现细节绑定。就像DoExport
方法不应该依赖于EventArgs' or the
sender` 对象。将来,需要从代码中的其他地方调用导出功能 (
DoExport
)。然后,您可以轻松调用DoExport
方法。测试: 如果你有这个方法 public 并且你想测试它。测试方法比编写代码引发事件然后测试功能要容易得多。
都不是,但是 B 比 A 更近:
SRP(单一职责原则)建议您将业务逻辑与 UI 分开,不仅是在方法级别,而且 至少是 class 级别(命名空间 and/or 库级别分隔也可能有用)。这是因为 UI 可能会独立于导出逻辑的变化而变化。
包含 btnExport_Click
的 UI class 负责驱动 UI,向用户显示数据并将点击等用户交互路由回业务逻辑.
和另外一个class完全一样,最好后面有一个抽象,理想的是一个接口(DIP,Dependency Inversion Principle),负责导出:
public class YouUIClass
{
IExporter exporter;
private void btnExport_Click(object sender, EventArgs e)
{
var fileName = GetFileName(reportPrefix);
if (fileName == null)
{
return;
}
exporter.DoExport(fileName);
}
}
public class Exporter : IExporter
{
public void DoExport(string fileName)
{
SaveFile(fileName, queryString);
}
}
(您可能需要将一些参数,例如 filename
或 queryString
从 UI 传递到导出器方法,正如我所演示的那样,因为我假设 GetFileName
是UI).
一个巨大的优势是您可以测试驱动业务逻辑,而无需 UI 参与。然后手动测试只是检查 UI 是否将事件正确转发到后续层。
当谈到以这种方式解耦 UI 时,您可以遵循一些模式而不是自己动手,例如 MVC、MVP 和 MVVM 等模式。