单一责任原则(SRP)

The Single Responsibility Principle (SRP) is one of the aspects of The SOLID Principles. It states that every class or object should have one purpose, one responsibility and effectively one reason for existence. This principle is concerned mainly with object-orientated programming but it can and should be thought about at a deeper granularity. Every function or method should have one reason to exist, do one thing and only one. It should do one thing and do that one thing well.

遵循SRP可以帮助您保持代码的可维护性,灵活性和易读性。 想象一下,无需运行代码或完全阅读每一行,就可以阅读您的代码并确切地了解它在做什么。 这将使代码更易于重构,并且通常也更易于处理。

Simple Example

让我们看一下非常简单的示例。 识别违反SRP的实体可能非常困难。 我们从一个简单的Square类开始,该类包含一个字段,即正方形的边长。 此类中有两种方法,一个字段的getter和setter。 显然,此类属于一个职责,因此遵循SRP。 它负责保存一个字段“ sideLength”。

public class Square {

  private int sideLength;

  public int getSideLength(){
    return sideLength;
  }

  public void setSideLength(int sideLength){
    this.sideLength = sideLength;
  }

}

现在,我们添加了一个名为“ getArea”的方法,该方法返回正方形的面积。 我们在类中添加了其他功能,因此现在它可以做两件事。 您可能会认为这现在与SRP背道而驰,因为它负责两方面的工作:边长和计算面积。 但是,如果我们更改SRP上下文的抽象,我们可以看到我们仍在遵循规则。 现在,类不再负责照看一个字段,而是照看我们的“方形”形状以及该对象所需的字段和操作。 它负责处理正方形形状。 重要的是要注意,我们类中的每个方法都负责一件事情,我们的“ getArea”方法除了返回计算出的面积之外没有做任何其他事情。

public class Square {

  private int sideLength;

  public int getSideLength(){
    return sideLength;
  }

  public void setSideLength(int sideLength){
    this.sideLength = sideLength;
  }

  public int getArea(){
    return sideLength * sideLength
  }

}

现在该打破单一责任原则了。 我们在方形类中添加了一个名为“ isUserAuthenticated”的方法,该方法将检查用户是否已通过我们的系统认证。 显然,此方法不合适,因为它与Square对象无关,所以不属于此类。 在我们的课堂中,这种新方法打破了SRP。

public class Square {

  private int sideLength;

  public int getSideLength(){
    return sideLength;
  }

  public void setSideLength(int sideLength){
    this.sideLength = sideLength;
  }

  public boolean isUserAuthenticated(User user){
    // Do something here
    return false;
  }

}

Real-Life Example

当我们打破单一责任原则时,前面的例子非常明显。 现在,让我们看一下您可能在真实的代码库或工作中处理的更真实的场景。 下面的类User显示了一系列与用户对应的字段; 他们的用户名,密码,名字和姓氏,出生日期,地址等。从技术上讲,这是遵循SRP的,因为它仅处理与用户有关的事情,在此类中没有任何奇怪或无关紧要的内容。 但是,如果我们仔细观察并考虑该类中可能还有其他代码,我们可能会提出不同的意见。

public class User {

  private String username;
  private String password;
  private String firstName;
  private String lastName;
  private Date dob;
  private String addressFirstLine;
  private String addressSecondLine;
  private String Country;
  private String addressPostcode;
  private String contactNumber;
  private String emailAddress;

  // Getters & Setters
  // + validation

}

我们可以争辩说,该类的地址部分与其他内容有关,它们具有不同的上下文。 我们可以将它们移到一个名为Address的新类中。 我们可以用联系号和电子邮件地址字段来争论同样的事情,就像使用ContactDetails一样。 这些是我们可以简化课程范围的简单方法,同时仍然忠实于SRP。

对于上述每个字段,我们可能都会进行验证,以确保密码强度高或电子邮件地址有效。 这些字段的验证可以移到单独的位置,因为验证是保存信息的另一责任。 我们也可能在此类中包含数据库代码,以从我们的数据库中保存和检索用户。 该代码也可以移到该类之外。 如您所知,在处理实际示例时,SRP可能会变得非常复杂,但是考虑类的目的并提取任何其他代码非常重要。 旨在保留有关用户的信息,验证某个字段,处理数据库交互以及处理日志记录吗?

Spring AOP

处理代码中的日志记录和安全性时,可能很难遵循单一职责原则。 您需要确保未经身份验证的用户无法访问这段代码,因此将其包装在身份验证检查中。 创建新的数据库项目时,您需要注销到文件,以便在代码周围添加一些日志记录行。 这些示例与SRP背道而驰,因为您的代码现在正在处理日志记录以及安全性或数据库交互。

幸运的是,如果我们使用Spring,它是Java编程语言的框架,则存在一个称为面向方面的编程(AOP)的模块。 我不会再详细介绍如何使用AOP或下面的代码如何工作,因为我将再次保存它。 AOP允许我们提取这些跨领域的问题,例如日志记录或身份验证。 横切关注点基本上是一些代码或功能,出现在代码中的许多模块或地方。 使用AOP,我们能够提取出这些问题,并且仍然遵循SRP。

@Aspect
public class UserAspect {

  private static final Logger LOGGER=LoggerFactory.getLogger(UserAspect.class);

  @Before("execution(public String getPassed())")
  public void getNameAdvice(){
    LOGGER.info("Executing Advice on getPassword()");
  }

  @Before("execution(* com.acroynon.spring.service.*.get*())")
  public void getAllAdvice(){
    LOGGER.info("Service method getter called");
  }

}

This post was originally published on https://acroynon.com

from: https://dev.to//acroynon/single-responsibility-principle-srp-i9l

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值