By Chen Changyi, nicknamed Chang Yi, is a technical expert in the AutoNavi team at Alibaba.
Don Roberts proposed a refactoring principle, which is as follows:
When you do a task for the first time, you only need to do it. When you do a similar task for the second time, you may feel a bit reluctant, but still manage to do it. When you do the task for the third time, you should think about refactoring.
The same is true for coding. When writing similar code multiple times, we need to think whether there is a way to increase the coding speed. As someone who has been engaged in agile development for several years, in this article I would like to summarize some coding methods here to help programmers write code in a faster and more efficient way.
Most novice JAVA programmers may type out the following code on the development tool simply by muscle memory:
public class Test {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
Yes, this is the classic "Hello world" statement, the one everyone learns when they first code.
Naturally manually entering code is an option. And in actuality, manually entering code is a good test of someone's competence as a programmer. In fact, many companies use manual coding as part of a computer programming examination during the interview process. During such exams, the interviewee needs to select a programming tool (such as Eclipse) based on the examination requirements, and then manually write, debug, and run some specific code. During the entire coding process, the interviewee cannot search for answers on the Internet or view any online help documentation. Generally the requirements are that the interviewee must be able to write the code completely by him or herself. Such examination tests the interviewee's coding abilities, including the syntax, function, logic, thinking, algorithm, and hands-on abilities.
Manual coding is a basic skill that any good programmer should and really must have. Manual coding is like the basic writing skills needed to write an article. Syntax is the method for making sentences in code. Functions are the words and sentences in the article. The class libraries are anecdotes for quoting. The architecture is the genre for expressions. The functionality is the main purpose of writing the article. The algorithms are the logic for organizing the language. Therefore, you need to master the syntax of a programming language, learn a bunch of functions of basic class libraries, quote some required third-party class libraries, select a mature and stable architecture, clarify the functions of product requirements, and select an algorithm to realize the logic. Then, manual coding is as easy as writing an article.
As the saying goes in China: "If you study 300 Tang poems well, and you can recite those poems even if you can't write them." The same is true for coding. The first step of coding is imitation. That is, copy and paste code. Copying and pasting code is an art. When properly used, this method allows you to complete coding with half the effort. However, code that is not tested is incredible. When you see the code that you need, carefully check the code before copying and pasting it. Code suitable for one scenario may not be necessarily suitable for another scenario. A qualified programmer cannot simply take and use the code without checking it.
In short, copying and pasting code is like other coding methods, and no one method is superior to any of the others. It is just a method that you can use either properly or improperly. If you copy and paste code, you must be responsible for the results.
The following is a piece of code that has been written to implement user query:
/** Query user service function */
public PageData<UserVO> queryUser(QueryUserParameterVO parameter) {
Long totalCount = userDAO.countByParameter(parameter);
List<UserVO> userList = null;
if (Objects.nonNull(totalCount) && totalCount.compareTo(0L) > 0) {
userList = userDAO.queryByParameter(parameter);
}
return new PageData<>(totalCount, userList);
}
/** Query user controller function */
@RequestMapping(path = "/queryUser", method = RequestMethod.POST)
public Result<PageData<UserVO>> queryUser(@Valid @RequestBody QueryUserParameterVO parameter) {
PageData<UserVO> pageData = userService.queryUser(parameter);
return Result.success(pageData);
}
If you want to write code to implement company query, the code format is similar to the user query code. The replacement relationship can be sorted out as follows:
You can use a text editor, such as Notepad or EditPlus, to replace the common text in case-sensitive mode. The final result is as follows:
/** Query company service function */
public PageData<CompanyVO> queryCompany(QueryCompanyParameterVO parameter) {
Long totalCount = companyDAO.countByParameter(parameter);
List<CompanyVO> companyList = null;
if (Objects.nonNull(totalCount) && totalCount.compareTo(0L) > 0) {
companyList = companyDAO.queryByParameter(parameter);
}
return new PageData<>(totalCount, companyList);
}
/** Query company controller function */
@RequestMapping(path = "/queryCompany", method = RequestMethod.POST)
public Result<PageData<CompanyVO>> queryCompany(@Valid @RequestBody QueryCompanyParameterVO parameter) {
PageData<CompanyVO> pageData = companyService.queryCompany(parameter);
return Result.success(pageData);
}
If you generate code by means of text replacement, the code generation time does not exceed one minute.
Excel formulas are very powerful and can be used to compile some formulated code.
Copy the interface model definition from Wiki to Excel. The sample data is as follows:
Write an Excel formula as follows:
= "/** "&D6&IF(ISBLANK(F6), "", "("&F6&")")&" */ "&IF(E6 = "否", IF(C6 = "String", "@NotBlank", "@NotNull"), "")&" private "&C6&" "&B6&";"
Use the formula to generate the code as follows:
/** User ID */ @NotNull private Long id;
/** Username */ @NotBlank private String name;
/** User gender (0:unknown;1:male;2:female) */ @NotNull private Integer sex;
/** User description */ private String description;
Create a model class and organize the code as follows:
/** User DO Class */
public class UserDO {
/** User ID */
@NotNull
private Long id;
/** User Name */
@NotBlank
private String name;
/** User gender (0:unknown;1:male;2:female) */
@NotNull
private Integer sex;
/** User description */
private String description;
......
}
Copy the enumeration definition from Wiki to Excel. The sample data is as follows:
Write an Excel formula as follows:
="/** "&D2&"("&B2&") */"&C2&"("&B2&", """&D2&"""),"
Use the formula to generate the code as follows:
/** empty(0) */NONE(0, "Unknown"),
/** male(1) */MAN(1, "Male"),
/** female(2) */WOMAN(2, "Female"),
Create an enumeration class and organize the code as follows:
/** User gender enumeration class */
public enum UserSex {
/** enumeration definition */
/** empty(0) */
NONE(0, "unknown"),
/** male(1) */
MAN(1, "male"),
/** female(2) */
WOMAN(2, "female");
......
}
The company list is sorted as follows in Excel. Based on this list, you need to write SQL statements to insert the records directly into the database.
Write an Excel formula as follows:
= "('"&B2&"', '"&C2&"', '"&D2&"', '"&E2&"'),"
Use the formula to generate SQL statements as follows:
('AutoNavi', 'First Tower', '(010)11111111', 'gaode@xxx.com'),
('Alibaba Cloud', 'Green village', '(010)22222222', 'aliyun@xxx.com'),
('Cainiao', 'Alibaba offices', '(010)33333333', 'cainiao@xxx.com'),
Add the into statement header and sort the SQL statements as follows:
insert into t_company(name, address, phone, email) values
('AutoNavi', 'First Tower', '(010)11111111', 'gaode@xxx.com'),
('Alibaba Cloud', 'Green village', '(010)22222222', 'aliyun@xxx.com'),
('Cainiao', 'Alibaba offices', '(010)33333333', 'cainiao@xxx.com');
That is, use an existing tool to generate code. Many development tools provide tools to generate code, for example, to generate constructors, reload base classes or interface functions, generate Getter/Setter functions, and generate toString functions. These tools save the trouble of manual coding. You can also use some code generation plug-ins to generate code that meets certain application scenarios.
The following takes the MyBatis-Generator plug-in as an example to explain how to use a tool to generate code.
For more information, search for related documents on the Internet.
The content of the User.java file is as follows:
......
public class User {
private Long id;
private String user;
private String password;
private Integer age;
......
}
The content of the UserMapper.java file is as follows:
......
public interface UserMapper {
User selectByPrimaryKey(Long id);
......
}
The content of the UserMapper.xml file is as follows:
......
<mapper namespace="com.test.dao.UserMapper" >
<resultMap id="BaseResultMap" type="com.test.pojo.User" >
<id column="id" property="id" jdbcType="BIGINT" />
<result column="user" property="user" jdbcType="VARCHAR" />
<result column="password" property="password" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
id, user, password, age
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
select
<include refid="Base_Column_List" />
from test_user
where id = #{id,jdbcType=BIGINT}
</select>
......
</mapper>
That is, write the code by yourself and generate code in your own style. The following takes the MyBatis-based database access code as an example to explain this method.
First, obtain the table and column information required for code generation from the database.
The statements for querying table information are as follows:
select t.table_name as 'table name'
, t.table_comment as 'table remarks'
from information_schema.tables t
where t.table_schema = ?
and t.table_type = 'BASE TABLE'
and t.table_name = ?;
The first question mark indicates the value assigned to the database name, and the second question mark indicates the value assigned to the table name.
The table information query result is as follows:
SN. | Table name | Table remarks |
1 | org_company | Organization company table |
The statements for querying column information are as follows:
select c.column_name as 'column name'
, c.column_comment as 'column remarks'
, c.data_type as 'data type'
, c.character_maximum_length as 'character length'
, c.numeric_precision as 'numeric precision'
, c.numeric_scale as 'numeric scale'
, c.column_default as ''
, c.is_nullable as 'optional?'
, c.column_key as 'column key name'
from information_schema.columns c
where c.table_schema = ?
and c.table_name = ?
order by c.ordinal_position;
The first question mark indicates the value assigned to the database name, and the second question mark indicates the value assigned to the table name.
/** Generate model class file function */
private void generateModelClassFile(File dir, Table table, List<Column> 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 class */");
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("}");
}
}
/** Generate DAO interface file function */
private void generateDaoInterfaceFile(File dir, Table table, List<Column> columnList, List<Column> 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 interface */");
writer.println("public interface " + className + "DAO {");
writer.println("\t/** get" + classComments + "function */");
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("}");
}
}
/** Generate DAO mapping file function */
private void generateDaoMapperFile(File dir, Table table, List<Column> columnList, List<Column> 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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
......
writer.println("<!-- " + classComments + "Mapping -->");
writer.println("<mapper namespace=\"" + groupName + "." + systemName + ".database." + className + "DAO\">");
writer.println("\t<!—All field statements -->");
writer.println("\t<sql id=\"fields\">");
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</sql>");
writer.println("\t<!-- get" + classComments + "function statement -->");
writer.println("\t<select id=\"get\" resultType=\"" + groupName + "." + systemName + ".database." + className + "DO\">");
writer.println("\t\tselect");
writer.println("\t\t<include refid=\"fields\"/>");
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</select>");
writer.println("</mapper>");
}
}
/** Organize company DO class */
@Getter
@Setter
@ToString
public class OrgCompanyDO {
/** company logo */
private Long id;
/** company name */
private String name;
/** contact address */
private String address;
/** company description */
private String description;
}
/** Organize company DAO interface */
public interface OrgCompanyDAO {
/** Get organization company function */
public OrgCompanyDO get(@Param("id") Long id);
}
<!—Organize company mapping -->
<mapper namespace="xxx.database.OrgCompanyDAO">
<!—All field statement -->
<sql id="fields">
id
, name
, address
, description
</sql>
<!—Get organization company function statement -->
<select id="get" resultType="xxx.database.OrgCompanyDO">
select
<include refid="fields"/>
from org_company
where id = #{id}
</select>
</mapper>
Is the ultimate method of coding where you can directly tell the computer what you need and then the computer will automatically generate code? This may become a reality after technologies develop to a certain level in the future. But today, this method is unrealistic. In reality, you cannot "open your mouth to generate code right away", unless you are a boss, product manager, or technical manager.
The ultimate method of coding is to use whatever methods that are appropriate, instead of sticking to a method only. All coding methods listed in this article have their own advantages or disadvantages, and are applicable to different scenarios. Therefore, flexible use of various coding methods is the real ultimate coding method.
Many of the preceding coding methods require manual compiling of sample code. If your code does not comply with code specifications, it is difficult to find commonalities between code and abstract the sample code that can be used as a standard. If the sample code that functions as a standard does not comply with code specifications, the generated code also does not comply with code specifications, and the noncompliance will be magnified by tens, hundreds, or even thousands of times. Therefore, code standardization is the top priority of coding.
When thinking about this article, I saw this joke on the Internet: a netizen makes sarcastic comments about the resume of an Alibaba employee, saying that the resume is full of such sentences as "a set of XX methodology is precipitated to empower the XX business". The buzzword "empower" seems very cool. Regardless of the resume, a person who can start with methodology must be worth learning from. Therefore, I would also like to borrow these buzzwords for the title of my article, "Coding Methodology Empowers You and Me."
Let's Talk about Some of the Chaos You'll Find on Java Servers in Startups
204 posts | 12 followers
FollowTheRock - June 17, 2024
Alibaba Cloud Community - March 23, 2023
Alibaba Cloud Community - March 22, 2023
zepan - March 5, 2020
Adrian Peng - February 1, 2021
淘系技术 - April 14, 2020
204 posts | 12 followers
FollowA low-code development platform to make work easier
Learn MoreHelp enterprises build high-quality, stable mobile apps
Learn MoreAlibaba Cloud (in partnership with Whale Cloud) helps telcos build an all-in-one telecommunication and digital lifestyle platform based on DingTalk.
Learn MoreMore Posts by Alibaba Cloud Native