设计问题:电话拨打电话号码,还是电话号码拨打电话?

时间:2008-09-16 01:41:13

标签: oop

这是我在DDD Yahoo!上发布的内容重新发布的。基。

在所有条件相同的情况下,您是否写过phone.dial(phoneNumber)或phoneNumber.dialOn(电话)?请记住可能的未来要求(除电话号码外的帐号,除电话外的计算器)。

这个选择倾向于说明信息专家,单一责任原则和Tell Do Not Ask的成语是如何相互矛盾的。

phoneNumber.dialOn(电话)支持信息专家和告诉不要问,而phone.dial(phoneNumber)支持单一责任原则。

如果您熟悉Ken Pugh在Prefactoring中的工作,那就是Spreadsheet Conundrum;你添加行或列?

13 个答案:

答案 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)

我根本没有电话号码作为一个类,因为它没有任何行为,它只是一个数据元素。