技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> 基于DSL风格的代码重构

基于DSL风格的代码重构

浏览:2183次  出处信息

什么样代码是简洁易懂, 这很难有个统一的标准, 因为它很大程度上决定于所在团队的编写风格(往往偏向于核心程序员).

正因如此, 本文仅仅呈现一下DSL的编码风格, 若你喜欢, 不妨在自己的实践中也试试; 不欣赏者, 只当浮云飘过吧

有如下java代码片段:

以下是代码片段:
public class Subscriber {
  private long skip;
  private final Channel channel;

  public Subscriber(final Channel channel, final long skip) {
    this.channel = channel;
    this.skip = skip;
  }

  public void receive(final ChannelBuffer buffer) throws Exception {
    if (buffer == null) {
      channel.write(new DefaultHttpResponse(HttpVersion.HTTP_1_1,
                                            HttpResponseStatus.OK));
      channel.close();
      return;
    }

    if (skip == 0) {
      channel.write(buffer);
      return;
    }

    if (buffer.readableBytes() <= skip) {
      skip = skip - buffer.readableBytes();
      return;
    }

    buffer.skipBytes((int) skip);
    channel.write(buffer);
    skip = 0;
  }
}

代码并不多, 看上去也还算简洁, 只是需要细细琢磨一下才能明白编写者的意图.

为了达到”显意”(代码尽可能直接表露业务含义, 而非执行步骤), 让我们重构一下:

以下是代码片段:
  public void receive(final ChannelBuffer buffer) throws Exception {
    if (isTail(buffer)) {
      sendOkResponseTo(channel);
      return;
    }

    if (skip == 0) {
      send(buffer, channel);
      return;
    }

    if (buffer.readableBytes() <= skip) {
      skip = skip - buffer.readableBytes();
      return;
    }

    buffer.skipBytes((int) skip);
    send(buffer,channel);
    skip = 0;
  }

  static void send(final ChannelBuffer buffer, Channel channel) {
    channel.write(buffer);
  }

  static void sendOkResponseTo(Channel channel) {
    channel.write(new DefaultHttpResponse(HTTP_1_1, OK)); // import static constants
    channel.close();
  }

  static boolean isTail(final ChannelBuffer buffer) {
    return buffer == null;
  }

似乎好了点, 至少能够一看出来的是:

  1. 若buffer到达结尾, 需要向channel发送OK的应答, 并关闭channel;
  2. 此外需要根据skip和buffer.readableBytes的大小关系, 决定要不要向channel发送buffer

有两点小不足的是:

  1. skip和buffer.readableBytes的大小关系, 如何处理不明了;
  2. if - return 看着不够简洁.

再重构一下:

以下是代码片段:
  public void receive(final ChannelBuffer buffer) throws Exception {
    if (isTail(buffer) && thenSendOkResponseAndClose(channel)) return;
    if (buffer.readableBytes() <= skip && thenSkip(buffer)) return;
    if (skip > 0) skipPartOf(buffer);
    send(buffer);
    skip = 0;
  }

  boolean thenSkip(final ChannelBuffer buffer) {
    skip = skip - buffer.readableBytes();
    return true;
  }

  void send(final ChannelBuffer buffer) {
    channel.write(buffer);
  }

  void skipPartOf(final ChannelBuffer buffer) {
    buffer.skipBytes((int) skip);
  }

  static boolean isTail(final ChannelBuffer buffer) {
    return buffer == null;
  }

  static boolean thenSendOkResponseAndClose(final Channel channel) {
    channel.write(build(OK).response());
    channel.close();
    return true;
  }

尽管代码行数上比最初的版本有了少许增加, 但核心方法receive的意图却变的更为明显了.

建议继续学习:

  1. 构建前端 DSL    (阅读:2719)
  2. 说说Shell在代码重构中的应用    (阅读:2408)
  3. API设计新思维:用流畅接口构造内部DSL    (阅读:2149)
  4. 为脚本语言平反-JavaScript篇(2)    (阅读:1992)
  5. 为脚本语言平反-JavaScript篇(3)    (阅读:1851)
  6. 从Java和JavaScript来学习Haskell和Groovy(DSL)    (阅读:1059)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1