在最近的一次工作面试中,除了提供各种原理的基本含义之外,我无法回答有关SOLID的问题。这真的让我很烦。我做了几天值得深入研究的工作,但还没有得出令人满意的总结。
面试问题是:
如果您要看一个我严格遵循SOLID原则的.Net项目,那么您期望在项目和代码结构方面看到什么?
我挣扎了一下,没有真正回答问题,然后轰炸了。
我如何更好地处理这个问题?
在最近的一次工作面试中,除了提供各种原理的基本含义之外,我无法回答有关SOLID的问题。这真的让我很烦。我做了几天值得深入研究的工作,但还没有得出令人满意的总结。
面试问题是:
如果您要看一个我严格遵循SOLID原则的.Net项目,那么您期望在项目和代码结构方面看到什么?
我挣扎了一下,没有真正回答问题,然后轰炸了。
我如何更好地处理这个问题?
Answers:
S =单一责任原则
因此,我希望看到一个组织良好的文件夹/文件结构和对象层次结构。每个功能类/每个部分都应命名为其功能非常明显,并且应仅包含执行该任务的逻辑。
如果您看到包含成千上万行代码的大型经理类,则表明没有遵循单一职责。
O =开/关原理
这基本上是一个想法,即应通过对现有功能影响最小/需要修改的新类添加新功能。
我希望看到大量使用对象继承,子类型,接口和抽象类来将功能设计与实际实现分离开来,从而允许其他人一起实现其他版本而不影响其功能。原版的。
L = Liskov替代原理
这与将子类型视为其父类型的能力有关。如果要实现适当的继承对象层次结构,这在C#中是现成的。
我希望看到将普通对象视为其基本类型的代码,并在基类/抽象类上调用方法,而不是实例化和处理子类型本身。
I =接口隔离原理
这类似于SRP。基本上,您将较小的功能子集定义为接口,并与这些子集一起使用,以使系统保持解耦状态(例如,a FileManager
可能具有处理文件I / O的单一职责,但是可以实现IFileReader
,IFileWriter
并且包含用于读取的特定方法定义)和文件写入)。
D =依赖反转原理。
同样,这涉及保持系统解耦。也许您会注意使用.NET依赖注入库,并将其用于解决方案中,例如Unity
或Ninject
或ServiceLocator系统,例如AutoFacServiceLocator
。
许多小类和接口到处都有依赖项注入。可能在大型项目中,您还将使用IoC框架来帮助您构造和管理所有这些小对象的生存期。参见https://stackoverflow.com/questions/21288/which-net-dependency-injection-frameworks-are-worth-look-into
请注意,一个严格遵循SOLID原则的大型.NET项目不一定意味着每个人都可以使用良好的代码库。根据面试官的身份,他/她可能希望您表明您了解SOLID的含义和/或检查您如何遵循设计原则。
您要成为SOLID,需要遵循以下步骤:
小号英格尔责任原则,让你将有很多小班他们每个人做一两件事只
O型封闭原则,在.NET中通常通过依赖项注入来实现,这也需要下面的I和D ...
使用 isliner在c#中解释L iskov替换原理可能是不可能的。幸运的是,还有其他问题可以解决,例如https://stackoverflow.com/questions/4428725/can-you-explain-liskov-substitution-principle-with-a-good-c-sharp-example
我覆盖整个院落隔离原则工作亦随开闭原则。如果按字面意思执行,那就意味着倾向于使用大量非常小的接口,而不是少数几个“较大”的接口
D倾向反转原理高级类不应依赖于低级类,而两者都应依赖于抽象。
我希望在一家商店的代码库中看到一些基本的东西,这些东西在日常工作中特别重视SOLID:
大量的Adapter和Composite模式-我期望使用大量的Adapter模式(通过“传递”到另一个接口的功能来实现一个接口的类)可以简化为一个目的而开发的依赖项的插入在不同地方也需要其功能。如果接口被更新以提供一种指定使用文件名的方式,那么像用文件记录器替换控制台记录器这样简单的更新将违反LSP / ISP / DIP。取而代之的是,文件记录器类将公开其他成员,然后适配器通过隐藏新内容使文件记录器看起来像控制台记录器,因此只有将所有这些都捕捉到的对象才需要知道它们之间的区别。
类似地,当一个类需要添加与现有接口相似的依赖关系时,为了避免更改对象(OCP),通常的答案是实现Composite / Strategy模式(一个类实现了依赖关系接口并使用了多个其他接口接口的实现,逻辑量的变化允许类将调用传递给一个,一些或所有实现。
乔恩·斯凯特(Jon Skeet)对 SOLID中的“ O”如何“无助且理解不清” 的讨论分散了他们的注意力,让他们谈论阿利斯泰尔·考克本(Alistair Cockburn)的“受保护的变体”和乔什·布洛赫(Josh Bloch)的“继承设计,或禁止继承”。
Skeet文章的简短摘要(尽管我不建议您在不阅读原始博客文章的情况下就删除他的名字!):
OP问:“我如何更好地解决这个问题?” 作为一名进行面试的高级工程师,我对候选人能够产生聪明的想法谈论各种代码设计风格的利弊比对那些能够从项目符号要点中脱颖而出的人更加感兴趣。
另一个很好的答案是:“嗯,这取决于他们对它的理解程度。如果他们所知道的只是SOLID流行语,我希望滥用继承,过度使用依赖项注入框架,一百万个小型接口都不是。反映用于与产品管理进行沟通的领域词汇。”
可能有很多方法可以在不同的时间量内回答。但是,我认为这更像是“您知道SOLID意味着什么吗?”。因此,回答这个问题可能只是归结为要点并按照项目进行解释。
因此,您希望看到以下内容:
这是一个很好的问题,尽管我认为这是一个艰难的面试问题。
SOLID原则确实支配着类和接口以及它们之间的相互关系。
这个问题实际上与文件而不是类有关。
我要给出的简短观察或答案是,通常您会看到仅包含接口的文件,并且通常约定是它们以大写字母I开头。除此之外,我还要提到文件中没有重复的代码(尤其是在模块,应用程序或库中),并且代码将在模块,应用程序或库之间的特定边界之间谨慎共享。
Robert Martin在使用Booch方法设计面向对象的C ++应用程序的C ++领域(请参阅有关内聚性,封闭性和可重用性的部分)和“ 干净代码”中讨论了这个主题。