程序设计——方法论总结

程序设计的所有原则和方法论都是追求一件事——简单——功能简单、依赖简单、修改简单、理解简单。因为只有简单才好用,简单才好维护。因此,不应该以评论艺术品的眼光来评价程序设计是否优秀,程序设计的艺术不在于有多复杂多深沉,而在于能用多简单的方式实现多复杂的业务需求;不在于只有少数人能理解,而在于能让更多人理解。

系列文章

程序设计——方法论总结
程序设计——领域驱动设计

前言

本篇希望可以为你解决如下问题提供思路

  1. 代码很难阅读:命名不规范、不地道,方法和类太臃肿,类之间调用关系绕来绕去
  2. 类分类不清楚,不知道一个类应该放哪个包下
  3. 分层不清楚,不知道哪层应该放什么样的代码
  4. 业务代码比较分散
  5. 扩展性差,牵一发动全身
  6. 做需求分析、系统设计、甚至是与团队沟通方案时不知道使用什么图做描述,或者使用的图不够地道

本篇是程序设计方法论的总结,其中有些不详细的地方请谅解,还望诸君查阅更多资料。如果有表达不正确的地方,也请指出。

1. 设计原则

1.1 开闭原则(Open Closed Principle)

描述

Software entities like classes, modules and functions should be open for extension but closed for modification
一个软件实体如类、模块和函数应该对扩展开放,对修改关闭。
适用场景: 模块、类、接口、方法
反例表现: 任何改动都只能在原来代码上删除和增加代码,牵一发而动全身,破坏原有代码的完整性,原来的功能都需要重新回归测试,才能保证功能没被影响。
好处: 扩展性好,代码变动风险低
如何做: 分离不变部分和易变部分,对不变部分做封装,对易变部分提供接口或者方法做扩展。
思考: 开闭原则是一切原则的总结,所有的原则都是为了实现开闭原则。

示例

先给出实现搜索功能的一个反例,如下

public class SearchService {
   
    public Result search(Params params) {
   
        // 关键词搜索
        if ("keyword".equals(params.getType())) {
   
            return searchByKeyword(params);
        }
        // 类目搜索
        if ("category".equals(params.getType())) {
   
            return searchByCategory(params);
        }
        // 促销搜索
        if ("promotion".equals(params.getType())) {
   
            return searchByPromotion(params);
        }
        
        return null;
    }
}

修改后的代码,如下

// 定义一个搜索接口
public class ISearch{
   
    Result search(Params params);
}

public class SearchService {
   
    // 使用一个容器来管理每个搜索类型的实现
    Map<String, ISearch> context = Map.of(
        "keyword", new KeywordSearch(), 
        "category", new CategorySearch(), 
        "promotion", new PromotionSearch());
        
    public Result search(Params params) {
   
        // 从容器中获取对应的搜索对象
        ISearch search = context.get(params.getEntryType());
        if (search == null) {
   
            return null;
        }
        return search.search(params);
    }
}

1.2 单一职责原则(Single Responsibility Principle)

描述

There should never be more than one reason for a class to change
适用场景: 模块、类、接口、方法
反例表现: 代码结构不清,代码量大呈现臃肿,重复代码。后果可读性差,不可维护,牵一发而动全身。
好处: 代码粒度小,可读性好。
如何做: 通过横向和纵向划分职责,组织代码结构,可使代码层级结构更清晰

示例

下面代码违法单一职责

public interface UserService {
   
  void register(String telephone, String password);
  void login(String telephone, String password);
  void sendEmail(String email);
  }

修改后代码如下

public interface UserService {
   
  void register(String telephone, String password);
  void login(String telephone, String password);
}

public interface EmailService {
   
  void sendEmail(String email);
}

1.3 依赖倒置原则(Dependence Inversion Principle)

描述

High level modules should not depend upon low level modules. Both should depend upon abstractions.
Abstractions should not depend upon details. Details should depend upon abstractions.

  1. 上层模块不应该依赖底层模块,它们都应该依赖于抽象。
  2. 抽象不应该依赖于细节,细节应该依赖于抽象。

作用
3. 避免类之间耦合
4. 提高系统稳定性

如何做
面向接口编程、IOC(spring ioc)、SPI

示例

以用户注册成功后发布成功消息为例子

// 1. 定义一个用户注册完成消息发布接口
public interface IUserRegisteredPublisher{
   
  void publish(User user);
}
// 2. 实现用户注册完成消息发布接口,把消息发布到kafka
public class UserRegisteredKafkaPublisher implements IUserRegisteredPublisher{
   
  @Override
  public void publish(User user) {
   
      System.out.println("send info to kafka");
  }
}
// 3. 定义用户注册服务
public class UserRegisterService{
   
  IUserRegisteredPublisher publisher;
  UserRegisterService(UserRegisterService publisher) {
   
      this.publisher = publisher;
  }
  
  public void register(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值