You may gain by learning this article
1, a requirement from generation, analysis to the solution of the whole process of thinking 2, simple object-oriented analysis practice 3, UML class diagram practice 4, the practical application of design pattern 5, finally harvest a fairly good code generation tool implementation ideas and source code
This paper will start from the whole process requirements -> goals -> ideas -> design -> realization -> summary mentioned in the first point.
In order to try to reproduce how a requirement would be implemented from scratch in a real world scenario, this article will assume that no one touches the code to generate this thing. You have to start from scratch.
Let’s begin the text.
1. Look at demand first
One day, Feng xiaonan (his young self) was writing code when the technical manager came over and patted feng xiaonan on the shoulder.
“Xiao Nan, you see our system inside so many add, delete, change and check functions, although copy copy can, but the efficiency is not high enough.”
Feng xiaonan thought
“Are CV mode efficiency is not high, you zha heaven?” .
Then the tech manager said
You see, now the user management module is finished, when I do other roles and organization management, the code specification and basic add, delete, change and check structure are the same, right? It can be copied quickly to achieve the other two functions, but there are several problems in this process still affect efficiency
First: file renaming problem, a basic module from the foreground to the background about 7-10 code files, in the copy at the same time all need to be renamed, the number of files depends on the development system and standards of each company. You can have fewer files, or you can have more
Second: there must be some different entity attributes, which need to be modified or added, which is a part of the workload
Third: class, method, field remarks need to adjust it, such as user management class remarks is user management, then you copy into role management to change to role management. The method fields are all the same
Fourth: class attributes, method names, local variables, etc., will also need to change, for example, UserService injected by UserController, userList variable declared inside method, that copy into role management corresponding name need to be adjusted to roleXXX
Fifth: redundant methods need to be deleted one by one
Sixth: there is a serious problem, is that after copying, people often forget to change the above points, resulting in less readable code.
Feng Xiaonan combined with their actual writing code is really such a problem, can not help but feel CV method in the replication of the whole module, is really not very convenient and fast, how to solve it? Wind xiaonan heart of doubt.
“Do your research in the next couple of days and see if there are more effective solutions in the industry. Try it first, and we can communicate with you at any time if there is any problem. (Voice over, please report any progress and problems in a timely manner.)”
With that, the tech manager turned and walked away.
Ah, the story is not well written, so let’s take a look at the core needs expressed to the OK.
2. Preliminary exploration
Research new technology that’s small wind like most things, there is no clear direction, just before his also have no experience in this field, this time can indicate the path to the oneself is elder or search engine, as a love for technology of small wind, that must be his first search research, in the short term, not the results under the consult predecessors. In general, the principle is, don’t delay the company, as long as the task is completed on time.
Open a search engine, how to search? Wind xiaonan found dont know what keywords to input to find what you want, have to determine the keywords first. Since this is a code copy problem, assuming there is a tool or solution for it, it should be called “code XX”.
Since it’s all about efficiency, let’s do a search for “code efficiency.” Part of the screenshot shows the results below
After a brief review of the content, I found that it is related to code tuning to speed up the execution efficiency, not to improve the efficiency of code development, then the keyword is wrong, and should be adjusted.
Feng xiaonan thought again, code copy tools? Code copying tools? Think about it should be wrong, but still tried a wave, did not find the desired results.
Efficiency is about speed. How about “rapid code development”? Try it again. The search results are as follows
A list of rapid development platforms appeared, and the word “code generation” appeared frequently. Feng had a hunch that this was the key word he wanted but didn’t know how to express it. Feng added that since the company uses Java, the search for “Java code generation” would be more accurate. At this point, the keyword is “Java code generation.”
Operation excited trembling hands, in the search engine type “Java code generation”, click search.
Wind opens at xiaonangou couldn’t wait a few roughly browse the content, then adjusted the keyword a few times, “Java code generation tool” and “Java code generator” searches after a wave of information, see the relevant implementation approach, can not help but big “isn’t that what we need, autonomous generating, template customization, one pace reachs the designated position”. What change quantity name, renaming, remarks all do not exist, wind xiaonan heart roughly spectrum.
There are roughly two ways to achieve this, one with the help of the existing code generation platform, and the other with the help of template engine technology. Here, there is the determination of technical direction, which needs to report to the leader.
Wind xiaonan will look up the information and their own understanding into a document, sent to the technical manager (active timely communication, reporting is very important), and to the technical manager’s station for a brief report, the technical manager listened to and roughly browse the wind xiaonan sorted out the information, said:
Doing well, our company has its own research and development platform, code generation tool is best can directly with platform integration, let’s now I saw the ready-made code generation tool of za integration platform is bad now, but too many functions, use of technical standards is different also, we implement a simple set of yourself, to solve the problem of the core line, need not too complex. I’ll leave it to you.
Feng Xiaonan heard this, that happy ah. Is there anything more fun than having a code? Yeah, that’s the code that masturbation can’t do. Ha ha.
So far, the preliminary exploration of the prophase program was completed.
In the exploration stage, it is often difficult to control the work, because the exploration must be unknown areas and unknown problems, the task itself is not specific, we do not know what the final outcome will be, and the time cycle may be long. At this time, we need to pay attention to the way of work. The point is to communicate and report progress in a timely manner.
3. Work assignment
I have the task and the general goal, but it is not specific enough. In order to prevent the final product from being different from what the technical manager wants, I will sort out the content of the conversation just now and form a clear work goal, and then confirm with the manager to reach an agreement before starting.
The goal is basically clear, what technology to use, the leader said that it should be easy to integrate into the company’s development platform, that is, it should be consistent with the company’s existing technical framework, consistent with the specification, oh yes, it also mentioned that it should be easy to use. Hence the following.
Code generation tool task book
Work objectives: (1) Solve the problem of low efficiency of current code copy and replication by core; (2) Realize a set of code generation tools through independent research and development, which can be integrated with the company platform
Technical selection (1) Springboot (2) Thymeleaf
Usage mode (1) Use the command line interface (CLI) without relying on web services
Wind xiaonan sorted out the brief work objectives document, sent to the technical manager, after a while, the technical manager replied to come over, add a few work objectives.
Work objectives: (1) Solve the problem of low efficiency of current code copy and replication by core; (2) realize a set of code generation tools through independent research and development, which can be integrated with the company platform; (3) It is easy to expand when adding new code templates; (4) It can be generated on demand, such as only generating Controller files. Instead of having to generate full module code
So far, working target has been determined, come down is concrete work.
When the leader is very busy, if we do not help you sort out specific tasks, we need to learn to sort ourselves and find the leader to confirm. This is also a process to help myself gradually accumulate. In the future, these routines can be reused and extended by myself to lead people and teams. They are object-oriented, on the other hand, they can also help leaders relieve pressure. Leaders don’t hate such employees.
5. Technical design
Originally wind xiaonan want to be good how to achieve, soon can make, but the technical manager added two requirements, let this thing become not so simple, also need to analyze, good design at a time.
Core schematic
Since this is the case, it is still the general principle of the first picture out, this is the core of the implementation of the idea, wind xiaonan roughly drew such a map.
With this core principle, it is necessary to develop the design based on this structure to meet the following two requirements.
(3) Easy to expand when adding new code templates (4) can be generated on demand, for example, you can only generate Controller files instead of having to generate full module code
Feng Xiaonan read these two requirements, came to a conclusion: in fact, what (3) said is to meet the open and closed principle, (4) is that the program should be able to freely combine the generation mode, support personalized customization.
The class diagram design
First of all, you need to design basic class diagrams and relationships. How do you do that? Without previous experience in this aspect, it is obviously impossible to reach the goal in one step, so we have to break down the steps step by step, analyze the above schematic diagram, first do not consider the relationship between classes, list all the classes we can think of, that is, exhaustive method, and then gradually optimize and adjust, this is the first step.
If you do a lot of work, you may not need to do exhaustive work with certain experience. Exhaustive work is suitable for situations where you don’t have good ideas or don’t know how to start. It is equivalent to looking for inspiration and methods in the process of work and gradually bringing your own thinking into the scene.
To read table metadata, for example, the process need to be able to read the table metadata, whether need a database connection class, need link configuration files, whether you need reading configuration class, read back where to put the table of metadata, also need table information and field information of class, regardless of reasonable unreasonable, listed first. And so on, and so on.
Just a little bit about metadata what is metadata? The data that describes the data is called metadata. Let’s take a simple example. Let’s say we have a User table, User, and we have two fields, id(int) name(String). The data that describes the User table and the field information is called metadata
The data on the left represents information about the User table on the right, such as the name, type, storage engine, version, etc. The data that represents the User table information is called the User table metadata. The same goes for fields, and the data that describes the field name, field type, field length, and so on is the metadata of a field.
Take Mysql as an example. After the Mysql database is created, there is a Schema called information_schema. This database is the Mysql metadata database, storing metadata information of some Mysql database instances, tables, fields, indexes, etc. Tables and Columns contain metadata for Tables and Columns.
Based on the core principles of the code generation tool process, Feng xiaonan came up with the following list of classes he could think of
The name of the class | use | Step process |
---|---|---|
Table | Table Metadata information | Reading metadata |
Column | Field metadata information | Reading metadata |
DbConnection | Getting database links | Reading metadata |
YamlRead | Read the YAML configuration | Reading metadata |
CodeTemplate | Template file | Reading Template Information |
Command | Generation command | The generated code |
TypeMapping | Database and Java type mapping classes | The generated code |
GenCode | Code generation | The generated code |
CodeOutput | Code output | The output |
GenCodeRunner | An entry class used by developers | Is up and running |
With the basic checklist in hand, the UML tool was used for the specific design. Feng xiaonan’s company uses PowerDesign for all its designs.
The class diagram).
Feng Xiaonan thinks that since it is the first edition, it must be to outline the big boundary and basic relationship first, to lock the boundary and find out the key elements. Basically, it is to draw the classes listed above and mark the simple relationship, so there is the following picture
The class diagram version 0.1
The basic prototype is available, and the following is to gradually think about each process of the prototype, fill in the attributes and methods of the class, check whether there is omission, and adjust the unreasonable design. The adjustment is as follows
GenCodeRunner has only one method, which is run. Run internally calls the GenCode object. Why GenCodeRunner is needed? The command line of control that part of the logic should be stripped away, with the core business, after all, behind may change to use other means, such as HTTP, GUI, etc are likely, if written in the core business logic, then it’s not convenient to replace the use way, so provide an independent run classes to receive input from the user and user interaction is necessary.
2, MetaData this class in the previous initial version of the analysis, and not, add this class is that GenCode does not need to know the details of the database, for GenCode it needs only MetaData, how to chain the database how to read the configuration, it should not care, so these things to the MetaData.
3. A class attribute has been added to the two classes of Table and Column, className has been added to Table and attrName has been added to Column. In most cases, the database naming standard is underlined, such as user_id, while the className is humped, such as userId. So in order to generate code in a template expression simple enough, do not deal with any logic, template expressions can also do this conversion, but template should do the template’s job, which is to display the data, so the user_id -> userId process in MetaData. Properties that conform to the class and attribute naming conventions are provided, respectively.
It is supposed to be separate and define classes and attribute information separately, but it is not considered to leave too much expandable space here. In order to avoid introducing too many classes, which will lead to complex design, it is merged into one class.
The class diagram version 0.2
After 0.1 version of the design, wind xiaonan feel the overall structure is basically clear, down is the need to find the middle of the point of change, there may be changes in the place of abstraction, so that you can avoid code modification or new internal adjustment. Close to modification, open to new, open closed principle. Meet the technical manager’s requirement number 3.
After analysis, Feng Xiaonan found that according to the actual situation of the current company, the main possible changes are that the template may be adjusted at any time, which will lead to the change of GenCodeRunner class, which will cause the adjustment of Command class. Another is the output mode after the code generation, which may be output to the file. In the future, if you want to output to the database, the command line is not impossible. After the above thinking, wind xiaonan on the above mentioned several parts of the content of the abstract design, formed the following figure.
The Command interface is designed to provide different generation commands for different templates, and can provide combined generation commands, that is, generate all the code of the module at once.
Codeout is adapted as an interface, providing different implementation classes for different output forms.
CodeTemplate is designed as a base class that provides different extended subclasses for different template files.
In such a way that GenCode core classes operate on interfaces or base classes, this layer can be basically stable, regardless of how the implementation layer changes, the layer is not affected.
The class diagram version 0.3
The overall structure has been formed, but Feng Xiaonan suddenly found that the position of the Command class seems to be inappropriate. The Command should be triggered by the user, not GenCode, so how the user triggers, the only entry is GenCodeRunner, so, Is Command more appropriate for GenCodeRunner? Feng repositioned the Command class again.
Command can be a single generated Command. Multiple generated commands can be combined to form a single Command, which meets the 4th requirement of the technical manager. The program should be able to freely combine the generation mode and support personalized customization. The final result is shown below.
Several key points of design:
GenCodeRunner will instantiate the corresponding Command object based on the input of the user and call the Gen method of GenCode.
The gen method in GenCode has no input parameters. After adjustment, the Gen method receives a generation command for specific code generation.
The class diagram version 0.4
The class relationships are all in order, but there is one thing missing. Feng suddenly realized that a class like TypeMapping, if the initial default values do not meet the requirements, should allow users to define their own.
Is currently the only TypeMapping a, can let the user directly through the method to extend the custom, there may be other configuration items, but behind these configuration interface were thrown to the user, user use complexity does not increase, so many configuration interface which remember him, so provide a global configuration entry class or very be necessary, Any level of configuration customization can be achieved through this configuration class. The user only needs to remember the global configuration class.
Call it GenCodeConfiguration, add members to the class diagram, and the final complete design is as follows.
Completion of the design
At this point, the design work is finished, the following can be implemented according to the class diagram design, maybe you feel so simple, so many classes, tired or not tired, I can fix two or three classes, yes, can fix, but decoupled, extensible, easy to maintain, how to achieve each process can be replaced? This requires more interfaces, abstract classes, object-oriented design ideas, the application of design patterns to achieve. In fact, the above class design could be more complex, but our current needs are so much, the current design is sufficient.
So, does it feel like why Spring is so complicated? Some open source frameworks may implement functions that are very simple, why there are so many interfaces, abstract classes, the purpose is to decouple, extensible, easy to maintain, internal implementation can be customized replacement.
Maybe you still feel that there is no need, then you have to think like this, not from these small tools, code to a little bit to hone their programming thinking, deepen the understanding of object-oriented design, then when to practice, without the previous small accumulation, you can step to achieve a Mybatis? Therefore, it is possible to design a more perfect and better tool or framework only by practicing small scenes and making breakthroughs.
6. Implementation process
The core principle is clear, the design has, for Feng Xiaonan the rest of the coding is the easiest thing. Of course, for the young people who just entered the line, there may be some obstacles to the realization of this obstacle is mainly to see less, write less, pure code writing ability is not able to easily, lack of code experience. The solution is to practice with your brain.
Need to note is that the design is not the final version, because of the specific implementation process may also find some design consider the content of less than, so the design and implementation is a perfect process promote each other, after all, don’t begin, not to be considered in some detail, what’s more, the author is not ready in advance to write, but to try to restore the real process, Side realization, side output article.
The first thing the code implementation does is define the project package structure. It’s really about categorizing the classes in your design and building code packages. After analysis, the package structure is basically formed as follows
GenCodeRunner
Command line interaction class, the core function is to initialize the global configuration and GenCode, another function is to receive user input, through interaction to determine the user needs to generate code command and output mode. The key code is as follows.
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\n"); GenCodeConfiguration uration = new GenCodeConfiguration(); GenCode genCode = new GenCode(genCodeConfiguration); // Control the user interactioncommand= this.selectCommand(genCodeConfiguration,scanner); CodeOutput output = this.selectOutput(genCodeConfiguration,scanner); String tableName = this.selectTableName(scanner); / / generates the Console. The log ("\n");
Console.log("Start generating....");
genCode.process(tableName,command,output);
Console.log("Build complete....");
Copy the code
GenCode
Core class, coordinate the relevant parameters required by various resources to obtain commands, call Command to perform code generation. The core code is as follows.
public void process(String tableName,Command command,CodeOutput codeOutput){
Table tableInfo = MetaData.getTableInfo(tableName,configuration.getTypeMapping());
command.execute(tableInfo,springTemplateEngine,codeOutput);
}
Copy the code
There is a slight difference between the implementation here and the design. In the design, the template is obtained in GenCode, but in the actual implementation, it is found that it is more appropriate to put it in Command.
command
Command package, used to achieve a variety of code generation implementation, look at the whole package class diagram structure
Look at the core code of a single command
public class GenControllerCommand extends SingleCommand {
public GenControllerCommand() {
this.commandName = "Controller build command";
this.commandCode = "01"; this.template = new ControllerCodeTemplate(); } @override public void process(Table Table, Map Map) {Override public void process(Table Table, Map Map) {Copy the code
Define the command name, named code (corresponding to the command code used for interactive input with the user), and bind the corresponding code generation template. The function of process function is reserved to provide users with secondary processing of data or other necessary logic before generating specific code. The Command package uses a combination of command patterns and template methods.
Take a look at the core code of the combination command
/ / from GenControllerAndEntityCommand publicGenControllerAndEntityCommand() {
this.commandName = "Controller & Entity generate command";
this.commandCode = "3"; singleCommands.add(new GenControllerCommand()); singleCommands.add(new GenEntityCommand()); } @override public void execute(Table Table, SpringTemplateEngine SpringTemplateEngine, CodeOutput codeOutput){for(SingleCommand singleCommand : singleCommands){ singleCommand.execute(table,springTemplateEngine,codeOutput); }}Copy the code
A combined command is a collection of multiple single commands. The execution process is to iterate through the execution methods of each single command one by one and completely reuse the single command.
configuration
Global configuration class, which provides default parameter configuration and user-defined extension configuration. It mainly completes command registration configuration, output type registration configuration, database and Java type mapping configuration.
All configuration entries are in the GenCodeConfiguration uration, so unified entries can be easily invoked to reduce the user’s memory burden. Centralized control can also be achieved within the framework.
db
This package is relatively simple, encapsulating the process of database connection acquisition, mainly contains a configuration class and a connection acquisition class, relatively simple, will not expand the description here.
exception
A uniform exception class GenCodeException is defined for code generation modules. Exceptions of code generation modules are wrapped as this exception.
meta
Data Table and field metadata acquisition package, the main processing logic is to read the database metadata packaged as Java corresponding Table and TableColumn objects.
// Table metadata Statement STMT = conn.createstatement (); String sql ="select table_comment from information_schema.tables where table_name = '"+ tableName + "'";
ResultSet tableResultSet = stmt.executeQuery(sql);
while (tableResultSet.next()) {
table.setComment(tableResultSet.getString("table_comment"));
break; } // DatabaseMetaData metaData = conn.getMetadata (); ResultSet resultSet = metaData.getColumns(null, null, table.getCode(),"%");
List<TableColumn> tableColumnList = CollectionUtil.newArrayList();
while (resultSet.next()) {
TableColumn tableColumn = new TableColumn();
tableColumn.setCode(resultSet.getString("column_name").toLowerCase());
tableColumn.setType(typeMapping.getJavaType(resultSet.getString("type_name")));
tableColumn.setComment(resultSet.getString("remarks"));
tableColumnList.add(tableColumn);
}
table.setColumnList(tableColumnList);
Copy the code
output
The output package mainly realizes the output form of the final generated code. At present, the console output and file output are realized. See the class structure.
consoleOutpute@override public void out(Table Table, String content, CodeTemplate template) {console.log (consoleoutpute@override public void out(Table Table, String content, CodeTemplate template) {console.log ("\n");
Console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
Console.log(content);
Console.log("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -"); } public void out(Table Table, String content, CodeTemplate template) {String fileName ="dist/" + table.getClassName() + template.getFileTag() + template.getFileSuffix();
File file = new File(fileName);
FileUtil.writeBytes(content.getBytes(),file);
Console.log("File Location :" + file.getAbsolutePath());
}
Copy the code
template
The template definition class of generated code, with no additional logical control, is the definition of template properties and corresponding attributes of the template to the final generated file.
public ControllerCodeTemplate() {
this.tplName = "Controller Template";
this.tplPath = "templates/Controller.tpl";
this.fileTag = "Controller";
this.fileSuffix = ".java";
}
Copy the code
tpl
For the template file, use thymeleaf’s text mode. Look at the simple template content
/ [* * * (${comment})]- entity * * @author yuboon * @version v1.0 * @date [(${createDate})]
*/
@Data
public class [(${className})] implements Serializable {
[# th:each="column : ${columnList}"]/ * * [(${column.comment})] */
@Column("[(${column.code})],")
private [(${column.type})] [(${column.attrName})]; / /}Copy the code
7. Use experience
Command line interaction mode
Custom call
public class GenCodeTest {
public static void main(String[] args) {
GenCodeConfiguration genCodeConfiguration = new GenCodeConfiguration();
GenCode genCode = new GenCode(genCodeConfiguration);
genCode.process("sys_user",new GenVoCommand(),new ConsoleOutput()); }}Copy the code
Based on this structure, it is easy to transform to GUI mode to obtain Web pages.
Extend a new template
It’s easy to define a new Command, a new Tpl template file, a CodeTemplate template definition file, and register the new Command through global configuration without changing any of the existing code.
8, summary
At this point, a simple code generation tool in the hands of feng Xiaonan.
Is there room for improvement? Of course there are. For example, can template engines be replaced at will? What if there are multiple versions of the code template file? Web end implementation, multi-module generation at the same time and so on.
In this paper, the core functions of the code generation tool as a case, from the requirements to the final implementation, a more detailed description of the work process and some work methods including some ideas and ideas of the design program.
Then you have a small tool need completely according to the steps above to you, it’s not, the more experienced, see more, this process can be simplified, some steps in their mind there is a thinking process, can even begin to write code directly, don’t have to like this, step by step is so complex, the article is to describe the whole process, So write more detailed, just look complicated on the surface.
Finally, some key points from the article are distilled: (3) It is very important to search for keywords. (3) Design first, thinking is more important than implementation. (4) When I don’t know how to do it, I will try it out in a specific scene. Step by step iterative implementation (6) Summary, ask why to do? What to do? How to do? Space for subsequent evolution?
9. Complete code address
Github.com/yuboon/java…
10, eggs
I believe that many students can not stick to the content of the article, and the content of the article can not fully reflect the overall design idea and implementation process, so I recorded a video for the implementation part, followed the public account at the end of the article, reply [Gencode] to get the explanation video.
More wonderful
You think it’s okay. Give it a thumbs up. That’s all for today, and I’ll see you next time. More quality content, the first public number [wind elephant south], welcome to pay attention to.