总结开源项目中的常见坏实践(Bad Practice)
一些开源项目包含了各种编程的最佳实践供人参考学习和借鉴。但是也有一些开源项目虽然初衷是好的。但是包含了一些代码的坏实践。特别是对于一部分刚入行的大学生来说,可能会给到一些错误的示范。于是在此列举一些项目中的坏实践。
1.方法的用意判断是与否却返回字符串的“0”或者“1”
如果一个方法明确返回是与否这两种情况,那么没有必要返回字符串的0或者1。这样会造成很多地方需要使用
字符串的形式来匹配结果判断是与否。例如以下这种形式。
方法应该直接返回true或者false。 代码会简洁明了很多。
2.滥用三元运算符
3.滥用机翻英语
Poor有不好,差的意思。 例如My english is poor.
这里的Poor是差的意思。
但是下图这个方法getDatePoor。也用poor来表达获取时间“差”的含义。
英语还是程序员应该要掌握学习的。不能光高机翻英语,不然容易闹笑话。
4.造不必要的大量轮子
很多方法或者功能我们应该尽可能的搜索是否已经有开源成熟的jar包或者框架实现。成熟的开源jar包或者框架,有大量完备的测试以及广泛的用户来确保质量。
如果实在需要自己造小轮子,请使用单元测试来确保质量
5.大量if else语句
大量的if-else语句,具体情况具体分析。但是大部分都可以用卫语句提前返回结果。避免大量嵌套。
例如左边的写法可以改为右边的写法
像下图这种情况可以用Stream Lambda来进行简化
优化后
6.多余的代码判断
有些时候可能会写出一些不必要的冗余判断
7.大量的代码细节让阅读者增加心智负担
我们应该封装一部分代码细节,暴露出代码的主流程,优化后
8.繁琐的代码逻辑
像上图这种情形,我们其实可以使用一句Stream 语句就可以描述出来。
9.数据库中是与否可以直接用tinyInt映射,不要用字符串来映射
这样会造成布尔字段取出时,还需要跟字符串1或者0进行比对,这是很尴尬的设计。
10.异常捕获之后不做任何处理
我们捕获异常之后一般都需要使用log来记录错误情形,如果什么都不做,就很可能丢失错误信息,并且使代码排查过程更加困难。
11.使用Map填充数据
使用Java是静态语言,使用Map填充数据,反而失去了静态语言带来了代码检查以及IDEA识别字段引用的功能。
12.混乱的常量
请不用将项目中所有的常量一股脑的放到一个类中。
可以使用像这种静态类的方式,分门别类地放入不同的常量
13.请使用驼峰命名
14.变量的定义请在系统内保持一致,比如1在系统内表示是。 请勿有时表示是,有时表示否。
有时候用1表示肯定,有时候用0表示肯定,有时候用Y表示肯定。
15.奇葩的代码脑回路
在外层方法判断一遍,在内层方法又进行一遍一样的判断
16.常量随意的命名格式
常量的命名请使用大写加下划线的格式
17.嵌套的Switch语句
就一种case了 完全没有必要使用switch语句
18.使用魔法值
例如项目中大量使用了“jpg”的字符串魔法值,使用魔法值使得我们无法统一找到代码的引用处。在重构的时候难免会有疏漏。
19.单个方法代码超过80行
如果单个方法的代码行超过80行,意味你的代码缺乏封装和可读性。例如这种一大坨的代码。
public static void initColumnField(GenTableColumn column, GenTable table)
{
String dataType = getDbType(column.getColumnType());
String columnName = column.getColumnName();
column.setTableId(table.getTableId());
column.setCreateBy(table.getCreateBy());
// 设置java字段名
column.setJavaField(StringUtils.toCamelCase(columnName));
// 设置默认类型
column.setJavaType(GenConstants.TYPE_STRING);
column.setQueryType(GenConstants.QUERY_EQ);
if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
{
// 字符串长度超过500设置为文本域
Integer columnLength = getColumnLength(column.getColumnType());
String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
column.setHtmlType(htmlType);
}
else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
{
column.setJavaType(GenConstants.TYPE_DATE);
column.setHtmlType(GenConstants.HTML_DATETIME);
}
else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
{
column.setHtmlType(GenConstants.HTML_INPUT);
// 如果是浮点型 统一用BigDecimal
String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
{
column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
}
// 如果是整形
else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
{
column.setJavaType(GenConstants.TYPE_INTEGER);
}
// 长整形
else
{
column.setJavaType(GenConstants.TYPE_LONG);
}
}
// 插入字段(默认所有字段都需要插入)
column.setIsInsert(GenConstants.REQUIRE);
// 编辑字段
if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
{
column.setIsEdit(GenConstants.REQUIRE);
}
// 列表字段
if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
{
column.setIsList(GenConstants.REQUIRE);
}
// 查询字段
if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
{
column.setIsQuery(GenConstants.REQUIRE);
}
// 查询字段类型
if (StringUtils.endsWithIgnoreCase(columnName, "name"))
{
column.setQueryType(GenConstants.QUERY_LIKE);
}
// 状态字段设置单选框
if (StringUtils.endsWithIgnoreCase(columnName, "status"))
{
column.setHtmlType(GenConstants.HTML_RADIO);
}
// 类型&性别字段设置下拉框
else if (StringUtils.endsWithIgnoreCase(columnName, "type")
|| StringUtils.endsWithIgnoreCase(columnName, "sex"))
{
column.setHtmlType(GenConstants.HTML_SELECT);
}
// 图片字段设置图片上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
{
column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
}
// 文件字段设置文件上传控件
else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
{
column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
}
// 内容字段设置富文本控件
else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
{
column.setHtmlType(GenConstants.HTML_EDITOR);
}
}
20.避免使用反逻辑
像图中!(x == 0)
可以直接改成x != 0
即可
还有以下这种冗余代码。
21.复杂的判断使用有意义的变量来替代
比如上图的判断我们可以用一个变量 isLongField来替代 提高代码的可读性。
22.常量没有使用final来修饰
如果没有使用final来修饰的话,就有可能在代码中被修改。
23.字符编码直接用字符串表示
字符编码,JDK中都有常量可以直接表示,我们可以直接使用
24.多余的方法修饰符
Java中interface类,方法默认都是Public的,没必要再加上public修饰符
25.不必要的ToString
26.多余的变量声明
如果变量声明之后没有做任何处理,请直接通过return返回,不要多声明一个变量
27.使用语义不清晰的方法
例如String的indexOf方法 我们完全可以使用contains方法来替代,使代码的语义更一目了然。
28.毫无必要的包装语句unboxing和boxing
Integer.valueOf
返回的本身就是int, 没有必要再调用intValue方法
29.使用+=进行在循环中字符串拼接
+=会造出临时的字符串,我们应该使用StringBuilder在循环中拼接字符串
以上就是总结的关于项目中的一些坏实践,请大家务必使用。有其他坏实践,恳请大家继续补充。
鄙人在业余时间弄了一个全栈项目Agileboot,初衷是想做一个代码规范,项目结构良好,可供大学生或者入门3年内的开发者参考使用的项目。
后端地址:
https://github.com/valarchie/AgileBoot-Back-End
鄙人能力水平有限,如果项目中发现不足或者错误,恳请指正。欢迎PR。一起构建一个规范完善的后端项目。
前端地址:
https://github.com/valarchie/AgileBoot-Front-End
鄙人前端小白,关于前端项目的规范以及优化仅作了力所能及的部分,还有很多优化空间。哪位前端大佬有兴趣一起帮忙规范和优化吗?
演示地址
www.agileboot.vip
欢迎加入全栈技术交流群:1398880
总结开源项目中的常见坏实践(Bad Practice)的更多相关文章
- android studio 使用jar包,arr包和怎么使用githup开源项目中的aar包或module
我这里的android studio的版本是2.2.3版本 一.现在大家都用android studio了,就有人问怎么使用jar包 其实使用jar包比较简单 直接吧jar放入工程的app目录下的li ...
- iOS之多控制器管理--项目中的常见文件
项目中的常见文件 内容大纲: 1.LaunchScreen 2.info.plist文件 3.pch文件 1.LaunchScreen xcode5和xcode6区别 1.xcode6没有Framew ...
- [转]C,C++开源项目中的100个Bugs
[转]C,C++开源项目中的100个Bugs http://tonybai.com/2013/04/10/100-bugs-in-c-cpp-opensource-projects/ 俄罗斯OOO P ...
- Xcode 6.4项目中的常见文件(info.plist)
Xcode 6.4项目中的常见文件(info.plist) 代码中获取 info.plist[NSBundle mainBundle] infoDictionary]; Bundle display ...
- iOS 项目中的常见文件
iOS的笔记-项目中的常见文件 新建一个项目之后,有那么多的文件,下面介绍一下主要的几个. 1.文件名 (1)AppDelegate UIApplication的代理,app收到干扰的时候,进行处 ...
- vue-axios的总结及项目中的常见封装方法。
前言 我们知道 vue 2.0版本开始推荐使用 axios 来完成前端 ajax 请求,axios 是一个基于Promise 的 http 库,可以用在浏览器和 node.js 中,axios 成为v ...
- dotnet 是 前30个增长最快速度的开源项目中排名第一的开发平台
CNCF 的博客 发了一篇文章 <Update on CNCF and Open Source Project Velocity 2020>,中文翻译参见 2020年CNCF和开源项目开发 ...
- 细数Android开源项目中那些频繁使用的并发库中的类
这篇blog旨在帮助大家 梳理一下前面分析的那些开源代码中喜欢使用的一些类,这对我们真正理解这些项目是有极大好处的,以后遇到类似问题 我们就可以自己模仿他们也写 出类似的代码. 1.ExecutorS ...
- 吐槽一下项目中的代码坏味道:滥用java常量
我们的项目中是否充斥着类似以下的代码呢?定义一个专门存放常量的java类(接口),非常多其它类依赖该常量类. public interface IConstant { int ZERO = 0; St ...
- C,C++开源项目中的100个Bugs
俄罗斯OOO Program Verification Systems公司用自己的静态源码分析产品PVS-Studio对一些知名的C/C++开源项目,诸如Apache Http Server.Chro ...
随机推荐
- 洛谷P1962 斐波那契数列 (矩阵快速幂)
学了矩阵,练一下手... 1 #include<bits/stdc++.h> 2 typedef long long ll; 3 const ll mod=1e9+7; 4 using n ...
- NodeJS 服务 Docker 镜像极致优化指北
这段时间在开发一个腾讯文档全品类通用的 HTML 动态服务,为了方便各品类接入的生成与部署,也顺应上云的趋势,考虑使用 Docker 的方式来固定服务内容,统一进行制品版本的管理.本篇文章就将我在服务 ...
- k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡
k8s 中的 service 如何找到绑定的 Pod 以及如何实现 Pod 负载均衡 前言 endpoint kube-proxy userspace 模式 iptables ipvs kernels ...
- MyBatis获取参数值的两种方式
MyBatis获取参数值的两种方式:${}和#{} ${}的本质就是字符串拼接,#{}的本质就是占位符赋值 ${}使用字符串拼接的方式拼接sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单 ...
- JDBC连接SQL Server2008 完成增加、删除、查询、修改等基本信息基本格式及示例代码
连接数据库的步骤: 1.注册驱动 (只做一次) 2.建立连接 3.创建执行SQL的语句.执行语句 4.处理执行结果 5.释放资源 1.建立连接的方法: Class.forName("com. ...
- JavaScript基础&实战(3)js中的流程控制语句、条件分支语句、for循环、while循环
文章目录 1.流程控制语句 1.1 代码 1.2 测试结果 2.弹窗提示输入内容 2.1 代码 2.2 测试结果 3.条件分支语句 3.1 代码 3.2 测试结果 4.while和 do...whil ...
- NLP之基于词嵌入(WordVec)的嵌入矩阵生成并可视化
词嵌入 @ 目录 词嵌入 1.理论 1.1 为什么使用词嵌入? 1.2 词嵌入的类比推理 1.3 学习词嵌入 1.4 Word2Vec & Skip-Gram(跳字模型) 1.5 分级& ...
- 7.websocket收发消息
客户端主动向服务端发起websocket连接,服务端接收到连接后通过(握手) 客户端 websocket socket = new WebSocket('ws://127.0.0.1/ws/'); 服 ...
- Codeforces Round #826 (Div. 3) A-E
比赛链接 A 题解 知识点:模拟. 时间复杂度 \(O(n)\) 空间复杂度 \(O(n)\) 代码 #include <bits/stdc++.h> #define ll long lo ...
- web安全学习(sql注入1)
web安全学习(sql注入1) 一.简介 sql语句就是数据库语句,而sql注入就是用户将自己构造的恶意sql语句提交,然后服务器执行提交的危险语句.sql注入可能造成信息泄露以及服务器被控制等危害. ...