是否需要按特定顺序执行的方法是私有的?

时间:2010-04-28 14:59:40

标签: c#

我有一个类可以检索一些数据,而图像会对它们执行一些操作,然后使用Web服务将它们上传到第三方应用程序。 该对象需要按顺序执行某些特定步骤。 我的问题是我是否应该像这样公开公开每种方法。

myObject obj = new myObject();
obj.RetrieveImages();
obj.RetrieveAssociatedData();
obj.LogIntoThirdPartyWebService();
obj.UploadStuffToWebService();

或者所有这些方法都应该是私有的,并且封装在一个像这样的公共方法中。

public class myObject()
{
 private void RetrieveImages(){};
 private void RetrieveAssociatedData(){};
 private void LogIntoThirdPartyWebService(){};
 private void UploadStuffToWebService(){};

 public void DoStuff()
  {
   this.RetrieveImages();
   this.RetrieveAssociatedData();
   this.LogIntoThirdPartyWebService();
   this.UploadStuffToWebService();
  }
}

就是这样称呼的。

myObject obj = new myObject();
obj.DoStuff();

15 个答案:

答案 0 :(得分:25)

这取决于谁知道应该以这种方式调用这些方法。

  • 消费者知道:例如,如果对象是Stream,则Stream的使用者通常决定何时{{1} },OpenRead流。显然,这些方法需要公开,否则对象无法正常使用。 (*)

  • 对象知道:如果对象知道方法的顺序(例如它是Close并且必须按特定顺序进行计算),那些方法应该是私有的,并通过单个更高级别的步骤公开(例如TaxForm将调用ComputeFederalTaxCalculateDeductionsAdjustGrossIncome)。

  • 如果步数超过少数,您将需要考虑DeductStateIncome,而不是将步骤直接耦合到对象中。然后你就可以改变一切,而不会过多地反对对象或它的界面。

在您的特定情况下,您的对象的消费者似乎并不关心除正在进行的处理操作之外的任何事情。由于它不需要知道这些步骤发生的顺序,因此应该只有一个名为Strategy的公共方法(或者那种效果)。


(*)但是,通常对象至少知道 order ,其中可以调用方法来防止无效状态,即使它不知道何时实际执行步骤。也就是说,对象应该足够了解以防止自己陷入无意义的状态;如果你试图在Process之前调用Close就是一个很好的例子,那么会抛出某种异常。

答案 1 :(得分:14)

如果除非首先调用A(),否则方法B()确实无法调用,那么正确的设计要求A应该返回B需要的一些对象作为参数。

这是否总是实用是另一回事,但这就是应该的完成方式。

答案 2 :(得分:4)

是私密的,否则你会打开门让用户做错事,这只会让每个人感到痛苦。

您是否需要自行调用这些方法?即,他们中的任何一个做了什么有用的,可能需要独立的?如果是这样,那么你可能希望保持那些公开,但即使你把它们全部公开,你应该有一个方法,以正确的顺序(最好是一个有用的名称)调用它们,以使你的用户更容易。

答案 3 :(得分:4)

这完全取决于操作是否基本上是原子的。在这种情况下,它对我们外人来说看起来像是一个单一的操作,但它真的吗?如果LogIntoThirdPartyWebService失败,UI是否需要提供一个对话框来询问用户是否要重试?在您只有一个操作的情况下,重试LogIntoThirdPartyWebService操作还需要重做像RetrieveImages这样可能很昂贵的操作,而将它们分开可以实现更精细的逻辑。

在这种情况下我会做的是这样的事情:

Images images = RetrieveImages();
ImagesAndData data = RetrieveAssociatedData(images);
WebService webservice = LogIntoThirdPartyWebService();
UploadStuffToWebService(data, webservice);

或者更理想的是这样的事情:

UploadStuffToWebService(RetrieveImages().RetrieveAssociatedData(),
                        LogIntoThirdPartyWebService());

现在,您在执行正确的操作顺序时具有粒度。

答案 4 :(得分:3)

对我而言,从对象的角度来看,对象做了一件事:它将图像从一个地方移动到另一个地方。作为对象的消费者,您需要采取的所有单独步骤与我无关;毕竟这就是为什么我让你为我做的。

因此,您应该使用一个DoStuff()方法来获取所有必需的参数,并将所有实现细节设为私有。

答案 5 :(得分:2)

私有 - 并在构造函数中获取参数并在那里执行命令。

不要假设来电者会按顺序打电话给他们,或者知道如何打电话给他们。

所以,不是你列出的例子,我会这样做:

MyObject myObject = new MyObject(); // make a constructor to take any parameters that are required to "setup" the object per your requirements.
myObject.UploadToWebService();

答案 6 :(得分:1)

这实际上取决于你是否估计任何人只想调用其中一种方法,以及它们是单独有意义还是可以独立实现。如果没有,那么最好避免暴露除高级操作之外的任何东西。

答案 7 :(得分:1)

根据需要尽可能少地曝光。如果对FuncA()的呼叫总是,然后呼叫FuncB(),制作一个public并让它调用另一个,否则让public FuncC()按顺序调用它们。

答案 8 :(得分:1)

是的,它绝对应该是私密的,特别是因为所有方法似乎都没有参数,而你只关心订单。

我唯一会考虑明确调用每个方法的方法是,如果它们各自采用了几个非重叠参数,并且您不希望将这么长的参数串传递给一个方法并且想要模块化。然后你应该确保清楚地记录它。但请记住,评论不可执行......您仍然需要比实际应该更多地信任您的用户。

信息隐藏和OOP的最大因素之一......只给用户绝对必要的东西。允许尽可能少的空间进行搞砸。

答案 9 :(得分:0)

公共或私人问题完全取决于您希望为对象公开的合同。您希望对象的用户单独调用方法,还是希望他们调用单个“DoStuff”方法并完成它?

all 取决于课程的预期用途。

在你给出的例子中,我说DoStuff应该是公开的,其余的是私有的。

答案 10 :(得分:0)

您认为对您的班级消费者来说哪个更容易?

绝对编写一个以正确顺序执行正确步骤的公共方法。否则,来电者不会做得对;他们会忘记一步或跳过一些东西。

答案 11 :(得分:0)

他们公开的一个原因是,如果您希望用户能够在步骤之间插入逻辑。在这种情况下,您应该强制通过保持一个非常小的状态机来在内部以正确的顺序调用函数。如果状态机以错误的顺序转换,除了执行错误之外,您还可以选择其他选项,例如抛出异常。

然而,如果需要在步骤之间采取行动的情况确实存在,则允许它们全部保持私有的替代设计。不是公开方法,而是提供一个公共回调接口,允许用户附加您在流程的每个步骤调用的处理程序。在您现在的私有doItAll()方法中,您可以执行以下操作:

if(preRetrieveHandlerExists){ preRetrieveHandler() } obj.RetrieveImages();

if(postRetrieveHandlerExists){ postRetrieveHandler() } //so on and so forth

答案 12 :(得分:0)

都不是。我认为您至少有3个对象,否则您将破坏单一责任委托人。您需要一个“获取并保存图像”的对象,一个“操纵图像”的对象,以及一个“管理外部供应商通信”的对象。

答案 13 :(得分:0)

我的软件工程经验法则是始终为用户/消费者/来电者提供尽可能少的机会。因此,请将方法保密,以确保正常工作。

答案 14 :(得分:0)

Fowler使用术语“特征嫉妒”来描述一个对象在另一个对象上调用少量方法(特别是重复)的情况。

我不知道他从哪里得到它。你在文献中没有看到太多,多年来很多人都不知道我在说什么(我不知道为什么,我以为这个名字在听到之后非常明显。这就是为什么我重复它)