方法的参数列表应包含对象还是对象标识符?


10

我们的团队进行了以下讨论:

假设我们有以下两种方法:

public Response Withdraw(int clubId, int terminalId,int cardId, string invoice, decimal amount);

public Response Withdraw(Club club, Terminal terminal,Card card, string invoice, decimal amount);

通过有线方式发送的只是ID。

一方说第一种方法是正确的,因为我们只有终端和俱乐部的ID,并且应该清楚我们别无其他,这是我的方法。

另一边说第二种方法是正确的,因为它更灵活。

我们熟悉对象参数的想法,另一边也认为对象参数应该具有对象作为属性。

哪种方法正确?

也许还有第三种更好的方法?


什么?...........
詹姆斯

1
上下文?网络服务?WCF?
CodesInChaos

1
@James-对不起,我很快就写了这个问题,您能告诉我一些不明白的地方,以便我进行编辑吗?
Mithir

@CodesInChaos方法实际上是BL方法
Mithir

Answers:


10

答案取决于上下文。

如果希望客户端具有所有可用的对象,则可以使用对象参数。否则,他们的代码将看起来比所需的更加复杂。(例如,他们会有类似的呼叫club.getId()。)

如果客户端仅容易获得ID,则第二种方法可能更好,因为如果您确实只需要ID,则可能不希望客户端组装/加载所有这些对象。

一种选择是提供两种方法,以便客户端可以选择使用哪种方法(前提是这不会使您的API混乱)

通常,对象参数更具扩展性,因为如果将来您需要另一段数据来完成工作,则无需引入采用该额外信息的另一种方法。

最后,您的方法签名不应由该方法执行的操作(在您的情况下,确切地讲是通过什么操作)的细节决定。该API应该抽象地有意义,因此,如果实现发生更改,您就不会被搞砸。


3
+1我只想再加一点:对于远程调用的方法(“通过电线”?),传递对象可能需要对广泛的对象树进行深度序列化。当您担心远程调用有效负载的大小时,ID是对象的理想替代品。
罗斯·帕特森

1
在这种情况下,您似乎已耦合到一组抽象,因此传递Id不会给您带来更大的灵活性,并且可能会增加您反转参数的可能性。问题是方法中的代码与我传递的抽象有多紧密?例如,诸如“ validateCreditCard(string card,string cvi)”之类的方法可能应该保留在原语中,以避免与某些CreditCard对象紧密耦合。
ipaul

我会在中间见面,并在参数列表中使用接口。这样,您的俱乐部可以成为俱乐部,但将来也可以成为桑拿浴室。
Pieter B

13

第一种方法表示原始痴迷。因为您要传递整数和字符串,所以程序员容易犯错误(例如,将clubId传递给terminalId参数)。这将导致难以发现错误。

在第二个示例中,当需要终端时不可能通过俱乐部-这将给您带来编译时错误。

即使这样,我仍然会看string invoice。发票真的是字符串吗?什么amount意思 这更可能是货币价值。

您在问题中提到“通过有线方式发送的只是ID。” 这是正确的,但不要让此要求使您的域变得混乱。

我所见过的最好的解释是Object Calisthenics的规则3 :

一个int本身只是一个标量,因此没有任何意义。当方法将int作为参数时,方法名称需要完成所有表达意图的工作。如果相同的方法将“小时”作为参数,则更容易了解发生了什么。这样的小对象可以使程序更易于维护,因为不可能将Year传递给采用Hour参数的方法。使用原始变量,编译器无法帮助您编写语义正确的程序。对于一个对象(甚至是一个很小的对象),您将为编译器和程序员提供有关值是什么以及为什么使用它的附加信息。


那么第二种方法是合适的吗?即使存在仅填充了id属性的club对象?
Mithir

这似乎是一个随机博客。没有证据说明什么是首选。谁真正在乎什么是首选?做对自己
James

@James对这个问题没有明确的答案,特别是因为OP没有给我们太多背景信息。任何断然宣称一种方法优于另一种方法的人都对OP造成了损害。不是那么黑白。
MattDavey 2013年

1
@James我只是指出,第一种方法很容易引入难以发现的错误。我并不是说原始类型不好,但是原始类型的目的是建立有意义的域类型。在此上下文之外使用它们是原始迷恋代码气味的定义。
MattDavey 2013年

5
@詹姆斯:马特·戴维说的是一个公认的事实。他并不是在说本机类型是不好的,而是在说:SomeMethod(int,int,int,字符串,十进制)比someMethod(Club,Terminal,Card,String)难于理解和使用。 ,十进制)
c_maker 2013年

2

这个问题没有正确的答案。两种选择都可能适合该工作。好吧,几乎任何方式,发票参数都使我的眉毛发红,我不知道从阅读代码中学到什么。

如果发送ID,则两个系统都需要紧密耦合到代表的位置。ClubID是clubs表中的键。更重要的是,主叫方和被叫方都需要同意调用Clubs表以及它在哪个数据库中。如果您不想或不能施加该约束,则可以使用一些常见的描述来传递对象,本机,序列化,xml,名称=值(任何ini文件):)

正如您所确定的那样,您将“花钱”。通过仅发送标识符来避免这种情况,您会在其他地方付出代价。因此,现在(或可能以后)对您的伤害最小。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.