当SRP和DRY出现冲突时

我最简单的ASP.NET MVC 2控制器调用我的服务层并将视图模型映射到使用AutoMapper的实体。 一切都很美妙,没有重复的代码。

但是,当我进入具有类似行为的场景时,我无法平衡单一责任原则(SRP)与不重复自己(DRY)。 例如,可能需要添加/编辑车辆,其中一些属性/行为是共享的,而另一些则是特定车辆所特有的。

如果我努力争取真正的瘦控制器(从而履行单一责任原则),我最终会在视图和控制器中重复代码,并略有变化(标题,字段标签,字段可见性,下拉值,选择标准等)。

如果我努力争取不重复的代码,我最终会将太多的逻辑捆绑到一个控制器/视图中,并且会变得臃肿。

在控制器/视图中解决重复代码的一些方法是什么? 我不是在讨论可以分解到存储库的数据库代码。 我也不是在讨论可以分解到服务层的业务逻辑。 我正在寻找工具和/或经验法则,这将有助于我在上述场景中生成最佳解决方案。


你得到:

  • 谐音
  • 的RenderAction
  • 动作过滤器
  • 服务层和辅助类(不是HtmlHelper)
  • 模型粘合剂
  • 基地控制器
  • 依赖注入
  • 因此,您的视图可以调用类似部分的共享部分/动作,通过动作过滤器可以准备常见数据,数据库访问代码可以隐藏在智能模型联编程序中,也可以让父控制器通过特定的调整覆盖子控制器。 当然,还有很好的老服务层,在这里你只需将通用代码提取到helper / static方法中,或者更好地注入特定的实现。

    这不是什么新鲜事,同样的老花样。

    或者,也许你的控制器做了太多的工作? 这是上面的东西也有帮助的地方。 ASP.NET MVC具有非常好的工具来隐藏基础结构层代码并将其从控制器中移除。 如果它不是基础设施 - 它可能属于域层。 在那里你可以使用继承,组合和其他OOP技巧。

    具体的例子。 假设你的控制器应该以不同的方式设置一些属性。

  • 如果主要是格式化或选择要显示的属性,则可以有自己的观点来做到这一点
  • 你可以让你的实体具有虚拟方法 - 即重构代码,以将决策移至域层而不是控制器
  • 你可以使用助手的ViewDetails类来获取你的实体并根据你需要的数据获取数据。 这是一个肮脏的伎俩,但有时是有用的; 你将决定委托给另一个“战略”类
  • 您可以使用操作过滤器将此数据添加到ViewData,或调整特定的ViewData.Model类型(查找它的某个界面)。
  • 你可以有抽象控制器,在这里儿童将实现细节传递给基类构造函数,如():base(repository => repository.GetSpecificData())
  • 等等。 我实际上在适当的地方使用它们全部。


    你太担心SRP和DRY。 他们只是原则,并不总是正确的。 如果SRP和DRY使你的代码更易于维护,那么SRP和DRY都是很好的,但如果它们阻碍了它们,那么就会忽略它们。 MVC是相似的。 它在简单的小型桌面应用程序中很有用,但不适用于Web应用程序。 Web Forms对于互联网世界来说要好得多,而MVC则是从20世纪80年代开始的。


    在这些情况下,我建议您使用SRP而不是DRY。 我在这里写了一个详细的答案。

    总之,这两个规则都有助于保持代码的可维护性。 DRY是一个低抽象层次的机制,而SRP是一个高抽象层次。 通过维护应用程序,高抽象级别结构比低抽象级别更重要。

    在你的情况下,我不认为有必要放弃DRY。

    例如,可能需要添加/编辑车辆,其中一些属性/行为是共享的,而另一些则是特定车辆所特有的。

    在这种情况下,许多设计模式都可以帮助您。 您可以使用修饰器,构图等......与不同类型的车辆的建造者结合使用。

    链接地址: http://www.djcxy.com/p/3661.html

    上一篇: when SRP and DRY appear to conflict

    下一篇: How can I integrate with the Windows Action Centre maintenance?