Design patterns 软件设计:DI-多个组件+;非公共类型

Design patterns 软件设计:DI-多个组件+;非公共类型,design-patterns,dependency-injection,architecture,inversion-of-control,software-design,Design Patterns,Dependency Injection,Architecture,Inversion Of Control,Software Design,我在这里的第一篇帖子大家好:) 我使用阶梯模式,例如,我有程序集A(入口点-合成根),它依赖于程序集B(包含接口),程序集C包含程序集B中定义的接口的实现: A-->B注册非公共类型)。我发现它很有用,因为我可以将程序集C中的类定义为内部类,这意味着没有人会从A创建对C的直接依赖。这样,A和C都只依赖于程序集B,它只包含我认为正确的抽象 我想知道这是否是一个好的设计选择。据我所知,只有Windsor允许注册非公共类型,并且它们还警告不要公开非公共类型,因此我的问题是。另外,我不认为这些考虑仅限于

我在这里的第一篇帖子大家好:)

我使用阶梯模式,例如,我有程序集A(入口点-合成根),它依赖于程序集B(包含接口),程序集C包含程序集B中定义的接口的实现:

A-->B注册非公共类型)。我发现它很有用,因为我可以将程序集C中的类定义为内部类,这意味着没有人会从A创建对C的直接依赖。这样,A和C都只依赖于程序集B,它只包含我认为正确的抽象


我想知道这是否是一个好的设计选择。据我所知,只有Windsor允许注册非公共类型,并且它们还警告不要公开非公共类型,因此我的问题是。另外,我不认为这些考虑仅限于.NET world,因此无论您使用何种技术,我都希望能够深入了解这个问题:)

是否有任何理由阻止C类从外部访问?只有当您让第三方使用此程序集(即,您将其发布为NuGet软件包供其他人使用)时,这才有意义。如果此库的唯一使用者在您自己的团队中,那么隐藏内部内容只会使事情变得复杂,因为:

  • 测试变得更加困难,因为您必须使用[InternalsVisibleTo]标记内容
  • 合成变得更加困难,因为您可以直接从合成根中引用组件。当您逐个注册它们时,需要直接引用它们,这有时是必需的,或者您希望手动更新它们,而不是让它们通过容器自动连接
  • 由于组合根(程序集A)是唯一依赖于程序集B的程序集,因此基本上只对组合根隐藏依赖项,这没有什么意义,因为根据定义,组合根位于应用程序中

另一方面,从可重用库的角度来看,将类内部化非常有意义。看看.NET框架本身,以及它有多少是内部的。将stuff设置为内部使更改stuff变得更容易,而不会引入中断更改。

我对Autofac做了同样的操作,在每个具有内部类型的程序集中使用模块。主(入口)程序集只知道它需要注册的模块(例如:电子邮件模块等)。将实现保持在C内部的主要原因是强制A依赖于B的抽象,避免任何人引入对C的实现的依赖,假设我在C中有10个类,其中一半提取了接口(C的内部接口)以便于测试——我不希望这些类暴露于to:1。避免在C2上引入不必要的A依赖项。避免用手接线。因此,C中的所有类和接口都是内部的,温莎使用includeNoPublicTypes选项自动连接。直到有人添加InternalsVisibleTo属性,所有内容都可以再次访问。尝试使用NsCop之类的工具来管理命名空间依赖关系,或者编写一个单元测试来防止从一个程序集到另一个程序集的依赖关系。此外,如果没有代码审查和与开发人员就您为什么有这样的规则进行适当的沟通,那么这些规则就会失败。由于时间压力和康威定律,体系结构规则将被打破。虽然我发现代码审查非常宝贵,但我认为在更大的团队中这是不够的,所以当我可以的时候,我宁愿尽可能多地执行。但这样处理(使类成为内部的)可能是错误的方法,我更愿意沿着通过自动化测试路径强制执行的体系结构规则走下去?一般来说,我最初的问题是,在汇编C中创建类并依靠DI自动解决依赖关系是否是一种设计气味?@PrivateVoid:不,我认为称之为设计气味太刺耳了。如果您希望尽可能多地强制执行,请查看像NDepend这样的工具,因为有很多是您无法在代码中强制执行的(开发人员将以任何方式绕过您的障碍)。像NDepend这样的工具允许您在(类似查询的)DSL中指定体系结构规则,这非常强大。非常感谢您的回复Steven,我非常感谢您的见解:)