当前位置:网站首页>程序员怎么才能提高代码编写速度?
程序员怎么才能提高代码编写速度?
2022-07-04 14:46:00 【大方老师讲单片机】
程序员怎么才能提高代码编写速度?
Don Roberts提出的一条重构准则:第一次做某件事时只管去做;第二次做类似的事时会产生反感,但无论如何还是可以去做;第三次再做类似的事时,你就应该重构。
编码也是如此,当多次编写类似的代码时,我们需要考虑是否有一种方法能够提高编码速度,让编码速度“起飞”?高德地图技术专家陈昌毅(常意)多年来致力于敏捷开发,总结了一套编码的方法论,有助于程序员"快速、优质、高效"地进行编码。
方法1:手工编写代码
大多数刚学习 Java的程序员,都会怀着一种崇敬的仪式感,一字一句地在开发工具上敲出以下代码:
public class Test {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
没错,这就是经典的"Hello world",这也是大多数人手工编写的第一个程序。
手工编写代码,更能体现一个程序员的基本素质。有很多公司,都把上机编程考试作为面试的重要手段之一。面试者需要根据题目的要求,挑选一款熟悉的编程工具(比如Eclipse),手工编写代码并调试运行通过。在整个过程中,不能通过网络搜索答案,不能查看联机帮助文档,要求面试者必须手工编写代码,主要是考察面试者手工编写代码的能力——语法、函数、逻辑、思维、算法以及动手能力。
手工编写代码,是一个优秀程序员必须具备的基础能力。手工编写代码正如提笔写文章,语法就是遣词造句的方法、函数就是组成文章的词句、类库就是据经引典的掌故、架构就是行文表述的体裁、功能就是写作文章的主旨、算法就是组织语言的逻辑……所以,只要掌握一门程序语言的语法、学习一堆基础类库的函数、引用一些所需的第三方类库、选择一款成熟稳定的架构、明确一下产品需求的功能、挑选一种实现逻辑的算法……手工编写代码就会像写文章一样手到擒来。
方法2:复制粘贴代码
常言道:"熟读唐诗三百首,不会作诗也会吟。"编码也是同样的道理,编码的第一步就是模仿,简单地说就是"抄代码"——复制粘贴代码。复制粘贴代码是一门艺术,用好了编码会事半功倍。但是,没有检验过的东西,终究是不可全信的。当看到需要的代码时,在复制粘贴前,我们都需要仔细研读、认真思考、详细甄别……很多东西,都是仁者见仁、智者见智的东西,适合别的场景但不一定适合你的场景。作为一名合格的程序员,切不可一味地"拿来主义"。
1.为什么要复制粘贴代码
·复制粘贴现有代码,可以节省开发时间;
·复制粘贴稳定代码,可以降低系统故障风险;
·复制粘贴网络代码,可以把别人的成果化为己用。
2.复制粘贴代码带来问题
·你对复制的代码理解程度是多少?实现逻辑是否合理?能不能稳定运行?存在多少潜在的 Bug?
·这个代码在项目中已经复制粘贴了多少次?根据“三则重构”原则,你是否需要对这些相同代码进行重构?
·代码被复制粘贴次数越多,带来的代码维护问题越多。多个代码版本的更改和修正,要保持这些代码的同步,就必须需要在每一处进行同样的修改,增加了维护的成本和风险。
总之,复制粘贴代码,跟其它编码方法一样,没有优劣对错之分。它只是一种方法,你可以善用,也可以滥用。如果我们用到了复制粘贴,我们就必须为结果负责。
方法3:用文本替换生成代码
1.生成代码样例
已经编写好的用户查询相关代码:
/**查询用户服务函数 */
public PageData queryUser(QueryUserParameterVO parameter) {
Long totalCount = userDAO.countByParameter(parameter);
List userList = null;
if (Objects.nonNull(totalCount) && totalCount.compareTo(0L) > 0) {
userList = userDAO.queryByParameter(parameter);
}
return new PageData<>(totalCount, userList);
}
/**查询用户控制器函数 */
@RequestMapping(path = "/queryUser", method = RequestMethod.POST)
public Result<>> queryUser(@Valid @RequestBody QueryUserParameterVO parameter) {
PageData pageData = userService.queryUser(parameter);
return Result.success(pageData);
}
如果我们要编写公司查询相关代码,其代码形式与用户查询类似,整理出替换关系如下:
·把"用户"替换为"公司";
·把"User"替换为"Company";
·把"user"替换为"company"。
利用 Notepad、EditPlus等文本编辑器,选择区分大小写,进行普通文本替换,最终得到结果如下:
/**查询公司服务函数 */
public PageData queryCompany(QueryCompanyParameterVO parameter) {
Long totalCount = companyDAO.countByParameter(parameter);
List companyList = null;
if (Objects.nonNull(totalCount) && totalCount.compareTo(0L) > 0) {
companyList = companyDAO.queryByParameter(parameter);
}
return new PageData<>(totalCount, companyList);
}
/**查询公司控制器函数 */
@RequestMapping(path = "/queryCompany", method = RequestMethod.POST)
public Result<>> queryCompany(@Valid @RequestBody QueryCompanyParameterVO parameter) {
PageData pageData = companyService.queryCompany(parameter);
return Result.success(pageData);
}
利用文本替换生成代码,整段代码生成时间不会超过1分钟。
2.主要优缺点
主要优点:
·生成代码速度较快。
主要缺点:
·必须编写样例代码;
·只适用于文本替换的情景。
方法4:用Excel公式生成代码
Excel的公式非常强悍,可以用于编写一些公式化的代码。
1.利用 Excel公式生成模型类
从 WIKI上拷贝接口模型定义到 Excel里,样例数据内容如下:
编写 Excel公式如下:
= "/** "&D6&IF(ISBLANK(F6), "", "("&F6&")")&" */ "&IF(E6 = "否", IF(C6 = "String", "@NotBlank", "@NotNull"), "")&" private "&C6&" "&B6&";"
利用公式生成代码如下:
/**用户标识 */ @NotNull private Long id;
/**用户名称 */ @NotBlank private String name;
/**用户性别(0:未知;1:男;2:女) */ @NotNull private Integer sex;
/**用户描述 */ private String description;
创建模型类,整理代码如下:
/**用户DO类 */
public class UserDO {
/**用户标识 */
@NotNull
private Long id;
/**用户名称 */
@NotBlank
private String name;
/**用户性别(0:未知;1:男;2:女) */
@NotNull
private Integer sex;
/**用户描述 */
private String description;
......
}
2.利用 Excel公式生成枚举类
从 WIKI上拷贝枚举定义到 Excel里,样例数据内容如下:
编写 Excel公式如下:
="/** "&D2&"("&B2&") */"&C2&"("&B2&", """&D2&"""),"
利用公式生成代码如下:
/**空(0) */NONE(0, "空"),
/**男(1) */MAN(1, "男"),
/**女(2) */WOMAN(2, "女"),
创建枚举类,整理代码如下:
/**用户性别枚举 */
public enum UserSex {
/**枚举定义 */
/**空(0) */
NONE(0, "空"),
/**男(1) */
MAN(1, "男"),
/**女(2) */
WOMAN(2, "女");
......
}
3.利用 Excel公式生成数据库语句
用 Excel整理的公司列表如下,需要整理成 SQL语句直接插入数据库:
编写 Excel公式如下:
= "('"&B2&"', '"&C2&"', '"&D2&"', '"&E2&"'),"
利用公式生成 SQL如下:
('高德', '首开大厦', '(010)11111111', 'g[email protected]'),
('阿里云', '绿地中心', '(010)22222222', '[email protected]'),
('菜鸟', '阿里中心', '(010)33333333', '[email protected]'),
添加 into语句头,整理 SQL如下:
insert into t_company(name, address, phone, email) values
('高德', '首开大厦', '(010)11111111', '[email protected]'),
('阿里云', '绿地中心', '(010)22222222', '[email protected]'),
('菜鸟', '阿里中心', '(010)33333333', '[email protected]');
4.主要优缺点
主要优点:
·适用于表格化数据的代码生成;
·写好公式后,拖拽生成代码,生成速度较快。
主要缺点:
·不适用于复杂功能的代码生成。
方法5:用工具生成代码
用工具生成代码,顾名思义就是借用已有的工具生成代码。很多开发工具都提供一些工具生成代码,比如:生成构造函数,重载基类/接口函数,生成 Getter/Setter函数,生成 toString函数……能够避免很多手敲代码。还有一些生成代码插件,也可以生成满足某些应用场景的代码。
这里以 mybatis-generator插件生成代码为例,介绍如何利用工具生成代码。
1.安装运行插件
具体方法这里不再累述,自行上网搜索文档了解。
2.生成代码样例
| 2.1.生成模型类代码
文件 User.java内容:
......
public class User {
private Long id;
private String user;
private String password;
private Integer age;
......
}
| 2.2.生成映射接口代码
文件 UserMapper.java内容:
......
public interface UserMapper {
User selectByPrimaryKey(Long id);
......
}
| 2.3.生成映射XML代码
文件 UserMapper.xml内容:
......
id, user, password, age
select
from test_user
where id = #{id,jdbcType=BIGINT}
......
3.主要优缺点
主要优点:
·利用生成代码插件,生成代码速度较快;
·利用插件配置文件,控制生成想要的功能代码。
主要缺点:
·需要时间研究和熟悉生成代码插件的使用;
·生成的代码不一定满足代码规范,每次生成后需进行代码合规;
·重新生成代码后,容易覆盖自定义代码(建议维护单独的生成代码库,通过DIFF工具比较代码差异,然后再赋值粘贴差异代码)。
方法6:用代码生成代码
用代码生成代码,就是自己编写代码,按照自己的格式生成代码。下面,以生成基于 MyBatis的数据库访问代码为例说明。
1.查询表格信息
首先,我们要从数据库中拿到我们生成代码所需要的表和列相关信息。
| 1.1.查询表信息
查询表信息语句:
select t.table_name as '表名称'
, t.table_comment as '表备注'
from information_schema.tables t
where t.table_schema = ?
and t.table_type = 'BASE TABLE'
and t.table_name = ?;
其中,第1个问号赋值数据库名称,第2个问号赋值表名称。
查询表信息结果:
| 1.2.查询列信息
查询列信息语句:
select c.column_name as '列名称'
, c.column_comment as '列备注'
, c.data_type as '数据类型'
, c.character_maximum_length as '字符长度'
, c.numeric_precision as '数字精度'
, c.numeric_scale as '数字范围'
, c.column_default as ''
, c.is_nullable as '是否可空'
, c.column_key as '列键名'
from information_schema.columns c
where c.table_schema = ?
and c.table_name = ?
order by c.ordinal_position;
其中,第1个问号赋值数据库名称,第2个问号赋值表名称。
查询列信息结果:
2.编写生成代码
| 2.1.编写生成模型类代码
/**生成模型类文件函数 */
private void generateModelClassFile(File dir, Table table, List columnList) throws Exception {
try (PrintWriter writer = new PrintWriter(new File(dir, className + "DO.java"))) {
String className = getClassName(table.getTableName());
String classComments = getClassComment(table.getTableComment());
writer.println("package " + groupName + "." + systemName + ".database;");
......
writer.println("/** " + classComments + "DO类 */");
writer.println("@Getter");
writer.println("@Setter");
writer.println("@ToString");
writer.println("public class " + className + "DO {");
for (Column column : columnList) {
String fieldType = getFieldType(column);
String fieldName = getFieldName(column.getColumnName());
String fieldComment = getFieldComment(column);
writer.println("\t/** " + fieldComment + " */");
writer.println("\tprivate " + fieldType + " " + fieldName + ";");
}
writer.println("}");
}
}
| 2.2.编写生成 DAO接口代码
/**生成DAO接口文件函数 */
private void generateDaoInterfaceFile(File dir, Table table, List columnList, List pkColumnList) throws Exception {
try (PrintWriter writer = new PrintWriter(new File(dir, className + "DAO.java"))) {
String className = getClassName(table.getTableName());
String classComments = getClassComment(table.getTableComment());
writer.println("package " + groupName + "." + systemName + ".database;");
......
writer.println("/** " + classComments + "DAO接口 */");
writer.println("public interface " + className + "DAO {");
writer.println("\t/**获取" + classComments + "函数 */");
writer.print("\tpublic " + className + "DO get(");
boolean isFirst = true;
for (Column pkColumn : pkColumnList) {
if (!isFirst) {
writer.print(", ");
} else {
isFirst = false;
}
String fieldType = getFieldType(pkColumn);
String fieldName = getFieldName(pkColumn.getColumnName());
writer.print("@Param(\"" + fieldName + "\") " + fieldType + " " + fieldName);
}
writer.println(");");
......
writer.println("}");
}
}
| 2.3.编写生成 DAO映射代码
/**生成DAO映射文件函数 */
private void generateDaoMapperFile(File dir, Table table, List columnList, List pkColumnList) throws Exception {
try (PrintWriter writer = new PrintWriter(new File(dir, className + "DAO.xml"))) {
String className = getClassName(table.getTableName());
String classComments = getClassComment(table.getTableComment());
writer.println("");
......
writer.println("");
writer.println("");
writer.println("\t");
writer.println("\t");
if (CollectionUtils.isNotEmpty(columnList)) {
boolean isFirst = true;
String columnName = getColumnName(pkColumn.getColumnName());
for (Column column : columnList) {
if (isFirst) {
isFirst = false;
writer.println("\t\t" + columnName);
} else {
writer.println("\t\t, " + columnName);
}
}
}
writer.println("\t");
writer.println("\t");
writer.println("\t");
writer.println("\t\tselect");
writer.println("\t\t");
writer.println("\t\tfrom " + table.getTableName());
boolean isFirst = true;
for (Column pkColumn : pkColumnList) {
String columnName = getColumnName(pkColumn.getColumnName());
String fieldName = getFieldName(pkColumn.getColumnName());
writer.print("\t\t");
if (isFirst) {
writer.print("where");
isFirst = false;
} else {
writer.print("and");
}
writer.println(" " + columnName + " = #{" + fieldName + "}");
}
writer.println("\t");
writer.println("");
}
}
3.生成相关代码
| 3.1.生成的模型类代码
/**组织公司DO类 */
@Getter
@Setter
@ToString
public class OrgCompanyDO {
/**公司标识 */
private Long id;
/**公司名称 */
private String name;
/**联系地址 */
private String address;
/**公司描述 */
private String description;
}
| 3.2.生成的 DAO接口代码
/**组织公司DAO接口 */
public interface OrgCompanyDAO {
/**获取组织公司函数 */
public OrgCompanyDO get(@Param("id") Long id);
}
| 3.3.生成的 DAO映射代码
id
, name
, address
, description
select
from org_company
where id = #{id}
3.主要优缺点
主要优点:
·代码格式可以定制,保证生成代码合规;
·代码功能可以定制,只生成需要的代码;
·经过前期代码沉淀后,后期能够直接使用。
主要缺点:
·需要研究数据来源,保证能获取到生成代码所需的数据;
·需要建立数据模型、编写生成代码,耗费时间比较长。
终极方法:无招胜有招
编码的终极方法,是不是直接对着电脑说需求,然后电脑就自动生成代码了?未来科技发展到一定水平后,这种情况或许会变成现实。但是,目前这种情况是不现实的。现实中,想要做到"大口一张、代码就来",除非你是老板、产品经理或者技术管理者。
编码的终极方法是“无招胜有招”,"无招"并不是不讲究"招式",而是不拘泥于某一"招式",信手拈来合适的"招式"为宜。本文中列举的各种编码方法,没有高低优劣之分,只有合不合适之说。所以,灵活地运用各种编码方法,就是编码的终极方法。
代码规范化
在上面的各种编码方法中,很多方法都需要手工编写样例代码。如果你的代码不遵循代码规范,就很难发现代码之间的共性,并抽象出能够作为标准的样例代码;如果作为标准的样例代码不满足代码规范,必然导致生成的代码也不满足代码规范,于是把这些不规范放大了十倍、百倍甚至千倍。所以,代码规范化是编码的重中之重。
边栏推荐
- Essential basic knowledge of digital image processing
- .Net 应用考虑x64生成
- Opencv learning -- geometric transformation of image processing
- 嵌入式软件架构设计-函数调用
- [native JS] optimized text rotation effect
- Using celery in projects
- Dry goods | fMRI standard reporting guidelines are fresh, come and increase your knowledge
- Talking about Net core how to use efcore to inject multiple instances of a context annotation type for connecting to the master-slave database
- What encryption algorithm is used for the master password of odoo database?
- Will the memory of ParticleSystem be affected by maxparticles
猜你喜欢
Will the memory of ParticleSystem be affected by maxparticles
Talking about Net core how to use efcore to inject multiple instances of a context annotation type for connecting to the master-slave database
How was MP3 born?
What should ABAP do when it calls a third-party API and encounters garbled code?
Interface fonctionnelle, référence de méthode, Widget de tri de liste implémenté par lambda
Redis' optimistic lock and pessimistic lock for solving transaction conflicts
函數式接口,方法引用,Lambda實現的List集合排序小工具
Vscode setting outline shortcut keys to improve efficiency
2022年九大CIO趋势和优先事项
Function test - knowledge points and common interview questions
随机推荐
Anta is actually a technology company? These operations fool netizens
TypeError: not enough arguments for format string
How can floating point numbers be compared with 0?
Unity script API - time class
Market trend report, technical innovation and market forecast of tetrabromophthalate (pht4 diol) in China
Practice: fabric user certificate revocation operation process
What encryption algorithm is used for the master password of odoo database?
Review of Weibo hot search in 2021 and analysis of hot search in the beginning of the year
Ten clothing stores have nine losses. A little change will make you buy every day
Hair and fuzz interceptor Industry Research Report - market status analysis and development prospect forecast
Preliminary practice of niuke.com (10)
[book club issue 13] ffmpeg common methods for viewing media information and processing audio and video files
Audio and video technology development weekly | 252
嵌入式软件架构设计-函数调用
Find numbers
Some fields of the crawler that should be output in Chinese are output as none
China's plastic processing machinery market trend report, technological innovation and market forecast
Unity animation day05
Rearrange array
AI system content recommendation issue 24