[JAVA] Coding methods and refactoring principles

Chanyi talked about the methods that can be used for ** coding ** and the current state of ** coding **, based on the problems of the refactoring principle.

Method 1: Write the code by hand

Most beginners JAVA Programmers type out the following code on development tools with just muscle memory You may.

public class Test {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}

Yes, this is the classic "Hello world" statement that everyone remembers when they first enter the code.

Of course, manually entering the code is also an option. And in practice, manually entering the code is a good way to test your ability as a programmer. In fact, many companies use manual coding as part of their computer programming exams during the interview process. For such exams, the interviewer selects a programming tool (such as Eclipse) based on the exam requirements and is specific. You have to write, debug, and run your code by hand. During the entire coding process, interviewers will not be able to search the internet for answers or view online help documentation. In general, it is a requirement that the interviewer be able to write the code entirely on his own. Such exams test the interviewer's coding abilities, including syntax, functions, logic, thinking, algorithms, and hands-on abilities.

Manual coding is a basic skill that any good programmer should have and really must have. Manual coding is like the basic writing skills you need to write an article. Syntax is a way to create sentences in your code. A function is a word or sentence in an article. A class library is an anecdote for quoting, and an architecture is a genre of expression. Features are the main purpose for writing articles. Algorithms are the logic for organizing languages. Therefore, master the syntax of programming languages, learn a bunch of basic class library features, cite some of the required third-party class libraries, choose a mature and stable architecture, and clarify the features of your product requirements. And you need to choose an algorithm that implements the logic. And manual coding is as easy as writing an article.

Method 2: Copy and paste the code

The same can be said for coding, as the Chinese proverb says, "If you study the 300 Tang dynasty poems well, you will be able to sing even if you can't write them." The first step in coding is to imitate. That is, copy and paste the code. Copying and pasting code is an art. If you use this method correctly, you can complete your coding with half the effort. When you have the code you need, check it carefully before copying and pasting. Code that is suitable for one scenario is not always suitable for another. Qualified programmers do not simply take and use code without checking it.

1. Why copy and paste the code

  1. You can shorten the development time by copying and pasting the existing code.
  2. By copying and pasting stable code, you can reduce the risk of system failure.
  3. By copying and pasting the network code, you can convert other people's achievements into your own achievements.

2. Problems with copying and pasting code

  1. How well do you understand the copied code? Is the implementation logic valid? Does the code work steadily? How many potential bugs are there?
  2. How many times have you copied and pasted the code in your project? If I do the same thing a third time, do I need to refactor the same code based on the refactoring principle?
  3. The more times you copy and paste the code, the more code maintenance problems will arise. The same changes must be made in each location to keep the code in sync after updating the code in multiple versions. As a result, maintenance costs and risks increase.

In short, copying and pasting code is like any other coding method, and no one is better. It's just a method that can be used properly or inappropriately. If you copy and paste the code, you are responsible for the result.

Method 3: Code generation by text replacement

1. Example of generated code

Below is a piece of code written to implement a 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);
}

When writing code that implements a corporate query, the code format is similar to that of a user query. The permutation relationship can be organized as follows.

  1. Replace "User" with "Company".
  2. Replace "user" with "company". Notepad and EditPlus You can use a text editor such as .0.31d5474dAMXb9I) to replace common text in a case-sensitive manner. The final result looks like this:
/** 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);
}

When generating code with text replacement, make sure that the code generation time does not exceed 1 minute.

2. Advantages and disadvantages

merit: 1, code generation speed is fast. Demerit:

  1. You need to compile the sample code. 2, this method only applies to text replacement scenarios.

Method 4: Generate code using Excel formulas

Excel formulas are very powerful and can be used to compile some formalized code.

1. Generate a model class using Excel formulas

Copy the interface model definition from the Wiki to Excel. The sample data is as follows.

image.png

Write the Excel calculation formula as follows.

= "/** "&D6&IF(ISBLANK(F6), "", "("&F6&")")&" */ "&IF(E6 = "no", IF(C6 = "String", "@NotBlank", "@NotNull"), "")&" private "&C6&" "&B6&";"

Generate code using formulas 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 your 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;
    ......
}

2. Generate an enumeration class using an Excel formula

Copy the enumeration definition from the Wiki to Excel. The sample data is as follows.

image.png

Write the Excel calculation formula as follows.

="/** "&D2&"("&B2&") */"&C2&"("&B2&", """&D2&"""),"

Generate code using formulas as follows:

/** empty(0) */NONE(0, "Unknown"),
/** male(1) */MAN(1, "Male"),
/** female(2) */WOMAN(2, "Female"),

Create an enumeration class and organize your 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");
    ......
}

3. Generate database statements using Excel formulas

The company list is sorted in Excel as follows. Based on this list, you need to write a SQL statement to insert the record directly into the database.

image.png

Write the Excel calculation formula as follows.

= "('"&B2&"', '"&C2&"', '"&D2&"', '"&E2&"'),"

Use the expression to generate a SQL statement similar to the following:

('AutoNavi', 'First Tower', '(010)11111111', '[email protected]'),
('Alibaba Cloud', 'Green village', '(010)22222222', '[email protected]'),
('Cainiao', 'Alibaba offices', '(010)33333333', '[email protected]'),

Add an into statement header and sort the SQL statements as follows:

insert into t_company(name, address, phone, email) values
('AutoNavi', 'First Tower', '(010)11111111', '[email protected]'),
('Alibaba Cloud', 'Green village', '(010)22222222', '[email protected]'),
('Cainiao', 'Alibaba offices', '(010)33333333', '[email protected]');

4. Advantages and disadvantages

merit:

  1. This method can be applied to code generation of table-based data.
  2. After writing the formula, you can generate the code by dragging and dropping. Therefore, the code generation speed is fast. Demerit:
  3. This method cannot be applied to code generation using complex functions.

Method 5: Generate code using a tool

That is, use your existing tools to generate the code. Many development tools provide tools to generate code. For example, generating constructors, reloading base classes and interface functions, generating getter / setter functions, generating toString functions, and so on. By using these tools, you can save yourself the trouble of manually coding. You can also use several code generation plug-ins to generate code that meets your specific application scenario.

In the following, we will explain how to use the code generation tool using the MyBatis-Generator plugin as an example.

1. Install and run the plugin

For more information, search the internet for related materials.

2. Example of generated code

** 2.1. Generate model class code ** The contents of the User.java file are as follows.

......
public class User {
    private Long id;
    private String user;
    private String password;
    private Integer age;
    ......
}

** 2.2 Mapper interface code generation ** The contents of the UserMapper.java file are as follows.

......
public interface UserMapper {
    User selectByPrimaryKey(Long id);
    ......
}

** 2.3. Mapper XML Code Generation ** The contents of the UserMapper.xml file are 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>

3. Advantages and disadvantages

merit:

  1. Generate code using the code generation plugin. Therefore, the code generation speed is fast.
  2. Use the plugin's configuration file to control the generation of the desired function code. Demerit:
  3. It takes time to learn how to use the code generation plugin and get used to it.
  4. The generated code does not always meet the code specifications. A code suitability check is required each time it is generated.
  5. After regenerating the code, the custom code is likely to be overwritten, so manage another code library, use the DIFF tool to identify the code differences, assign values, and then different It is recommended to paste the code.

Method 6: Generate code using code

In other words, write your own and generate your own code. The following describes this method using the MyBatis-based database access code as an example.

1. Inquiry about table information

First, get the table and column information needed for code generation from the database.

** 1.1. Inquire table information ** The statement for querying table information is:

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 shows the value assigned to the database name, and the second question mark shows the value assigned to the table name.

The query result of the table information is as follows.

SN. Table name Table remarks
1 org_company Organization company table

** 1.2. Query column information ** The statement for querying column information is:

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 shows the value assigned to the database name, and the second question mark shows the value assigned to the table name.

** The query result of the column information is as follows. ** **

image.png

2 Code compilation and generation

** 2.1 Compiling and generating model class code **

/** 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("}");
    }
}

** 2.2 Compiling and generating DAO interface code **

/** 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("}");
    }
}

** 2.3 Compiling and generating DAO mapper code **

/** 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>");
    }
}

3 Generation of related code

** 3.1 Generated model class code **

/** 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;
}

** 3.2 Generated DAO interface code **

/** Organize company DAO interface */
public interface OrgCompanyDAO {
    /** Get organization company function */
    public OrgCompanyDO get(@Param("id") Long id);
}

** 3.3 Generated DAO mapper code **

<!—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>

4. Advantages and disadvantages

merit:

  1. You can customize the code format to ensure the compliance of the generated code.
  2. You can customize the code function to generate only the desired code. 3, After pre-code precipitation, the code can be used directly later. Demerit:
  3. It is necessary to consider the data source to ensure that the data required for code generation is obtained.
  4. It takes time to create and compile a data model and generate code.

Ultimate method: Don't just stick to the method

Is it the ultimate coding method where you can tell the computer what you need and the computer will automatically generate the code for you? This may become a reality after some technological development in the future. However, this method is now impractical. In reality, unless you're a boss, product manager, or technical manager, you can't "generate code as soon as you open your mouth."

The ultimate way to code is not just stick to the method, but use whatever method is right for you. All of the coding methods listed in this article have their advantages and disadvantages and can be applied to a variety of scenarios. Therefore, it can be said that the true ultimate coding method is to flexibly use various coding methods.

Code standardization

Many of the preceding coding methods require you to manually compile the sample code. If your code does not comply with the code specification, it will be difficult to find common ground between the code and abstract the sample code that serves as a standard. If the sample code that functions as a standard does not comply with the code specifications, the generated code will also not comply with the code specifications, and non-compliance will increase tens, hundreds, and thousands of times. .. Therefore, code standardization is a coding priority.

Recommended Posts

Coding methods and refactoring principles
Functions and methods
Ruby variables and methods
[Java] Generics classes and generics methods
rails path and url methods
About pluck and ids methods
Java methods and method overloads
[Ruby] Singular methods and singular classes
Ruby variables and functions (methods)
Ruby methods and classes (basic)
Java abstract methods and classes
[Ruby] Singular methods and singular classes
About Java static and non-static methods
About the equals () and hashcode () methods
Ruby standard input and various methods
How to call classes and methods
Studying Java 8 (StaticIF and Default methods)
Java generics (defines classes and methods)
TCP: Basic Principles and Application Architecture
Application of downcase and slice methods