违反SRP,德米特定律等的影响

pha*_*ani 2 oop tdd refactoring unit-testing design-patterns

我知道以下是一个主观问题,但您的指导方针确实有助于我追求干净,可测试的代码.

请考虑以下示例,我认为这违反了一系列设计原则.

public class OfferEligibilityCheckerServiceImpl implements OfferEligibilityCheckerService, Refreshable{

     private Map<String, OfferCriteria>  offerIdToOfferCriteriaMap;

     private OffersAccessorService offersAccessorService

     public OfferEligibilityCheckerServiceImpl (OffersAccessorService offersAccessorService ){
            this.offersAccessorService = offersAccessorService;
            initValidOfferIdSet();
     }

     protected void initOfferIdToOfferCriteriaMap(){
          offerIdToOfferCriteriaMap = offersAccessorService.get..Criteria();
     }

     //REAL BUSINESS LOGIC, i.e. this is why the service is used by clients!!
     @Override 
     public boolean isUserEligible(String offerId, UserInfo userInfo){
          offerCriteria = offerIdToOfferCriteriaMap.get(offerId);
          return offerCriteria.isEligible(userInfo); // let's not worry about NPE
     }


     // Gets invoked at regular intervals by some scheduler, say Spring.
     @Override // from Refreshable
     public void refresh(){ // ANOTHER responsibility
         initOfferIdToOfferCriteriaMap();
     }
}
Run Code Online (Sandbox Code Playgroud)

我觉得上面的代码在很多层面都是错误的,但是我缺乏足够深入的知识来说服别人说它是平庸的/不可测试的.

根据我的有限知识,上述设计的问题在于它看起来是可测试的,因为某些部件可以替代,但它违反了所有"可测试设计"指南.

我和其他人之间的对话.

  1. :构造函数中的复杂逻辑.

    其他:不,我正在从构造函数中调用一个受保护的方法,如果你需要一个double测试,它可以被覆盖.

  2. :demeter违规法 - 要求确切的东西,而不是中介.

    其他:请参阅"代码到接口"的强大功能.我正在传递一个serviceImpl,而构造函数需要一个Service.所以我总是可以在测试时替换,以便在单元测试期间serviceImpl不会真正与DAO /数据库通信.

  3. :违反SRP - 处理业务逻辑,处理让我在构建过程中得到自己的东西,处理让我自己刷新.

    其他:那没关系!我不想将这个类分成3个类,并且要经历调度它们/连接它们的开销.

  4. :混合业务逻辑和对象构造逻辑.

    其他人:我甚至没有得到你.

问题1) 我是对的吗?

我可能没有指出正确的问题或者没有以正确的方式表达它们.

如果你能列出我们将来可能面临的问题,那就很好了.如果你可以解决或验证我的积分1到4,那就更好了.

问题2:您将如何重新设计它(包括接线部分)?

k.m*_*k.m 5

这就是设计模式和原则的问题 - 过分关注它们会使我们远离编写代码/生成软件的真正目的......这就是解决业务问题.

首先,让我告诉你为什么这段代码没问题:

  • 它很简单(我,作为一个与项目无关的人可以或多或少地告诉它它的作用)
  • 很小(一行解决一个问题的20行代码)
  • 它是可测试的(正如你的同事提到的,他们可以注入存根并测试它)

话虽如此,但结论显而易见 - 除了SRP违规之外,没有太大的改进空间; 令人耳目一新的部分确实可以在不同的组件中 然而,那么你有两个你必须连接在一起的东西(你的同事也提到过 - 事实上,这类已经有了).有人可能认为这是要走的路,但是当类/责任这么小时,努力通常不值得获益,而且往往会给代码带来不必要的复杂性.

您的第1,2和4点不是重新设计的最佳参数.你是对的SRP.但是,你的同事的论点更强 - 将这样的小班打成3个最有可能不会有任何好处,肯定会让人们稍后提出问题.

总而言之,值得记住的是,某些人在某些时候必须阅读您的代码.您需要知道何时停止关注模式和完美设计以及何时开始专注于使您的代码尽可能简单地让其他人遵循.