有时很容易将整个逻辑写入程序模式而不是使用 SOLID
我完全同意,对于我们程序员来说,以过程模式处理代码更容易。这使得 OOP 对于习惯于过程式编程的程序员来说很难。
然而,我发现首先编写通用接口和消费者比打破为较小模块设计的接口更容易。这是,一种Test First Development -> Red, green, refactor
修行。(请注意,如果您想实现neat design
,请考虑遵循 TDD 而不是本指南。本指南只是做 TDD 的一小部分)
假设我们要创建ServiceAttendance
to do scanEmployeeID
。我们将有一个类似的接口(请注意该示例以 C# 命名):
public interface IServiceAttendance{
bool ScanEmployeeId();
}
请注意,我决定返回 bool 而不是 void 来确定成功/失败操作的方法。请注意下面的消费者示例没有实现任何 DI,因为我只是想展示如何使用它。然后在消费者中,我们可以有:
public void ConsumeServiceAttendance(){
IServiceAttendance attendance = Resolve<IServiceAttendance>();
if(attendance.ScanEmployeeId()){
// do something
}
}
消费者到此结束。现在我们开始执行。假设您可以使用过程编程开发它并获得整体代码块。您可以使用类似 pseu 的语句来说明实现。
public class ServiceAttendance : IServiceAttendance{
public bool ScanEmployeeId(){
bool isEmpValid = false;
// 1 scan the employee id
// 2 validate the login
// 3 if valid, create the login session
// 4 notify the user
return isEmpValid;
}
}
现在我们在这一操作中有 4 个步骤要完成。我的原则是,不要在一种方法中完成超过 3 个外观过程,因此我可以简单地将 3 和 4 重构为一个过程。现在我们有
public class ServiceAttendance : IServiceAttendance{
public bool ScanEmployeeId(){
bool isEmpValid = false;
// 1 scan the employee id
// 2 validate the login
// 3 if valid, create the login session and notify the user
return isEmpValid;
}
}
这个,我们有3个主要操作。我们可以通过分解操作来分析是否需要创建更小的模块。假设我们要中断第二个操作。我们可以得到:
// 2 validate the login
// 2.1 check if employee id matches the format policy
// 2.2 check if employee id exists in repository
// 2.3 check if employee id valid to access the module
分解操作本身很明显,足以将第二个模块分解成另一个更小的模块。对于2.2
和2.3
,我们需要注入一个更小的模块。仅仅因为它需要对存储库的依赖,因此需要注入。同样的情况也适用于操作步骤1 scan the employee id
,因为它需要依赖指纹扫描仪,所以扫描仪处理程序必须在单独的模块中实现。
我们总是可以分解操作,因为我们可以这样做2.1
:
// 2.1 check if employee id matches the format policy
// 2.1.1 employee id must match the length
// 2.1.2 employee id must has format emp#####
现在我不确定是否2.1.1
并且2.1.2
需要将其分解为 2 个独立的模块,由您决定。现在我们有了接口,然后我们就可以开始实现了。期望exceptions
在验证期间抛出,否则您将需要传递自定义类来处理错误消息。