谁应该负责调用方法?

时间:2017-09-03 06:08:18

标签: architecture solid-principles design-principles responsibility grasp

如果我有一个复杂的任务需要解决,我有时会遇到一种控制执行的方法。由于null检查,if语句,调用类型之间的映射方法等等,这种方法可能会变得很长,而且我很难使它变得更简单。

示例1

public class A
public string MethodA(string stringA)
{
    var fooResult = _fooService.fooMethod(stringA);

    if(fooResult)
    var barResult = _barService.barMethod(fooResult);

    if(barResult)
    // And so on..

    return someResult;
}

我可以链接方法调用,这使第一个方法更简单。但是这使得fooMethod依赖于_barService,而barMethod依赖于_someService等等。

示例2(与上面相同,但使用链式方法调用)

public class B
public string MethodB(string stringB)
{
    return _fooService.fooMethod(stringB);
}

public class Foo
public string fooMethod(string stringB)
{
    return _barService.barMethod(stringB);
}

public class Bar
public string barMethod(string fooString)
{
    return _someService.someMethod(fooString);
    // And so on...
}

我应该如何构建代码?当涉及到哪个方法负责调用另一个方法时,我该如何思考?

换句话说,我应该这样做:

class A
{
  Execute()
  {
    A();
    B();
    C();
  }

  method A()
  {
  ...
  }

  method B()
  {
  ...
  }

  method C()
  {
  ...
  }
}

或者像这样:

class B
{
  Execute()
  {
    A();
  }

  method A()
  {
    B();
  }

  method B()
  {
    C();
  }

  method C()
  {
  ...
  }
}

2 个答案:

答案 0 :(得分:1)

这取决于。

如果阶段定义明确,在大多数情况下按顺序调用它们会更方便。

然而,如果例如B被很好地定义但是A和C实际上只是依赖于B的工作的开始和结束,那么A或C本身都没有多大意义并且难以命名/描述或为了评估它们是否已经成功,那么在这种情况下,将A和C组合在一个调用B的方法中更有意义。 分离方法以便每个方法执行特定任务都是好的,但是如果该部分任务本身没有多少意义,则应该避免将事物分离到只执行任务的一部分。

您应该考虑如何测试代码 - 使用一种设计比另一种设计更容易。

考虑如何维护代码。这是最容易理解代码的地方,但也考虑一个阶段是否需要编辑来修复错误或增强功能;哪种设计允许您以最少的努力,对其他代码的副作用以及对不应该受到影响的区域的相关重新测试来做到这一点?

想想您将来是否需要改变其中一个步骤 - 根据某些输入或设置调用B的替代版本?

考虑可重用性。如果A呼叫B,则在您不想同时呼叫B的情况下无法重复使用A,在您的其他设计中,您可以重复使用A.

他们是否总是需要按顺序调用 - 是否可以通过并行调用B和C来优化速度(从B调用C不允许)。

如果B失败,你仍然应该尝试调用C(我怀疑大多数人会说不是因为这更可能是真的,但它确实取决于真正的问题)单独调用通常比链接更容易。 / p>

赞成从A调用B,你只需要在界面中公开A,并且(如果你选择的语言允许)你可以使B和C私有。然后更容易确保B只从A调用,因此B可以避免测试某些初始条件是真的,只是依靠A完成它的工作。

当然,上面的问题不仅仅是答案,而是因为任何一种设计都可能是正确的,这取决于你的实际任务是什么,但希望上述考虑因素可以帮助你做出决定。

答案 1 :(得分:0)

您的所有任务都没有普遍的决定权。基本上,您应该努力编写简短的方法并执行一项任务。正确的方法命名将帮助您做到这一点(似乎这是你的问题)。例如,避免使用ExampleClass.DoWork()ExampleClass.ManageObject(object)这样的名称,因为它们不精确并且会导致复杂和长期的实现。

一般来说,&#34; serial&#34;最后两个示例的版本更易于阅读,A()B()C()可能会有更多简单的实现,并且更容易正确命名。< / p>

有关更具体的建议,您可以在Code Review

中发布您的代码