该得墨忒耳定律指出你应该只给你关于直接了解对象说话.也就是说,不要执行方法链接与其他对象交谈.当您这样做时,您正在与中间对象建立不正确的链接,不恰当地将您的代码与其他代码耦合.
那很糟.
解决方案是针对您所知道的类,基本上公开简单的包装器,将责任委托给与其有关系的对象.
非常好.
但是,这似乎导致班级具有低凝聚力.它不再只是简单地对其所做的事情负责,但它也有代表在某种意义上,通过复制其相关对象的部分界面使代码更具凝聚力.
那很糟.
它真的会降低凝聚力吗?它是两个邪恶中的较小者吗?
这是发展的灰色区域之一,您可以在哪里讨论线路的位置,或者是否有强有力的,有原则的方式来决定在哪里划线,以及您可以使用哪些标准来做出决定?
我和一位同事为我们的客户设计了一个系统,我们认为我们创造了一个漂亮干净的设计.但是我遇到了一些我们引入的耦合问题.我可以尝试创建一个包含与我们的设计相同的问题的示例设计,但如果您原谅我,我将创建一个设计摘录来支持这个问题.
我们正在开发一种为患者注册某些治疗方案的系统.为了避免链接到图像,我将概念性UML类图描述为ac#样式类定义.
class Discipline {}
class ProtocolKind
{
Discipline;
}
class Protocol
{
ProtocolKind;
ProtocolMedication; //1..*
}
class ProtocolMedication
{
Medicine;
}
class Medicine
{
AdministrationRoute;
}
class AdministrationRoute {}
Run Code Online (Sandbox Code Playgroud)
我将尝试解释一下设计,协议是新治疗的模板.并且协议属于某种类型并且具有需要施用的药物.根据协议,对于相同的药物(以及其他事物),剂量可以不同,因此存储在ProtocolMedication类中.AdministrationRoute是药物的管理方式,与协议管理分开创建/更新.
我发现以下地方违反了得墨忒耳法则:
例如,在ProtocolMedication的业务逻辑中,存在依赖于药物的AdministrationRoute.Soluble属性的规则.代码将成为
if (!Medicine.AdministrationRoute.Soluble)
{
//validate constrains on fields
}
Run Code Online (Sandbox Code Playgroud)
列出某个学科中所有协议的方法将写成:
public IQueryable<Protocol> ListQueryable(Discipline discipline)
{
return ListQueryable().Where(p => (p.Kind.Discipline.Id == discipline.Id)); // Entity Frameworks needs you to compare the Id...
}
Run Code Online (Sandbox Code Playgroud)
我们使用ASP.NET(没有MVC)作为我们系统的接口,在我看来这个层目前有最严重的违规行为.gridview的数据绑定(必须显示协议的Discipline的列必须绑定到Kind.Discipline.Name),这是字符串,因此没有编译时错误.
<asp:TemplateField HeaderText="Discipline" SortExpression="Kind.Discipline.Name">
<ItemTemplate>
<%# Eval("Kind.Discipline.Name")%>
</ItemTemplate>
</asp:TemplateField>
Run Code Online (Sandbox Code Playgroud)
所以我认为实际的问题可能是,什么时候可以将其视为Demeter的建议,以及可以采取哪些措施来解决违反Demeter法的问题?
我对自己有一些想法,但我会将它们作为答案发布,以便他们可以单独评论和投票.(我不确定这是不是这样做的方法,如果没有,我会删除我的答案并将其添加到问题中).
谁能告诉我什么是凝聚力和解耦?我找到了耦合,但在任何地方都没有去耦.我需要了解它们的含义.
任何帮助将不胜感激.感谢回复.
将渲染代码与实际游戏引擎/逻辑代码分开的最佳方法是什么?将它们分开是一个好主意吗?
假设我们有一个名为Knight的游戏对象.必须在屏幕上呈现骑士以供用户查看.我们现在有两个选择.要么我们给Knight一个Render/Draw我们可以调用的方法,要么我们创建一个渲染所有骑士的渲染器类.
在两者分开的场景中,骑士应该还包含渲染他所需的所有信息,还是应该将它分开呢?
在我们创建的最后一个项目中,我们决定让渲染对象所需的所有信息都存储在对象本身中,但是我们有一个单独的组件来实际读取该信息并渲染对象.该对象将包含诸如大小,旋转,缩放以及当前正在播放的动画等信息,并且基于此,渲染器对象将构成屏幕.
像XNA这样的框架似乎认为加入对象和渲染是一个好主意,但是我们害怕被绑定到特定的渲染框架,而构建单独的渲染组件使我们可以在任何给定时间更自由地更改框架.
班级名称已被更改以保护无辜者.
如果我有一个名为ISomeInterface的接口.我还有继承接口的类,FirstClass和SecondClass.FirstClass使用必须处理的资源.SecondClass没有.
所以问题是,我应该从IDisposable继承哪里?以下两个选项似乎都不太理想:
1)使FirstClass继承IDisposable.然后,任何处理ISomeInterfaces的代码都必须知道是否要处理它们.这闻起来像是与我紧密耦合.
2)使ISomeInterface继承IDisposable.然后,任何从它继承的类都必须实现IDisposable,即使没有任何东西可以处理.除了注释之外,Dispose方法基本上是空白的.
#2对我来说似乎是正确的选择,但我想知道是否有其他选择.
我有一个模型,需要从辅助源加载外部数据.我的模型可以从(可交换)中获取数据的许多Web服务,但我不想创建难以更改服务的代码(成本因变量和固定使用而显着不同而且可能会发生变化将被要求).
我想创建一个驱动程序来执行交互(如果服务需要切换,则创建更多自定义驱动程序).不幸的是,由于驱动程序和模型的紧密耦合,将代码提取到插件或gem中是没有意义的.我已将所有代码解压缩到一个模块中(参见示例),并且当前在我的模型上面声明了代码.
module Synchronize
def refresh
self.attributes = ...
self.save
end
end
class Data < ActiveRecord::Base
include Synchronize
end
Run Code Online (Sandbox Code Playgroud)
Rails(3.0.0)是否有一个约定存储与模型紧密耦合的模块?我应该使用插件来执行此操作吗?这与'app/helpers'目录有关吗?如果没有,最适合存储代码的地方在哪里?谢谢!
我正在阅读Steve McConell的Code Complete,我正在考虑他在松散耦合的一节中给出的一个例子.它是关于计算员工假期数量的方法的界面,该方法是根据员工的入职日期及其销售额计算得出的.作者建议将输入日期和销售作为方法的参数而不是雇员的实例:
int holidays(Date entryDate, Number sales)
Run Code Online (Sandbox Code Playgroud)
代替
int holidays(Employee emp)
Run Code Online (Sandbox Code Playgroud)
这个论点是,这解耦了方法的客户端,因为它不需要知道关于Employee类的任何信息.
我想到了两件事:
提供计算所需的所有参数会破坏封装.它显示了该方法的内部结构如何计算结果.
更改更难,例如当有人决定员工的年龄也应该包含在计算中时.人们必须改变签名.
你怎么看?
我坚信后端和前端之间紧密耦合的异端思想:我希望在生成用户界面时自动使用有关后端的现有隐含知识.例如,如果VARCHAR列的最大值为20个字符,则GUI应自动约束用户在相关表单字段中键入超过20个字符.
我对想要定义我的数据库表的ORM有强烈的反感,或者基于某些hack,因为ORM,每个表都需要有额外的数字ID列.
我已经看了一下Python数据库框架,我想我可以断定SQLAlchemy最适合我的心态.
现在,我需要找到一个自然适合SQLAlchemy(或同等版本)的Web应用程序框架,甚至可能还有我对耦合的兴趣.使用"Web应用程序框架",我的意思是产品/项目,如Pyhons,Django,TurboGears,web2py等.
例如,它理想情况下应该能够:
所有这些都应该动态发生,因此表调整会自动反映在前端 - 可能是使用缓存机制,因此所有模型内省都不会扼杀性能.换句话说,我不想在我的数据库中仔细定义XML文件(或类似文件)中重复我的模型定义.
是否存在Python(或任何语言)的框架?如果不是:如果我自己添加部分上述功能,那么几个Python Web应用程序框架中哪一个最不会受到影响?
编写一个定义依赖于另一个库的接口的库是不好的做法吗?
我知道紧耦合很糟糕,但是在使用.NET类时这仍然适用吗?
例如,在.NET中,如果我有一个返回Color对象的库,它将强制在使用我的库的任何东西上依赖System.Drawing.在库中创建自己的Color-type类会更好吗?
coupling ×10
oop ×3
cohesion ×2
decoupling ×2
.net ×1
c# ×1
data-driven ×1
dependencies ×1
idisposable ×1
inheritance ×1
interface ×1
libraries ×1
metadata ×1
object ×1
python ×1
refactoring ×1
ruby ×1
sql ×1