代码之家  ›  专栏  ›  技术社区  ›  etoisarobot

需要按特定顺序执行的方法应该是私有的吗?[关闭]

c#
  •  26
  • etoisarobot  · 技术社区  · 15 年前

    我有一个类,它检索一些数据和图像,并对它们执行一些操作,然后使用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 回复  |  直到 15 年前
        1
  •  25
  •   John Feminella    15 年前

    这取决于谁知道应该这样调用方法。

    • 消费者知道: 例如,如果对象是 Stream ,通常是 消费者 决定何时 Open , Read Close 小溪。显然,这些方法必须是公共的,否则对象不能正确使用。(*)

    • 对象知道: 如果 对象 知道方法的顺序(例如 TaxForm 并且必须按照特定的顺序进行计算),那么这些方法应该是私有的,并通过一个更高级别的步骤(例如 ComputeFederalTax 将调用 CalculateDeductions , AdjustGrossIncome DeductStateIncome )

    • 如果步骤的数量超过少数,则需要考虑 Strategy 而不是让步骤直接耦合到对象中。然后你就可以改变周围的事物,而不必过多地干扰对象或其接口。

    在您的特定情况下,对象的使用者似乎不关心正在进行的处理操作以外的任何事情。因为它不需要知道这些步骤发生的顺序,所以应该只有一个名为 Process (或者其他类似的东西)。


    (*)但是,通常对象至少知道 秩序 其中可以调用方法以防止无效状态,即使它不知道 什么时候 去做这些步骤。也就是说,对象应该知道足够多的信息,以防止自己进入一种无意义的状态;如果试图调用 关闭 之前 正常开放 就是一个很好的例子。

        2
  •  14
  •   Rex M    15 年前

    如果除非首先调用a(),否则方法b()确实无法调用,那么正确的设计要求a返回b作为参数所需的某个对象。

    这是否总是切实可行是另一回事,但就是这样 应该 完成。

        3
  •  4
  •   Sam Holder Brian Adams    15 年前

    是的,私人的,否则你就给用户留下了做错事情的机会,这只会给每个人带来痛苦。

    你需要自己调用这些方法吗?他们中有人单独做些有用的事吗?如果是这样,那么您可能希望保持这些公开,但即使您将它们全部公开,您也应该拥有按正确顺序(最好使用有用的名称)调用它们的方法,以使您的用户更轻松。

        4
  •  4
  •   Gabe Timothy Khouri    15 年前

    这完全取决于操作是否本质上是原子的。在这种情况下,对我们这些局外人来说,这看起来像是一个单一的行动,但这真的是吗?如果 LogIntoThirdPartyWebService 失败,用户界面是否需要显示一个对话框来询问用户是否要重试?如果只有一个操作,请重试 登录第三方Web服务 操作还需要重做潜在的昂贵操作,如 RetrieveImages ,同时使它们分离可以实现更细粒度的逻辑。

    在这种情况下,我会这样做:

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

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

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

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

        5
  •  3
  •   i_am_jorf    15 年前

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

    所以你应该有一个 DoStuff() 方法,该方法获取所有必需的参数,并将所有实现详细信息设为私有。

        6
  •  2
  •   Ian P    15 年前

    private——获取构造函数中的参数并在那里执行顺序。

    不要以为打电话的人会或知道如何按顺序打电话给他们。

    所以,我不想举你列举的例子,而是这样做:

    MyObject myObject = new MyObject(); // make a constructor to take any parameters that are required to "setup" the object per your requirements.
    myObject.UploadToWebService();
    
        7
  •  1
  •   Uri    15 年前

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

        8
  •  1
  •   egrunin    15 年前

    尽可能少地暴露,尽可能多地暴露。 如果调用 FuncA() 总是 接着是一个电话 FuncB() ,做一个 public 让它叫另一个,否则 public FuncC() 按顺序给他们打电话。

        9
  •  1
  •   froadie    15 年前

    是的,它绝对应该是私有的,特别是因为所有的方法似乎都是无参数的,而您只关心顺序。

    我唯一考虑显式调用每个方法的时候是,如果每个方法都有几个不重叠的参数,并且您不希望将这么长的参数字符串传递给一个方法,并且希望模块化。然后你应该确保记录下来 清晰地 . 但请记住,评论是不可执行的…你仍然需要比你真正应该信任你的用户多一点。

    信息隐藏和面向对象的最大因素之一…只给用户绝对必要的东西。留出尽可能小的空间来收拾残局。

        10
  •  0
  •   Randolpho    15 年前

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

    全部的 取决于类的预期用途。

    在你给出的例子中,我认为dostuff应该是公共的,其余的应该是私有的。

        11
  •  0
  •   Michael Todd    15 年前

    你认为哪个对你班的消费者更容易?

    绝对的 编写一个按正确顺序执行正确步骤的公共方法。否则,打电话的人不会做对的;他们会忘记一步或跳过一些事情。

        12
  •  0
  •   DancesWithBamboo    15 年前

    两者都不。我认为你至少有三个目标否则你就违反了单一责任原则。您需要一个“获取并保存图像”的对象、一个“操纵图像”的对象和一个“管理外部供应商通信”的对象。

        13
  •  0
  •   frankc    15 年前

    它们公开的一个原因是,如果您希望用户能够在步骤之间插入逻辑。在这种情况下,您应该通过保留一个非常小的状态机来强制要求函数在内部以正确的顺序调用。如果状态机以错误的顺序转换,除了做一些错误的事情(例如引发异常)之外,您还有其他选择。

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

    if(preretrievehandlerExists){ 预检索处理程序() } 目标检索图像();

    如果(postRetrieveHandlerExists){ PostRetrieveHandler() } /等等

        14
  •  0
  •   Brandi    15 年前

    我的软件工程经验法则是总是给用户/消费者/调用者尽可能少的机会把事情搞砸。因此,请将方法保密以确保工作秩序。

        15
  •  0
  •   Jason    15 年前

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

    我不知道他从哪儿弄来的。你在文学作品中看不太多,多年来很多人都不知道我在说什么(我不知道为什么,我觉得这个名字一听到就很明显了)。这就是我重复的原因)