这是我在DDD Yahoo!上发布的内容重新发布的。基。
在所有条件相同的情况下,您是否写过phone.dial(phoneNumber)或phoneNumber.dialOn(电话)?请记住可能的未来要求(除电话号码外的帐号,除电话外的计算器)。
这个选择倾向于说明信息专家,单一责任原则和Tell Do Not Ask的成语是如何相互矛盾的。
phoneNumber.dialOn(电话)支持信息专家和告诉不要问,而phone.dial(phoneNumber)支持单一责任原则。
如果您熟悉Ken Pugh在Prefactoring中的工作,那就是Spreadsheet Conundrum;你添加行或列?
答案 0 :(得分:18)
phone.dial()
,因为它是拨打电话的手机。
Actor.Verb(输入) - >输出。
答案 1 :(得分:9)
Meh - User.Dial(数字)。在给定的环境中,手机毫无意义。 SOL(大声说出来)是一种很好的方式来思考这个问题(除了成语和原则):
手机有拨号盘。他们无法拨打自己的电话。 电话号码是数字。 用户在电话拨号上拨打电话号码。
答案 2 :(得分:3)
这个问题假定了答案的背景,从而造成了一个错误的困境
在这个例子中,'电子表格难题'是一个错误的二分法:行和列是表示层,不一定是数据层。下面的评论告诉我,我误解了这个比喻,但我不这么认为 - 说'这应该是一行还是一列,哪一个更有可能改变'是迫使在问题空间上做出不必要的选择 - 它们都是同样可能改变。在这个具体的例子中,这导致为解决方案选择错误的[yes 错误的]范例。拨打电话是指旧机械设备与另一台旧机械设备连接的程度。这对现代电话来说并不是一个恰当的比喻。并假设有一个“用户”发起呼叫只是移动问题 - 虽然它以正确的方向移动,即远离旋转式电话型号; - )如果你看看TAPI如何[对于早先的错误,这是TAPI而不是ATAPI!]协议工作,有一个呼叫控制器 - 相当于我认为在某种意义上的'用户' - 管理设备之间的连接。一个设备不会呼叫另一个设备,呼叫控制器连接设备。所以下面的例子仍然是基本正确的。使用CallController对象而不是通用Connection可能更正确,但类比应该足够清晰。
在此示例中,电话是具有地址(即“电话号码”)的设备。 'dial'运算符在两个设备之间建立连接。所以答案是:
Phone p1 = new Phone(phoneNumber1);
Phone p2 = new Phone(phoneNumber2);
Connection conn = new Connection(p1,p2);
conn.Open();
//...talk
conn.Close();
这也将支持多方通话,方法是重载Connection以包含设备列表或其他连接,例如
Connection confCall = new Connection(p1,p2,p3,p4,p5,p6);
confCall.Open();
Connection joinCall = new Connection(confCall,p7,p8,conn);
joinCall.Open();
查看TAPI协议了解更多示例
答案 3 :(得分:1)
如果您的写作OO然后您从基本对象开始,这不是数字,那么数字将进入手机,所以phone.dial()就这样你也可以通过phone.answer()phone.disconnect() phone.powerOFF,ect。
另一种看待它的方法是电话是拨打电话号码还是号码拨打电话?
答案 4 :(得分:1)
显然,phone.Dial(号码)
答案 5 :(得分:1)
显然,您可以从PhoneUserFactory.CreatePhoneUser()方法获得实现的PhoneUserInterface接口具有可用于拨打电话的方法拨号(电话号码)。
编辑:回答评论。都不是。手机应该有一个buttonPressed()或类似的东西。用户通过该界面输入电话号码的数字/字符。
答案 6 :(得分:1)
都不是。用户拨打电话上的电话号码。
答案 7 :(得分:1)
答:phone.dial(phone_number)
PhoneNumber很笨,只是一个数据集。当“拨号”发生时,PhoneNumber对象应该知道如何拨号吗?有许多州需要跟踪,例如:
如果您的PhoneNumber对象需要知道所有这些,那么它就不是DRY而且您的代码会更少 便携式,更容易破裂。
我会说Steven A. Lowe让它失望了。这应该由一个Controller类型的对象来完成,以处理不同的状态等。保持你的PhoneNumber对象愚蠢,并给那些需要担心让手机保持嗡嗡声的中间人智能。
答案 8 :(得分:1)
选择是否为列对象或行对象提供拨号方法不会改变程序的缩放方式。
拨号方法本身就是一系列行和列方法。你必须问这些方法依赖的是什么。
如果行方法的顺序不依赖于确切地知道涉及哪个列对象(但是取决于涉及哪个特定的行对象),而反之亦然用于列方法的序列,那么问题就像m + n那样(m = num.naving,n = num.cops)。创建新行时,如果已为列方法分配了“拨号”方法,则实际上不会保存任何工作。你仍然需要指定一个独特的行方法序列,以便在某个地方使用'dial'!
但是,如果说'dial'中的列方法序列甚至不依赖于涉及哪个列对象(它们使用一个'通用'列方法序列),那么问题只是缩放为m。如果你已经将“拨号”方法分配给列对象,那么程序仍然可以缩放为m;在添加1个列对象时,基本上不需要做任何工作来制作新的拨号方法,并且您可以选择将所有这些拨号方法本身抽象为一个通用拨号方法。
答案 9 :(得分:0)
这里不是负面的,但这些问题非常具有学术性。这完全取决于应用程序。无论哪种方式,我都能想到这样做的非常好的理由,而且我看到太多优秀的程序员陷入了这种模拟设计细节中。
答案 10 :(得分:0)
我不确定这与电子表格难题有什么关系。您是否希望将来使用电话拨打帐号?在计算器上使用电话号码?你的“未来需求准备”的例子并不是很好......
另外,您使用动词“dial”。当然,我可以想象在手机上“拨打”一个帐号。 (但这是一个很大的延伸。)但是如果要在计算器上使用这个电话号码,你会把这个动作称为“拨号”吗?如果函数的名称根据传递的参数类型而改变,则会出现设计错误。
在典型的OO设计中,对象会收到包含数据的消息,而不是相反。
答案 11 :(得分:0)
phone.dial()+1。
PhoneNumber的变体状态或行为是什么?唯一想到的是“拨号规则”(如果在外面拨打国家代码,拨打“9”以获得外线等)。这种情况似乎非常适合电话。
如果你的对象模型不需要方差 - 一个数字只是一个数字序列,“dial”就是foreach(数字在phonenumber中){press(digit);我和Rob Conery在一起:meh。
答案 12 :(得分:0)
我根本没有电话号码作为一个类,因为它没有任何行为,它只是一个数据元素。