2009-07-16 77 views
3

我有关于使用函数参数的问题。函数参数最佳实践

在过去,我总是写我的代码,以便函数所需的所有信息都作为参数传入。即全局参数不被使用。

但是,通过查看其他人的代码,没有参数的函数似乎是常态。我应该注意到这些是为了一个类的私有函数,并且作为参数传入的值实际上是该类的私有成员变量。

这导致整洁的代码,我开始倾向于私人功能,但希望其他人的看法。

E.g.

Start(); 
Process(); 
Stop(); 

比更整洁并且更可读:

ParamD = Start(paramA, ParamB, ParamC); 
Process(ParamA, ParamD); 
Stop(ParamC); 

它从一个方法点从一个点类破坏封装但不是。

回答

1

在它是常见的依赖关系(即这个类将与通信的类)和配置值在构造和唯一的值,以传递一个面向对象的语言,以实际上在函数调用被操作。

这实际上可以更具可读性。考虑代码,你有一个生成和发布发票的服务。可以有多种方式来进行发布 - 通过将它发送到某种集中式服务器的Web服务,或者通过发送给仓库中某个人的电子邮件,或者也可以将其发送到默认打印机。但是,调用Publish()的方法通常不会知道发布的具体细节 - 它只需要知道发布顺利完成即可。这样可以让您一次只想较少的事情,并更好地专注于问题。然后你只需利用一个接口来服务(在C#):

// Notice the consuming class needs only know what it does, not how it does it 
public interface IInvoicePublisher { 
    pubic void Publish(Invoice anInvoice); 
} 

这可以通过多种方式来实现,例如:

public class DefaultPrinterInvoicePublisher 
    DefaultPrinterInvoicePublisher _printer; 
    public DefaultPrinterInvoicePublisher(DefaultPrinterFacade printer) { 
    _printer = printer 
    } 
    public void Publish(Invoice anInvoice) { 
    printableObject = //Generate crystal report, or something else that can be printed 
    _printer.Print(printableObject); 
    } 

使用它会代码那么还需要一个IInvoicePublisher作为构造函数参数,以便可以在整个过程中使用该功能。

4

正如你所说,他们之间有一个权衡。总是宁愿选择另一个,也没有硬性规定。尽量减少变量的范围将使其副作用保持在本地,代码更加模块化,可重用,调试更容易。但是,在某些情况下,这可能是一种矫枉过正的行为。如果你保持你的课程小(你应该这样做),那么共享变量通常是有意义的。但是,还可能存在其他问题,例如可能影响您选择的线程安全性。

1

通常,最好使用参数。大大提高了使用依赖注入和测试驱动设计等模式的能力。

但是,如果它是内部唯一的方法,那并不重要。

2

不将对象自己的成员属性作为参数传递给它的方法是正常实践:有效地当你调用myobject.someMethod()时,你隐式地将整个对象(及其所有属性)作为参数传递给方法代码。

+0

该OP主要是谈论私人的东西。有一种常见的替代方法是对某些属性执行操作的“静态”实用程序方法。在这些情况下,对象引用是**不自动传递。 – 2009-07-16 12:39:38

1

我普遍同意Mehrdad和Mufasa的评论。对于什么是最好的,没有硬性规定。您应该使用适合你铭记工作的具体情景的办法:

  • 的代码的可读性
  • 清洁的代码(如果你通过一百万和一个参数到一个方法会导致混乱 - 特别是如果它们是类级别的变量,也可以将参数封装到组中,并在一个对象中创建一个结构为整个多个值)
  • 代码的可测试性。这在我看来很重要。我曾偶尔重构代码参数纯粹添加一种用于提高可测性的目的,因为它可以实现更好的单元测试
2

这是你需要衡量的情况下,一些逐案。

例如问问你自己,如果你要在私有方法中使用参数是否合理地传递一个值,该值是对象中特定属性以外的值?如果不是,那么你可以直接在方法中访问属性/字段。

你也许会问自己这个方法是否会改变对象的状态?如果不是,那么它可能会更好,作为一个静态和所有需要的值作为参数传递。

有各种各样的考虑,最重要的是“其他开发者最容易理解的东西”。

0

我不会将对象的状态传递给私有方法,因为方法可以像这样访问状态。

当从公共方法调用私有方法时,我将参数传递给一个私有方法,然后公共方法获取它随后发送给私有方法的参数。

Public DoTask(string jobid, object T) 
{ 
DoTask1(jobid, t); 
DoTask2(jobid, t); 
} 

private DoTask1(string jobid, object T) 
{ 
} 

private DoTask2(string jobid, object T) 
{ 
} 
6

从原理上讲,函数访问对象字段没有什么问题,但是您给出的具体示例让我感到害怕,因为简化函数调用的代价是您混淆了数据的生命周期。

若要翻译ARGS例如成田,你会碰到这样的:

void Start() { 
    // read FieldA, FieldB, and FieldC 
    // set the value of FieldD 
} 

void Process() { 
    // read FieldA and do something 
    // read FieldD and do something 
} 

void Stop() { 
    // read the value of FieldC 
} 

Start()FieldD的副作用。这意味着在拨打Start()之前拨打Process()可能无效。但代码并没有告诉你。您只能通过搜索查看FieldD的初始化位置。这是要求错误。

我的经验法则是,函数只能访问一个对象字段,如果它是总是安全地访问该字段。最好的是,如果它是一个在构建时初始化的字段,但是存储对合作者对象或其他内容的引用的字段也可以随时间变化。

但是,如果在另一个函数产生了一些输出之后调用一个函数是无效的,则该输出应该被传入,而不是存储在状态中。如果您将每个函数视为独立函数,并避免副作用,那么您的代码将更易于维护并更易于理解。

+1

嘿,对于如何在共享字段和参数之间做出决定,这是一个非常好的建议。我总是有点用我的直觉 - 不得不以这种方式开始思考。谢谢。 – 2013-02-12 21:36:50