其他
系统困境与软件复杂度:为什么我们的系统会如此复杂?
读 A Philosophy of Software Design 有感,软件设计与架构复杂度,你是战术龙卷风吗?
前言
Aliware
什么是复杂性
Aliware
理性度量
感性认知
Complexity is anything that makes software hard to understand or to modify
译:所谓复杂性,就是任何使得软件难于理解和修改的因素。John Ousterhout 《A Philosophy of Software Design》
复杂性的表现形式
Aliware
症状 1-变更放大
Change amplification: a seemingly simple change requires code modifications in many different places.
译:看似简单的变更需要在许多不同地方进行代码修改。John Ousterhout 《A Philosophy of Software Design》
/**
* 销售捡入客户
*/
public void pick(String salesId, String customerId) {
// 查询客户总数
long customerCnt = customerDao.findCustomerCount(salesId);
// 查询销售库容
long capacity = capacityDao.findSalesCapacity(salesId);
// 判断是否超额
if(customerCnt >= capacity) {
throws new BizException("capacity over limit");
}
// 代码省略 do customer pick
}
症状 2-认知负荷
Cognitive load: how much a developer needs to know in order to complete a task.
译:开发人员需要多少知识才能完成一项任务。John Ousterhout 《A Philosophy of Software Design》
症状 3-未知的未知
Unknown unknowns: it is not obvious which pieces of code must be modified to complete a task.
译:必须修改哪些代码才能完成任务。John Ousterhout 《A Philosophy of Software Design》
为什么会产生复杂性
Aliware
想简单图省事,没有及时治理不合理的内容 缺少匠心追求,对肮脏代码视而不见
技术能力不够,无法应对复杂系统 交接过渡缺失,三无产品几乎无法维护
统一的中国与分裂的欧洲
软件固有的复杂性
The Complexity of software is an essential property, not an accidental one.
译:软件的复杂性是一个基本特征,而不是偶然如此。Grady Booch 《Object-Oriented Analysis and Design with Applications》
Everything, without exception, requires additional energy and order to maintain itself. I knew this in the abstract as the famous second law of thermodynamics, which states that everything is falling apart slowly.
译:世间万物都需要额外的能量和秩序来维持自身,无一例外。这就是著名的热力学第二定律,即所有的事务都在缓慢地分崩离析。Kevin Kelly 《The Inevitable》
软件架构治理复杂度
Aliware
架构的本质
结构化编程取消 goto 移除跳转语句,对程序控制权的直接转移进行了限制和规范 面向对象编程限制指针的使用,对程序控制权的间接转移进行了限制和规范 函数式编程以 λ 演算法为核心思想,对程序中的赋值进行了限制和规范
递增的复杂性
模糊性创造了复杂,依赖性传播了复杂 复杂性往往不是由单个灾难引起的
我们可以容易地说服自己,当前变更带来的一点点复杂性没什么大不了
编程思维论
1、战术编程
当前一定是最快的 不会花费太多时间来寻找最佳设计 每个编程任务都会引入一些复杂度 重构会减慢当前任务速度,所以保持最快速度
@HSFProvider(serviceInterface = AgnDistributeRuleConfigQueryService.class)
public class AgnDistributeRuleConfigQueryServiceImpl implements AgnDistributeRuleConfigQueryService {
@Override
public ResultModel<AgnDistributeRuleConfigDto> queryAgnDistributeRuleConfigById(String id) {
logger.info("queryAgnDistributeRuleConfigById id=" + id);
ResultModel<AgnDistributeRuleConfigDto> result = new ResultModel<AgnDistributeRuleConfigDto>();
if(StringUtils.isBlank(id)){
result.setSuccess(false);
result.setErrorMsg("id cannot be blank");
return result
}
try {
AgnDistributeRuleConfigDto agnDistributeRuleConfigDto = new AgnDistributeRuleConfigDto();
AgnDistributeRuleConfig agnDistributeRuleConfig = agnDistributeRuleConfigMapper.selectById(id);
if(agnDistributeRuleConfig == null){
logger.error("agnDistributeRuleConfig is null");
result.setSuccess(false);
result.setErrorMsg("agnDistributeRuleConfig is null");
return result
}
this.filterDynamicRule(agnDistributeRuleConfig);
BeanUtils.copyProperties(agnDistributeRuleConfig, agnDistributeRuleConfigDto);
result.setSuccess(true);
result.setTotal(1);
result.setValues(agnDistributeRuleConfigDto);
} catch (Exception e) {
logger.error("queryAgnDistributeRuleConfigById error,", e);
result.setSuccess(false);
result.setErrorMsg(e.getMessage());
}
return result;
}
}
Facade 层定义全部逻辑 - 未做结构分层 业务与技术未做分离 - 耦合接口信息与业务数据
Try catch 满天飞 - 缺少统一异常处理机制 没有规范化的日志格式 - 日志格式混乱
2、战术龙卷风
Almost every software development organization has at least one developer who takes tactical programming to the extreme: a tactical tornado.
译:几乎每个软件开发组织都有至少一个将战术编程发挥到极致的开发人员:战术龙卷风。John Ousterhout 《A Philosophy of Software Design》
是一位多产的程序员,没人比龙卷风更快完成任务 总能留下龙卷风后毁灭的痕迹留给后人去清理 是真的很卷
3、战略编程
工作代码远远不够 引入不必要的复杂度不可接受
不断对系统设计进行小幅改进 投资心态(每位工程师都需要对良好的设计进行连续的少量投资 10~20%)
系统的困境与演进
A condition that is often incorrectly labeled software maintenance. To be more precise, it is maintenance when we correct errors; it is evolution when we respond to changing requirements. 译:我们总是说我们需要“维护”这些老系统。而准确的说,在软件发展过程里,只有我们修正错误时,才是维护;在我们应对改变的需求时,这是演进。 Grady Booch 《Object-Oriented Analysis and Design with Applications》
it is preservation when we continue to use extraordinary means to keep an ancient and decaying piece of software in operation. Unfortunately, reality suggests that an inordinate percent- age of software development resources are spent on software preservation.
译:当我们使用一些极端的手段来保持古老而陈腐的软件继续工作时,这是保护(苟且)。事实证明我们更多的时间是在应对最后一种状况。
Grady Booch 《Object-Oriented Analysis and Design with Applications》
架构伪论
Aliware
好的代码自解释
Comments do not make up for bad code
译:注释不是对劣质代码的补救Martin Fowler 《Clean Code》
/**
* 批量查询客户信息
*/
public List<CustomerVO> queryCustomerList(){
// 查询参数准备
UserInfo userInfo = context.getLoginContext().getUserInfo();
if(userInfo == null || StringUtils.isBlank(userInfo.getUserId())){
return Collections.emptyList();
}
LoginDTO loginDTO = userInfoConvertor.convert(userInfo);
// 查询客户信息
List<CustomerSearchVO> customerSearchVOList = customerRemoteQueryService.queryCustomerList(loginDTO);
Iterator<CustomerSearchVO> it = customerSearchVOList.iterator();
// 排除不合规客户
while(it.hasNext()){
CustomerSearchVO customerSearchVO = it.next();
if(isInBlackList(customerSearchVO) || isLowQuality(customerSearchVO)){
it.remove();
}
}
// 补充客户其他属性信息
batchFillCustomerPositionInfo(customerSearchVOList);
batchFillCustomerAddressInfo(customerSearchVOList);
return customerSearchVOList;
}
无法精准命名
命名的含义是抽象实体隐藏细节,我们不能在一个名字上赋予它全部的信息,而必要的注释可以完美的进行辅佐。设计思想的阐述
代码只能实现设计不能阐述设计,这也是为什么一些复杂的架构设计我们需要文档的支撑而非代码的‘自解释’,在文档与代码之间的空隙,由注释来填补。
母语的力量
这点尤其适合我们中国人,有时并不是因为注释少代码多,所以我们下意识会首先看代码。而是我们几十年感受的文化,让我们对中文与ABC具有完全不一样的感观。
永远追求最优雅
The goal of software architecture is to minimize the human resources required
to build and maintain the required system.
译:软件架构的终极目标是,用最小的人力成本来满足构建和维护该系统的需求。Robert C.Martin 《Clean Architecture》
写在最后
Aliware
- A Philosophy of Software Design