使用函数式编程进行重构

什么

重构是一种用于使代码更具可读性和
对人类而言是可以理解的,从而可以维护。 它不会影响
功能。 实际上,它不应该影响功能。

为什么

当您让其他人阅读您的代码时,重构是必要的。 因此,如果您在休息后重新访问代码,可能还会发现
很难理解。 重构也使添加新的内容更容易
功能,并供其他人在其代码中使用。 就是这样
重构代码很重要。

怎么样

让我们看下面的例子。 假设我需要编写如下程序:

名称:“ extract-properties ”。

描述: 从文件中提取并打印属性值

输入:

  • 文件 (类型为xml |属性| json ..)和
  • 要提取的值的 属性名称
  • 动态地图 (用相应的地图值替换在属性值中找到的动态地图键(如果有)。)

现在我们可以将问题分解为较小的问题,例如:

  1. 从给定文件中提取属性( Extract方法应该支持文件类型,例如xml,property,json。)
  2. 用动态值替换占位符

有三种解决方法。

  • 程序
  • 面向对象
  • 功能性

让我们评估所有三个。

程序

解决问题的程序方式,

  • main方法读取文件内容并调用提取方法。
  • extract方法使用if条件调用类型,根据类型解析内容
    特定的解析方法并提取属性并返回这些属性
    属性。
  • main方法现在调用replace方法,以其动态值替换占位符。

现在,假设您需要添加另一个处理程序,例如“ YAML”文件类型。 您将需要:

  • 在“提取”方法中添加另一个if else块。

上述方法的优点:

  1. 当扩展/修改受到限制时,易于编写。

上述方法的缺点是什么?

  1. 这会导致提取方法出现瓶颈。 在一个开发人员团队中,所有开发人员对单个实体的不断更新将导致合并冲突。
  2. 随着添加扩展,提取方法的大小将增加。 这将使其可读性降低。
  3. 在I / O操作中穿插业务逻辑将导致单元测试用例,而这需要实际资源而不是模拟资源。
  4. 由于资源I / O操作代码与业务逻辑紧密耦合,因此无法在代码的其他部分中重复使用。

面向对象

让我们有一个基类ResourceHandler 。 这定义了方法extract()和replace ()extract()需要允许自定义实现以支持将来的增强。 尽管replace()必须是通用逻辑,但与自定义提取实现无关。

我们可以这样建模:

如您所见,ResourceHandler具有方法:

  • 处理()。 它包含业务逻辑,就我们的目的而言,它可以很简单:
  • public Map handle ()  {
      extract();
      replace();
    }
  • 受保护的抽象void extract()-包含从文件中提取属性的逻辑
  • private void replace()-包含用于替换动态映射中的属性的逻辑

现在,抽象方法“提取”需要被其子类覆盖:

  • XmlResource
  • 杰森资源
  • 属性资源

以下是主要课程。

这种方法的优点:

  1. 这种结构允许添加新的扩展名而无需修改基本的“ handler”方法,该方法被调用以提取和替换属性。 因此,子类不能破坏业务逻辑。
  2. 提取方法不再像以前那样存在瓶颈
    程序代码。 现在每种自定义提取方法都有自己的方法
    在自己的类中实现。 这将减少可能的
    从事不同自定义提取实现的多个开发人员之间的合并冲突。
  3. 关闭对象“ ResourceHandler”以进行修改,同时打开其扩展。 这是SOLID的支柱之一
    原理。 例如,如果ResourceHandler作为jar共享,则可以
    仍然可以扩展以支持其他资源类型,但是
    基础基本逻辑仍然受到限制。

缺点:

  1. 用于提取给定类型的属性的IO逻辑仍与
    业务逻辑,由于基类的结构。 作为唯一
    公共方法是handle,它调用extract方法并替换
    方法。 因此,我们不能孤立地使用提取。

功能性

让我们使用如下接口来实现功能代码:

ResourceHandler接口定义单个方法“提取”,该方法提取文件和要提取的属性列表,然后从输入文件返回相应的提取属性。

我们将在业务逻辑中利用ResourceHandler,并注入
封装在类ExtractReplace中的特定实现
业务逻辑如下:

class ExtractReplace  {
  private Map extracted_properties;

  public ExtractReplace (File file, List properties,Map dynamic, ResourceHandler handler)  {
    Map props = handler.extract(file, properties);
    extracted_properties = replace(props, dynamic);
  }

  private Map replace (Map properties, Map dynamic)  {...}
  @Override
  public String toString ()  {
    return extracted_properties.toString();
  }
}

现在,主类将如下所示:

主类通过传递一个类型来创建ExtractReplace类型的对象
通过Lambda构造实现ResourceHandler接口
看过。 这演示了定义即席匿名的能力
不需要放在自己的类型中的实现,
从而降低结构复杂度。

我们还可以遵循一种更加结构化的方法,其中不同风格的ResourceHandlers存放在它们自己的类型中。

这种结构允许独立使用XmlHandler / JsonHandler…对象来提取属性。 与上面所示的面向对象的方法相比,这是一个优势。

主类可以创建特定类型的ResourceHandler的对象,并将它们传递给ExtractReplace类,如下所示:

您可以通过具有构建器类(使用构建器模式)来进一步解耦if-else代码,以实例化ResourceHandler。

具有'builder'模式的增强的ExtractReplace类将如下所示:

class ExtractReplace {
  private Map extracted_properties;

  static class Builder  {
    private File file;
    private List properties;
    private Map dynamic;
    private ResourceHandler handler;
    static Builder getInstance (File file, List properties, Map dynamic) {
      this .file = file;
      this .properties = properties;
      this .dynamic = dynamic;
      if (file.getName().endsWith( ".json" ))
        this .handler = new JsonHandler();
      else if (file.getName().endsWith( ".xml" ))
        this .handler = new XmlHandler();
  }
    public ExtractReplace build ()  {
      new ExtractReplace( this );
    }
  }
  private ExtractReplace (Builder builder)  {
    Map props = builder.handler.extract(builder.file, builder.properties);
  }
  private Map replace (Map properties, Map dynamic)  { ... }

  @Override
  public String toString () {
    return extracted_properties.toString();
  }
}

更多关于构建器模式的信息

优点:

  1. 除了面向对象方法提供的优势之外,这还将提取逻辑与业务逻辑分离。 因此,您可以重用此提取方法。
  2. 您可以通过创建可以重用的ResourceHandler的不同实现类来遵循结构化方法。
  3. 您还可以使用Lambda函数遵循即席匿名方法。 如果您不打算在其他地方重用提取逻辑,而又想降低结构复杂性,则这很有用。

最后说明

上面的功能代码是Strategy模式的实现,类似于Collections.sort,您可以在其中传递自定义的Comparator
实施。 如您所见,代码是可扩展的,更容易
消费,理解和扩展。

From: https://hackernoon.com/refactoring-using-functional-programming-g682o30g6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值