当前位置:网站首页>How to reduce the gap between software design and implementation
How to reduce the gap between software design and implementation
2022-07-31 22:33:00 【GeorgiaStar】
在软件领域,there is an old myth:That is, I can guarantee that the design and code implementation are exactly the same.This is indeed a very worthy goal.试想下,If our system is not designed,Or the design has nothing to do with the code implementation,With today's software so complex,Its implementation and maintenance difficulty can be imagined.
This article will combine my recentICTSome insights from doing software design training,Try to introduce some ways to reduce the gap between design and implementation,这些方法包括语言一致、Consistent design and code.In addition to introducing the method,I will take the operator billing system as a practical case,Assist to explain how to implement consistent design.诚然,Perfect design and consistent code are indeed myths(same as the myth of man-moon),因此,This article is not intended to guide you to become“神”,Rather, it is expected to be on a journey to reduce design and implementation inconsistencies,take a small step.
一、语言一致
“语言、语言、语言”,重要的事情说三遍,I have been sparing no effort in emphasizing the importance of language,because language is the foundation of everything,As Wittgenstein said,“Language boundaries determine our thinking boundaries”.
To ensure consistency of design and implementation,首先要保证的,the integrity of the concept and the consistency of the language.If the language is not consistent,其他的都是扯淡.
1. 统一语言
具体而言,我们需要保证“沟通语言、文档语言、设计语言、代码语言”的一致性.We can do this by unifying the language,统一语言(Ubiquitous Language)这个概念来自于Eric Evans的著作《Domain Driven Design》,When talking about it himselfDDD核心的时候,always put“统一语言”放在第一位.

The key to forming a unified language is that we have to develop a domain vocabulary,put in the field,Core concepts involved,用英文、中文、The form of interpretation is specified unambiguously.This vocabulary as a team“共识”,就是true of source,Subsequent activities should strictly follow the.
- 沟通语言:It's our daily communication、language used in the meeting,Everyone should use the language in the domain vocabulary to communicate,Otherwise, there will be a lot of chickens and ducks talking,you need a lot of time to clarify concepts.
- 文档语言:不管是需求文档,设计文档,测试文档等等,The language in it should be consistent with the domain vocabulary.
- 设计语言:Whether it's a use case diagram、模型图、流程图、类图、Timing diagram, etc. under design,Its language should also be consistent with the domain vocabulary.
- 代码语言:最后,也是最重要的.When the project landed,Our code, of course, also want to consistent and domain vocabulary.除此之外,Our code must also be consistent with the design intent.
2. 计费系统
In I enter any project the first thing,无一例外,Starts from the domain concepts.First of all, I need to understand,then dig concepts,Then work with the team to form a domain vocabulary(统一语言).Many teams that have been mentored by me,When looking back,也都表示“统一语言”One of the biggest point is help to them.
接下来,Let's take the operator billing system as an example,Find out what the Unified Language is,这个需求是这样的:
Operators provide telephone services to users,Support users to dial/接听电话,And the call charge.如:Active call to collect0.5元/minutes of calling;answer the phone charge0.4元/minutes of calling.
Operators to attract customers,Several phone plans are defined,There are three types of packages in total.The three packages are:
- 基础套餐:Caller charges0.5元/分钟;Called charges 0.4元/分钟
- Fixed duration package:Flat monthly fee100元,包含:200minutes calling time+200minutes called answer time
- 家庭套餐:Flat monthly fee20元,用户可以指定Nnumber as your family number,用户接听/There is no charge for calling the family number
我们要设计一个 计费系统 for package计费规则的执行,保存计费记录,And notify the account system to deduct fees.注意:during a call,The call control system may call the billing system multiple times for billing.
Everyone should be familiar with this requirement,It's what we use every day,通过分析需求,It is not difficult for us to put some core domain concepts inside,such as billing(Charge)、账户(Account)、Billing Package(ChargePlan)、计费规则(ChargeRule)wait to sort it out,Form the following domain vocabulary.

这里,What everyone needs to pay attention to is that in addition to showing the concept(that is clearly stated in the requirements.such as the concept of an account),There are also implicit concepts.The hermit concept is sometimes hidden deep,not easily obtained.Like the one marked in redResource这个概念,is a very important implicit concept,Is our package behind the customer rights and interests of the abstract,Because this benefit can be consumed,so call it资源(Resource).
3. 两个Tips
When building a domain vocabulary,有两个点需要注意一下.
一个是language is symbol,共识即正确.Vocabulary is not a person in the field of,It is an important consensus and asset of the team.It first requires team consensus,容易理解,As for the correctness of the translation, it is second.我经常拿Kangaroo(袋鼠)example of this word,When Captain Cook first arrived in Australia,Point to the kangaroo and ask the Aboriginal what it is,Indigenous people are afraid,回答说Kangaroo.it is meant to say“我不知道”,虽然 KangarooNot what the kangaroos meant,but as a symbol,does not affect our understanding and use.另外,为了方便理解,我曾经在CRM系统里,Use the concept of private sea with a typicalChinglish——PrivateSea来表示,instead of using the orthodox translationTerritory,因为PrivateSeaBetter for everyone to understand.
所以,The same goes for the Billing Systems Domain Glossary,such as the word set,when i was in class,Some students translate it intoCombo,说实话,I think more thanPlan更好的.But if the team is accustomed to usingPlanto indicate a package,It's okay to continue using.
第二个是language develops,也会迭代.Given the centrality of the Unified Language,Vocabulary is like a field“圣旨”,Everyone should strictly follow.But what's the one thing that doesn't change?,Sometimes we discover new concepts,will then be added to the vocabulary,It may also be found that there is a problem with direct comprehension,Change glossary.当然,The cost of change is high,But if it must be changed,We must also embrace change,该改就改.
二、设计一致
understand the problem domain,Domain Glossary,Then we can start our design work.Design work mainly includes the application architecture design,领域模型设计,详细设计等.The gist of this section is ourThe design must be strictly aligned with the domain vocabulary.Here we temporarily ignore the non-functional design requirements.Because today's infrastructure is relatively complete today,DFXNot much challenge,The main challenge is the business itself.当然有时候DFXwill also become critical,It's just that we don't consider it here.
1. The application architecture is consistent
在进行设计之前,We must first determine the application architecture.About Application Architecture,No more writing here,My other articles have elaborated.In general we have to follow a clean architecture(Clean Architecture)的思想,具体落地,You can use my open sourceCOLA(https://github.com/alibaba/COLA/)架构.

对于一个典型的业务应用系统来说,COLADo the following definition level,每一层都有明确的职责定义.
- 适配层(Adapter Layer):负责对前端展示(web/wireless/wap)的路由和适配,对于传统B/S系统而言,adapter就相当于MVC中的controller;
- 应用层(Application Layer):主要负责获取输入、组装上下文、参数校验,调用领域层做业务处理,如果需要的话,发送消息通知等.层次是开放的,应用层也可以绕过领域层,直接访问基础实施层;
- 领域层(Domain Layer):主要是封装了核心业务逻辑,并通过领域服务(Domain Service)和领域对象(Domain Entity)的方法对App层提供业务实体和业务逻辑计算.领域是应用的核心,不依赖任何其他层次;
- 基础实施层(Infrastructure Layer):主要负责技术细节问题的处理,比如数据库的CRUD、搜索引擎、文件系统、分布式服务的RPC等.此外,领域防腐的重任也落在这里,外部依赖需要通过gateway的转义处理,才能被上面的App层和Domain层使用.
To take care of the application architecture,我们可以考虑使用ArchUnit工具,to protect the integrity of the architecture,Mainly the layering strategy and the relationship between layers.对于COLA架构,We can take care of the following ways.
public class CleanArchTest {
@Test
public void protect_clean_arch() {
JavaClasses classes = new ClassFileImporter()
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
.importPackages("com.huawei.charging");
layeredArchitecture()
.layer("adapter").definedBy("com.huawei.charging.adapter")
.layer("application").definedBy("com.huawei.charging.application")
.layer("domain").definedBy("com.huawei.charging.domain")
.layer("infrastructure").definedBy("com.huawei.charging.infrastructure")
.whereLayer("adapter").mayNotBeAccessedByAnyLayer()
.whereLayer("domain").mayOnlyBeAccessedByLayers("application", "infrastructure")
.as("The layer dependencies must be respected")
.because("we must follow the Clean Architecture principle")
.check(classes);
}
}
2. Model design is consistent
Determined application architecture,We can start our modeling work,The model mainly here is the domain model(or conceptual model),Including Domain Modeling and Boundary Demarcation.补充说明一下,Associated with the billing system and call control system and account system.

Here we are mainly concerned with the billing system,For billing systems,Its core entity is nothing more thanAccount、ChargePlan、ChargeRule、ChargeRecord等这些,Its domain model is shown in the following figure.其中AccountAlthough it is a concept in the account system,But it's equally important for billing systems,So it should also be expressed.

more complex areas,Its core domain models are not too complicated,This kind of graph can use the classUMLclass diagram to draw,But don't expose too many details.另外,concepts in the modelStrictly follow the definitions in the domain glossary.If at design time you find that the vocabulary needs to be adjusted,Can go back and modify the glossary.But don't fork,This is the first hurdle to ensure our design consistency.
3. Consistent detailed design
The domain model expresses the core concepts of the system,But to fall on the code,Still need further detailed design.对于计费系统来说,Billing is on account(Account)的计费,Multiple packages can be set up an account,Each plan has one or more billing rules, etc..基于这样的思路,We can design more complete class diagram,to guide us in writing code.

This is a refinement of the domain model,Added some new elements needed in code implementation,比如ChargeContext是用来做Charge的上下文,CompositeChargeRuleIt is a combination mode design for billing rules,The billing rules are encapsulated,简化了Accountbilling calculation.
In addition to the detailed class diagram design,Sometimes for complex business logic,We will also use a swimlane、流程图、状态图、Sequence diagrams, etc. help us clarify business logic.For example, the swimlane diagram below actually expresses the priority relationship between different packages,Obviously the family package has the highest priority.

Here again,Detailed design is the same as model design,also be consistent with the domain vocabulary.Glossary is the decree,你可以调整,but can't deviate from.
三、代码一致
最后,也是最关键的部分.is how our code implementation is consistent with our design.首先,Let's take a look at the billing system(charging)application architecture code,the outermost4个package正是我们COLA提倡的4个层次.
If you go to see the applicationDSM(Dependency Structure Matrix,依赖结构矩阵),The following analysis results will be obtained,说明Domainis indeed the core of the application,因为Domain被Application依赖了69次,被Infrastructure依赖了19次,而DomainNo dependencies on other levels,This is in line with our architectural constraints.

On the premise of ensuring the consistency of the application architecture,We also need to make sure that our design and code are also consistent.不妨,Let's look at us as a wholeDomain层的代码.

Description of the code structure in the above figure,在domainModel is the most want to insideaccount和charge,其中charge里面有chargeplan和chargerule,each of the concepts,Each class is related to our domain vocabulary、In the design of naming to maintain consistent.This is consistent with our model design and detailed design.
Consistency of language is the foundation,对于代码来说,Correctly reflect model relationships,It is also very important to correctly reflect the design intent,否则,Even if you have the same language,Neither is design and implementation consistent.在设计部分,I said billing is forAccount进行的,而且一个AccountMultiple packages available,那么,我们不妨来看看Account的代码:
public class Account {
/** * 用户号码 */
private long phoneNo;
/** * 账户余额 */
private Money remaining;
/** * Accounts have meal */
private List<ChargePlan> chargePlanList = new ArrayList<>();;
@Resource
private AccountGateway accountGateway;
public Account(long phoneNo, Money amount, List<ChargePlan> chargePlanList){
this.phoneNo = phoneNo;
this.remaining = amount;
this.chargePlanList = chargePlanList;
}
/** * Check if account balance is sufficient */
public void checkRemaining() {
if (remaining.isLessThan(Money.of(0))) {
throw BizException.of(this.phoneNo + " has insufficient amount");
}
}
/** * Billing the account */
public List<ChargeRecord> charge(ChargeContext ctx) {
CompositeChargeRule compositeChargeRule = ChargeRuleFactory.get(chargePlanList);
List<ChargeRecord> chargeRecords = compositeChargeRule.doCharge(ctx);
log.debug("Charges: "+ chargeRecords);
// Update account system
accountGateway.sync(phoneNo, chargeRecords);
return chargeRecords;
}
}
从代码中不难看出,The entire billing entry is atAccount的charge(ChargeContext ctx),Account的chargePlanListproperty is the package it owns,This is exactly the same as the semantics in our design.
再比如FamilyChargePlan(家庭套餐)这个类,Earlier we said that the hidden behind the package is the resource(Resource),这个就是通过ChargePlan的getResource( )来体现的.
public class FamilyChargePlan extends ChargePlan<FamilyChargePlan.FamilyMember> {
public FamilyChargePlan() {
this.priority = 2;
}
@Override
public FamilyMember getResource() {
return new FamilyMember();
}
// Define the resources owned by the package
public static class FamilyMember implements Resource {
private Set<Long> familyMembers = new HashSet<>();
/** * Mock here, 真实场景下,The family number needs to be obtained from the external system * Directly write the fixed value here */
public FamilyMember() {
familyMembers.add(13681874561L);
familyMembers.add(15921582125L);
}
public boolean isMember(long phoneNo) {
return familyMembers.contains(phoneNo);
}
}
}
所以,In the landing code link,The key here is mainly two levels of consistency:
- 第一层:The language in the code should be consistent with the unified language,这个是基础,这一点做不到,Design and implementation will definitely not be consistent.
- 第二层:The implementation of the code should reflect the design intent,That is, the model and code in your design should correspond to,relationship in design(继承、组合、依赖等)To be fully represented in the code.
四、总结
为了Ensure that the design and implementation of consistent,Language is the key.only under the pull of a unified language,把我们从沟通、文档、设计、Domain Concept Alignment in Code,并在此基础上,Maximum guarantee our code reflects our design intent,It is possible to reduce the loss between design and implementation.

Complete billing system code example:https://github.com/alibaba/COLA/tree/master/samples/charge
边栏推荐
- Basic Grammar Introduction of Carbon Tutorial (Tutorial)
- grep命令 笔试题
- Daily practice——Randomly generate an integer between 1-100 and see how many times you can guess.Requirements: The number of guesses cannot exceed 7 times, and after each guess, it will prompt "bigger"
- BM5 合并k个已排序的链表
- BOW/DOM (top)
- 【核心概念】图像分类和目标检测中的正负样本划分以及架构理解
- Flex layout in detail
- NVIDIA has begun testing graphics products with AD106 and AD107 GPU cores
- The whole network is on the verge of triggering, and the all-round assistant for content distribution from media people - Rongmeibao
- HTC使用官方固件作为底包制作rom卡刷包教程
猜你喜欢
TestCafeSummary
嵌入式开发没有激情了,正常吗?
Bionic caterpillar robot source code
支付模块实现
GateWay implements load balancing
顺序表的实现
Shell script quick start to actual combat -02
In Golang go-redis cluster mode, new connections are constantly created, and the problem of decreased efficiency is solved
Write a database document management tool based on WPF repeating the wheel (1)
Arduino框架下STM32全系列开发固件安装指南
随机推荐
Arduino框架下STM32全系列开发固件安装指南
【公开课预告】:超分辨率技术在视频画质增强领域的研究与应用
Unity - by casting and cloning method dynamic control under various UGUI create and display
信息学奥赛一本通 1941:【07NOIP普及组】Hanoi双塔问题 | 洛谷 P1096 [NOIP2007 普及组] Hanoi 双塔问题
hboot与recovery、boot.img、system.img
A few permanent free network transmission, convenient and simple (Intranet through tutorials)
GateWay implements load balancing
Transfer Learning - Domain Adaptation
C程序设计-方法与实践(清华大学出版社)习题解析
Quick Start Tutorial for flyway
Realize serial port receiving data based on STM32 ring queue
Efficient Concurrency: A Detailed Explanation of Synchornized's Lock Optimization
#yyds dry goods inventory# Interview must brush TOP101: the entry node of the ring in the linked list
sqlite3简单操作
MySQL数据库‘反斜杠\’ ,‘单引号‘’,‘双引号“’,‘null’无法存储
Unity-LineRenderer显示一条线
Redis Overview: Talk to the interviewer all night long about Redis caching, persistence, elimination mechanism, sentinel, and the underlying principles of clusters!...
HTC使用官方固件作为底包制作rom卡刷包教程
The principle of ReentrantLock (to be continued)
Redis综述篇:与面试官彻夜长谈Redis缓存、持久化、淘汰机制、哨兵、集群底层原理!...