什么是技术细节,业务逻辑?
业务人员和开发人员对需求的时,常常会出现下面这段对话。
业务人员:我希望加一个用户注册的功能,用户要填入自己的用户电话,邮箱,还有头像,我们保存图片需要进行大小缩放,以便符合我们的要求,同时电话,邮箱要有效。
开发人员1:好的,当用户注册的时候,需要前端检查电话号码,邮箱是否正确。然后获得头像图片,进行图片处理,最后存到MySQL中的user和account表中。
用户注册操作代码实现如下
class UserService {
public void createUser(String username, String avatar, String phone, String email, String password){
if(password == null){
return;
}
if(password.contains("*")){
return;
}
...
String uploadUrl = getPicture(avatar)
User user = new User(username, phone, email, uploadedUrl);
userRepo.save(user);
}
private void getPicture(String avatar){
File avatarFile = processPicture(avatar)
// uploadFile 实现逻辑
...
}
// 图片处理,使得图片大小在一个规定的值
private File processPicture(String avatar){
//下载图片
//判断图片大小是否符合标准
//当图片过大,进行图片裁剪
//当图片过小,进行图片放大
...
}
}
class User{
private String username;
private String phone;
private String email;
private String uploadedUrl;
private String avatar;
}
可以看到,上面的对话和代码实现,包含2类内容。技术细节和业务逻辑。
- 技术细节:它们和业务无关,仅仅代表应用中的一种技术能力。如,我的数据库表如何设计,验证谁来做,是前后端分离还是不分离,数据是从前端来,还是从后端给。
- 业务逻辑:它们和业务相关,代表应用中的一种业务能力。如,填入电话,邮箱,头像图片,图片大小的规定。
再看看UserService,主要实现注册功能的类。processPicture方法中存在了处理图片的逻辑(裁剪图片,放大图片等技术细节),也包含了业务逻辑(规定的图片大小)。当我们想从UserService中了解业务逻辑时,我们需要读懂processPicture方法。我们需要花很长的时间去理解processPicture方法中的技术细节是在做什么(如何做图片裁剪,如何做放大图片操作)。然而,过多的技术细节展现对于了解业务逻辑没有任何帮助,反而会使人凌乱。使得代码不那么清晰。
用户注册操作代码修改
class UserService {
private int WIDTH_PIXEL = 1024;
private int HIGHT_PIXEL = 1024;
public void createUser(String username, String avatar, String phone, String email, String password){
if(password == null){
return;
}
if(password.contains("*")){
return;
}
...
String uploadedUrl = FileUtils.processPictureTo(avatar, WIDTH_PIXEL, HIGHT_PIXEL)
User user = new User(username, phone, email, uploadedUrl);
userRepo.save(user);
}
}
class User{
private String username;
private String phone;
private String email;
private String uploadedUrl;
private String avatar;
}
class FileUtil {
public String processPictureTo(String avatar,WIDTH_PIXEL, HIGHT_PIXEL){
//下载图片
//判断图片大小是否符合标准
//当图片过大,进行图片裁剪
//当图片过小,进行图片放大
//上传图片
}
}
再看修改后,我们将技术细节封装到了个新的类FileUtil中,同时将图片缩放的大小这个业务逻辑放在UserService中。这样,我们在读UserService的时候,就可以更清晰的了解业务逻辑。
为什么要区分?
大脑的短期记忆无法一次容纳约7个以上的记忆项目 —— 《金字塔原理》
当一个开发人员去熟悉一个新模块的时候,首先会从整体去了解这个新模块提供的功能,然后再会去看每个功能具体的实现细节是什么。就像画画一样,一开始要画草图去确定各个部分画什么东西,然后再慢慢补充细节。所谓细节都是魔鬼,如果一开始就进入细节,就容易陷入到细节中去,很难看到全局并找到重点。
因此,从认知的角度,我们其实一开始关注的是业务逻辑,当了解到我们关心的业务逻辑后,才会去做技术细节的展开。因此,我们可以把业务逻辑的代码和具体的技术实现进行分离,这样,可以帮助我们通过整体-细节的方式进行学习。
如何区分业务逻辑和技术细节?
我们可以通过问问题的方式来区分现在做的这个事儿是业务逻辑还是技术细节。
- 这个事儿业务人员关心么?有业务价值么?
排序算法业务关心么?把数据存到关系型数据库还是文档型数据库业务关心么?实时计算结果还是提前计算好结果保存下来,业务关心么?是先取A数据进行计算还是先去B数据计算,业务关心么?有价值么?
如果答案是:Yes,那么这就是业务逻辑,如果答案是:No,那么这些可能就是技术细节,需要封装到别处去 - 这个事儿换一种方式可以达成么?
冒泡排序可以换成其他方式?MySQL存储换一种方式可以达成么?实时计算结果换一种方式能达成么?
如果答案是:Yes,那么这就是技术细节,如果答案是:No,那么就是业务逻辑
区分后该怎么办?
分清了业务逻辑和技术细节后,我们需要把他们进行分区。
将业务逻辑放到一个package中,将技术细节放到一个package中。
三层架构
业务逻辑集中在service层中。业务无关的技术细节按照功能放到其他层。
- Controller
- TaskRequest
- TaskController
- TaskCreateRequest
- ProjectController
- ProjectResponse/ProjectVO
- Service
- Task
- TaskService
- Task
- Project
- ProjectService
- Project
- Picture
- Picture
- PictureService
- Repository
- Utils
- EdocUtils
- PicutreUtils
- Config
- LogConfig
- HealthCheckConfig
六边形架构
- adapter
- inbound(外部对本服务的访问,UI,controller)
- rest
- resources
- TaskRequest
- rpc
- outbound(本服务访问三方系统,db,中间件,服务)
- persist
- application(用例,用例可以调用多个domain里面的service)
- usecase
- TaskUseCase
- ProjectUseCase
- domain(业务模型)
- task
- Task
- TaskRepo
- project
- Project
- ProjectService
- config(配置信息)
- LogConfig
- HealthCheckConfig
网友评论