首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >我的代码这样优化,瞬间清爽多了

我的代码这样优化,瞬间清爽多了

作者头像
Lvshen
发布2022-05-05 18:55:59
发布2022-05-05 18:55:59
4340
举报

关于代码优化,我之前也写了一篇文章

今天这篇文章我们又来聊聊代码优化😀。

隐藏行为细节

在平时的开发过程中,你肯定会碰到这样的业务,比如判断车速是否正常。一般编码如下:

代码语言:javascript
复制
float speed = 60f;
if (speed > 0f && speed <120f) {
    Console.log("你的车速正常!!!");
}

其实按照面向对象封装的思想,功能应该是模块化的。我们不应该暴露车速判断的具体细节,优化后的编码可以这样写:

代码语言:javascript
复制
if (isNormalSpeed(speed)) {
    Console.log("你的车速正常!!!");
}

private static boolean isNormalSpeed(float speed) {
    return speed > 0f && speed < 120f;
}

我们将车速的具体判断隐藏,开发人员只需调用这个方法,无需在自己的代码中编写行为的细节。这样的封装更能复用。

同样,如果判断身份证是否合法,我们一般可能直接这样写:

代码语言:javascript
复制
String idCardNum = "xxxxxxxxxxxx";
if (idCardNum.length() == 18) {
    Console.log("合法的身份证号!!!");
}

当然,我建议这么写:

代码语言:javascript
复制
if (isIdCard(idCardNum)) {
    Console.log("合法的身份证号!!!");
}

private static boolean isIdCard(String idCardNumber) {
    return idCardNumber.length() == 18;
}

不要认为这么写多此一举,如果当业务逻辑越来复杂,业务的细节就会会散落在大量的方法中,原本代码的意图会渐渐不明确。会对代码的阅读加大难度。

这里我主要的思想就是:

“编写小而美的函数,将行为细节隐藏,进行模块化调用。”

赋予对象更丰富的行为

我们有一个Member实体类,实体类细节如下:

代码语言:javascript
复制
public class Member implements Serializable {

    private static final long serialVersionUID = 1L;
    
    private String id;

    private String name;
    ...
}

我们给name赋值,现在的业务逻辑是,判断这个Member对象是不是我的女朋友,常规编码如下:

代码语言:javascript
复制
Member member = new Member();
member.setName("Zhouzhou");

String userName = "Zhouzhou";
if (StringUtils.isNotBlank(member.getName()) && member.getName().equals(userName)) {
    Console.log("我的女朋友是:{}",userName);
}

上面的业务逻辑就是,如果Member中的name为"Zhouzhou",是我的女朋友的判断成立。

上面的代码功能上确实是没什么问题,但是看到这么多.头都晕了。这里违反了编码中的迪米特法则,一个对象应该对其他对象尽可能少的理解。我们优化代码如下:

代码语言:javascript
复制
public class Member implements Serializable {

    private static final long serialVersionUID = 1L;
    
    private String id;

    private String name;
    ...
    
    public boolean isMyGirlFriend (String userName) {
        return StringUtils.isNotBlank(this.getName()) && this.getName().equals(userName);
    }
}

这里我们增加Member的一个行为isMyGirlFriend(),用于判断实体对象中是不是我的女朋友。调用如下:

代码语言:javascript
复制
if (member.isMyGirlFriend(userName)) {
    Console.log("我的女朋友是:{}",userName);
}

实际上面属于充血模型,实体除了Getter/Setter方法,我们还增加了描述实体行为和动作的方法。

关于充血模型,我们再来举个例子。如果我们要专门写一个订单发货的方法,一般情况下我们是这么写的:

代码语言:javascript
复制
/**
 * 修改订单至发货
 * @return
 */
public void updateOrderDelivery(String orderId,String memberId) {
    Order order = new Order();
    order.setId(orderId);
    order.setMemberId(memberId);
    order.setStatus(OrderStatusEnum.DELIVERY.name());
    
    //修改方法
}

如果我们采用充血模型:

代码语言:javascript
复制
public class Order {

    /**
     * 订单id
     */
    private String id;

    /**
     * 下单用户id
     */
    private String memberId;

    /**
     * 订单状态
     */
    private String status;

    /**
     * 行为:构建一个发货状态的行为
     * @return
     */
    public void buildDeliveryStatus() {
        this.status = OrderStatusEnum.DELIVERY.name();
    }

}

在实体类中我们增加一个实体的发货行为方法buildDeliveryStatus(),调用如下:

代码语言:javascript
复制
/**
 * 修改订单至发货
 * @return
 */
public void updateOrderDelivery(String orderId,String memberId) {
    Order order = new Order();
    order.setId(orderId);
    order.setMemberId(memberId);
    //这里直接调用订单实体的行为方法
    order.buildDeliveryStatus();
    //修改方法

}

我认为充血模型也是面向对象思想的很好实践,开发人员不需要知道行为具体细节。我们将行为封装,从而实现行为的复用。

这篇文章到这里就结束啦,个人觉得编码细节对于程序员来说还是很重要的。有机会我还会写一篇编码优化的文章。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-10-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Lvshen的技术小屋 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 隐藏行为细节
  • 赋予对象更丰富的行为
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档