我了解以下内容是一个主观的问题,但是您的指南确实可以帮助我追求简洁,可测试的代码。

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

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();
     }
}


我觉得上面的代码在很多层次上都是错误的,但是我缺乏足够的深入知识来说服其他人,它是中等/不可测试的。

据我所知,上述设计的问题在于它看起来是可测试的,因为某些零件可以被替换,但它违反了所有“可测试的设计”准则。

我和其他人之间的对话。


我:构造函数中的复杂逻辑。

其他:不,我正在从构造函数中调用一个受保护的方法,如果您需要两次测试,可以将其覆盖。
我:违反Demeter的法律-要求提供确切的信息,而不是中介。

其他:请参见“接口代码”的功能。我传入一个serviceImpl,而构造函数期望一个Service。因此,我总是可以在测试时进行替换,以使serviceImpl在单元测试期间不会真正与DAO /数据库对话。
我:违反SRP-处理业务逻辑,处理使我在构建过程中得到自己的东西,处理使我精神焕发。

其他:很好!我不想将此类分为3类,而要安排它们/连接它们的开销。
我:混合业务逻辑和对象构造逻辑。

其他人:我什至不明白你的意思。


问题1)
我对吗?

我可能没有指出正确的问题或没有以正确的方式表达问题。

如果您能列出以上设计在将来可能遇到的问题,那将是非常不错的。如果您可以解决或验证我的第1至4点,那就更好了。

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

最佳答案

这通常是设计模式和原理的问题-过多地关注设计模式和原理会使我们远离编写代码/生产软件的真正目的……这是为了解决业务问题。

首先,让我告诉您为什么此代码还可以:


这很简单(我,因为与项目无关的人或多或少可以分辨出它的作用)
它很小(一类解决一个问题的20行代码)
它是可测试的(如您的同事所述,他们可以注入存根并对其进行良好测试)


话虽如此,结论是显而易见的-除了违反SRP之外,没有太多的改进空间。令人耳目一新的部分确实可以在不同的组件中。但是,您将必须将两个连接在一起(正如您的同事所提到的-实际上,此类已经做到了)。有人可能会说这是要走的路,但是当类/职责很小的时候,付出的努力通常是不值得的,而且常常会给代码带来不必要的复杂性。

您的观点1,观点2和观点4不是重新设计的最佳理由。您使用SRP是正确的。但是,然后,您的同事的论点就更强了-将这么小的一类人分成3个极有可能没有任何好处,并且肯定会在以后引起人们的提问。

总而言之,值得记住的是,有人在某些时候必须阅读您的代码。您需要知道什么时候停止专注于模式和完美的设计,什么时候开始专注于使您的代码尽可能容易地被他人遵循。

关于oop - 违反SRP,Demeter定律等的影响,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21348251/

10-10 13:08