Answers:
单一责任原则是关于您的代码仅做一件事情,您可以将所有功能拆分为几个类,所有这些类都旨在做一件特定的事情。一个示例是用于验证,执行一些业务逻辑,丰富模型,检索数据,更新数据,导航等的特定类。
关注点分离是关于您的代码没有与其他某些类/系统紧密耦合。在代码中使用接口有很大帮助,这样您就可以将类/系统轻松地耦合到代码中。另外一个好处是,对代码进行单元测试也更加容易。有很多(IoC)框架可以帮助您实现这一目标,但是您当然也可以自己实现。
SoC但不具有SRP的示例
public class Foo
{
private readonly IValidator _validator;
private readonly IDataRetriever _dataRetriever;
public Foo(IValidator validator, IDataRetriever dataRetriever)
{
_validator = validator;
_dataRetriever = dataRetriever;
}
public NavigationObject GetDataAndNavigateSomewhereIfValid()
{
var data = _dataRetriever.GetAllData();
if(_validator.IsAllDataValid(data))
{
object b = null;
foreach (var item in data.Items)
{
b = DoSomeFancyCalculations(item);
}
if(_validator.IsBusinessDataValid(b))
{
return ValidBusinessLogic();
}
}
return InvalidItems();
}
private object DoSomeFancyCalculations(object item)
{
return new object();
}
private NavigationObject ValidBusinessLogic()
{
return new NavigationObject();
}
private NavigationObject InvalidItems()
{
return new NavigationObject();
}
}
如您所见,此代码并未与类或其他系统紧密耦合,因为它仅使用某些接口来完成工作。从SoC的角度来看,这很好。
如您所见,该类还包含3个私有方法,它们可以做一些花哨的事情。从SRP的角度来看,这些方法可能应该放在它们自己的某些类中。他们中的2个人做了一些导航,这将适合某些INavigation类。另一个对项目进行了一些复杂的计算,这很可能放在IBusinessLogic类中。
有了这样的东西,你们都拥有SoC和SRP:
public class Foo
{
private readonly IValidator _validator;
private readonly IDataRetriever _dataRetriever;
private readonly IBusinessLogic _businessLogic;
private readonly INavigation _navigation;
public Foo(IValidator validator, IDataRetriever dataRetriever, IBusinessLogic businessLogic, INavigation navigation)
{
_validator = validator;
_dataRetriever = dataRetriever;
_businessLogic = businessLogic;
_navigation = navigation;
}
public NavigationObject GetDataAndNavigateSomewhereIfValid()
{
var data = _dataRetriever.GetAllData();
if(_validator.IsAllDataValid(data))
{
object b = null;
foreach (var item in data.Items)
{
b = _businessLogic.DoSomeFancyCalculations(item);
}
if(_validator.IsBusinessDataValid(b))
{
return _navigation.ValidBusinessLogic();
}
}
return _navigation.InvalidItems();
}
}
当然,您可以辩论是否应将所有这些逻辑都放在GetDataAndNavigateSomewhereIfValid
方法中。这是您应该自己决定的事情。在我看来,这种方法正在做太多事情。
至于仅在课堂上应用的SRP,罗伯特·C·马丁(Robert C. Martin)(据我所知,如果没有提出这个概念,他就会普及)指出:
清除代码页。138:“单一职责原则(SRP)规定,一个类或模块应该有一个并且只有一个改变的理由。”
在C#中的敏捷原理,模式和实践中,第116页:“将内聚力与导致模块或类改变的力相关联。”
强调我的。
在APPP中,他更广泛地讨论了SRP,几乎完全集中在课堂上。尽管他似乎确实专注于类级别,但我认为该原则也针对模块和其他更高级别的构造。
因此,我不会像您在问题中所建议的那样将SRP评为SoC类。
在这里您可以找到一个简短的视频,清楚地解释了这些术语之间的区别。https://www.youtube.com/watch?v=C7hkrV1oaSY
关注点分离(SoC)。将您的应用程序划分为不同的功能,并尽可能减少功能重叠。(微软)。
“关注” =“明显特征” =“明显部分”
“关注”在高低两方面都起作用
单一责任原则指出,每个模块或类都应对软件提供的功能的一部分负责,而责任应由类完全封装。它的所有服务都应严格地与这一责任保持一致。(维基百科定义)
“责任” =“改变的理由”
改变什么?“软件提供的功能的一部分” = 基本单元
结论
单一责任原则适用于基本单位->低级适用
关注点分离在高水平和低水平上均有效
SRP和SoC协同工作以分离关注点。它们在低级时完全相同
这是我对这些原则的理解。
关注点分离(SoC) —是将软件系统划分为较小的模块,这些模块上的每个模块负责一个关注点。在这种情况下,关注点是软件系统的功能或用例。模块具有定义明确的API(接口),从而使整个系统具有高度的凝聚力。有两种主要类型:水平和垂直。
单一职责原则(SRP) –是一种设计原则,指出系统的每个构建块(可以是类,模块,对象甚至功能)都应仅具有单一职责。罗伯特·马丁 马丁将责任描述为改变的原因。通常,最好由一个类/对象来负责功能的单个部分,而不是能够执行很多(有时甚至是不相关的)功能,从而使此类更大且紧密耦合,因此,被称为“上帝的对象”。
我还在博客文章中更详细地描述了这些原理,请看一看。
https://crosp.net/blog/software-architecture/srp-soc-android-settings-example/