简介: 读完本章的收获:代码规范、代码可读性、鲁棒性的代码好坏案例,写出好代码的能力。
【资料图】
一、背景
开发一款Idea插件,实现对yaml文件的定制化格式检查。
!! 后指定的类路径是否准确 yaml中的key是否equal类中field的name value是否能够转换成类中field的类型 ……完成代码功能上线后,使用过程发现很多问题。后在主管帮助下,对代码进行了重构。事后对重构前后代码的好坏进行分析总结,文章下面将从 结构设计 、 代码可读性 、 鲁棒性 3个角度对重构前后代码作比较。
二、代码比较
1 结构设计
before:
after:
比较:
after:增加抽象类中的 celtVisitMapping 层代码,对多个代码检查模块做 统一代理 。做了错误的捕获,后面也可以做一些其他的统一处理(日志、标识参数等),方便拓展。
2 代码可读性
2.1命名
一个好的命名能输出更多的信息,它会告诉你,它为什么存在,它是做什么事的,应该怎么使用。
2.1.1 类
功能 | 时间 | 类名称 |
检查yaml文件是否可以成功反序列化成项目中的对象。 | before | YamlBaseInspection |
after | CeltClassInspection |
比较:
类的命名要做到 见名知意 ,before的命名 YamlBaseInspection 做不到这一点,通过类名并不能够获取到有用的信息。对于 CeltClassInspection 的命名格式,在了解插件功能的基础上,可以直接判断出属于yaml 类格式检查 。
2.1.2 函数
功能 | 时间 | 函数名称 |
比较value是否可以反序列化成PsiClass | before | compareNameAndValue |
after | compareKeyAndValue |
比较:
before:
1.name是Class中field中的name,通过函数名称并不能够看出,函数名传达 信息不准确 。
2.Value是yaml中map的概念前后 单位不统一 。两者放在一起,会使阅读代码者很迷惑。
after:函数名前后 单位统一 ,key和Value是一个yaml中map的两个概念。能从函数名得出函数功能:检验Key和Value的是否准确。
2.1.3 变量
//beforeASTNode node = mapping.getNode().findChildByType(YAMLTokenTypes.TAG);String className = node.getText().substring(2);//afterASTNode node = mapping.getNode().findChildByType(YAMLTokenTypes.TAG);String tagClassName = node.getText().substring(2);
比较:
String className 来源可以有两个:
1.通过yaml中 tag 标签在项目中查找得到。
2.PsiClass中的变量类型得出。
after:通过变量名 tagClass 可以快速准确的获取变量名属于上述来源中的第一个,能够降低 阅读代码的复杂度。 变量名可以传递更多有用的信息。
2.2 注释
2.2.2 注释格式
before 1.无注释 2.有注释不符合规范 after 有注释符合JavaDoc规范//beforeprivate boolean checkSimpleValue(PsiClass psiClass, PsiElement value) /** * 检查枚举类的value * @return */boolean checkEnum(PsiClass psiClass,String text)//after/** * @param psiClass * @param value * @return true 正常;false 异常 */private boolean checkSimpleValue(PsiClass psiClass, PsiElement value, ProblemsHolder holder)
2.2.3 注释位置
before:
//simple类型,检查keyName 和 value格式if (PsiClassUtil.isSimpleType(psiClass)) {//泛型(T)、Object、白名单:不进行检查} else if (PsiClassUtil.isGenericType(psiClass)) {//complex类型} else { }
after:
// simpleValue 为 null 或者 \"null\"if (YamlUtil.isNull(value)) { }if (PsiClassUtil.isSimpleType(psiClass)) { // simple类型,检查keyName 和 value格式 checkSimpleValue(psiClass, value, holder);} else if (PsiClassUtil.isGenericType(psiClass)) { //泛型(T)、Object、白名单:不进行检查} else { checkComplexValue(psiClass, value, holder);}
行内注释应该在解释的代码块内。
2.3 方法抽象
before:
public void compareNameAndValue(PsiClass psiClass, YAMLValue value) { //simple类型,检查keyName 和 value格式 if (PsiClassUtil.isSimpleType(psiClass)) { //泛型(T)、Object、白名单:不进行检查 } else if (PsiClassUtil.isGenericType(psiClass)) { //complex类型 } else { Mapmap = new HashMap<>(); MapkeyValuePsiTypeMap = new HashMap<>(); //init Map, 注册keyName Error的错误 PsiField[] allFields = psiClass.getAllFields(); YAMLMapping mapping = (YAMLMapping) value; CollectionkeyValues = mapping.getKeyValues(); for (PsiField field : allFields) { map.put(field.getName(), field.getType()); } for (YAMLKeyValue keyValue : keyValues) { if (map.containsKey(keyValue.getName())) { keyValuePsiTypeMap.put(keyValue, map.get(keyValue.getName())); } else { holder.registerProblem(keyValue.getKey(), \"找不到这个属性\", ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); } } keyValuePsiTypeMap.forEach((yamlKeyValue, psiType) ->{ //todo:数组类型type 的 check if (psiType instanceof PsiArrayType || PsiClassUtil.isCollectionOrMap(PsiTypeUtil.getPsiCLass(psiType, yamlKeyValue))) { } else { compareNameAndValue(PsiTypeUtil.getPsiCLass(psiType, yamlKeyValue), yamlKeyValue.getValue()); } }); }}
after:
public void compareKeyAndValue(PsiClass psiClass, YAMLValue value, ProblemsHolder holder) { // simpleValue 为 null 或者 \"null\" if (YamlUtil.isNull(value)) { return; } if (PsiClassUtil.isSimpleType(psiClass)) { // simple类型,检查keyName 和 value格式 checkSimpleValue(psiClass, value, holder); } else if (PsiClassUtil.isGenericType(psiClass)) { //泛型(T)、Object、白名单:不进行检查 } else { checkComplexValue(psiClass, value, holder); }}boolean checkComplexValue();
比较:
before: compareNameAndValue方法代码 过长 ,一个屏幕不能浏览整个方法。方法的框架不能够简洁明亮,即要负责判断类型,进行分发处理,还需要负责complex类型的比较,功能耦合。
after:把对complex对象的比较抽离出一个方法,该方法负责进行复杂类型的比较。原方法只负责区分类型,并调用实际的方法比较。能够清晰的看出 方法架构 ,代码后期易 维护 。
点击查看原文,获取更多福利!
https://developer.aliyun.com/article/1128548?utm_content=g_1000367316
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
-
花8000多元买的商品,白等两个月却没收到货?亚马逊回应“花8000多元买的商品,白等了两个月却没收到货。”近日,消费者赵先生向《中国消费者报》投诉,称他通过亚马逊购物APP下了两笔订单,在等待两个月后订单均被强制取消。
-
广东省消委会发布二手车买卖合同示范文本为配合广东省推进“阳光二手车”工作,促进二手车流通行业健康发展,推动经营主体树立诚信经营理念,规范二手车交易行为,切实保护消费者的合法权益。
-
国家卫健委:家庭医生签约服务“最后一公里”有望打通3月15日,国家卫生健康委、财政部等六部门共同提出的《关于推进家庭医生签约服务高质量发展的指导意见》(以下简称《意见》)发布。
-
2022年1~2月房企拿地榜出炉:冠军碧桂园近日,中指研究院公布了2022年1~2月房企拿地(金额)TOP100榜单。令业内惊讶的是,除了品牌房企名次“乾坤大挪移”,榜单内还冒出了许多“名不见经传”的新面孔。
-
这个春节,世界同庆中国年(环球热点)1月31日在芬兰赫尔辛基街头拍摄的舞龙表演。马蒂·马蒂凯宁摄(新华社发) 1月21日,联合国邮政管理局在纽约发
X 关闭
X 关闭