Written document

As a developer, everyone has to write code.

At work, almost every developer has to document.

Because work is a collaboration of people and people, product needs to write requirements documents, development needs to write detailed design documents, interface documents.

However, as a lazy person, usually the most annoying thing is to write documents.

The thing that annoys me most about documentation is that the code comments have to be changed once, and then the documentation has to be changed again.

All that repetitive work is the biggest waste of our precious fishing time.

So I often wondered, could I just write it once?

An introduction to the I-DOC project

Idoc generates project documentation for Java projects.

Generate as brief a document as possible, based on native Java annotations. Users can customize their own templates to generate their own required documents.

Implementation principle: Based on Maven plug-in, similar to Javadoc. Can be more flexible, allowing users to customize.

features

(1) Generate metadata containing most of the information based on Maven project

(2) By default, markDown is supported to simplify the generation of documents, and custom templates are supported

(3) Support user – defined document generator

(4) Support user – defined generated document class filter

(5) Add field type alias to support user customization

Quick start

Need to be

Jdk1.8 +

maven 3.x+

Maven is introduced into

Import the current IDOC plug-in using Maven.

<build>
    <plugins>
        <plugin>
            <groupId>com.github.houbb</groupId>
            <artifactId>idoc-core</artifactId>
            <version>0.3.0</version>
        </plugin>
    </plugins>
</build>
Copy the code

Test object creation

To illustrate the document, we create an Address object.

package com.github.houbb.idoc.test.model;

/** * address *@author binbin.hou
 * @since0.0.1 * /
public class Address {

    /** * city */
    private String country;

    /** * street */
    private String street;

    public String getCountry(a) {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getStreet(a) {
        return street;
    }

    public void setStreet(String street) {
        this.street = street; }}Copy the code

Perform the plugin

MVN com. Making. Houbb: idoc - core: 0.3.0: idocCopy the code

Command line logs

[the INFO] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Start the generate doc [INFO] a total of [1] a file to be processed, please be patient. The schedule is as follows:  ==================================================================================================== 100% [INFO] Generator doc with docGenerator: Com. Making. Houbb. Idoc. Core. API. The generator. The ConsoleDocGenerator [INFO] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - document information is as follows: [class] com. Making. Houbb. Idoc. Test. The model. The Address [information] {" comment ":" address ", "docAnnotationList" : [], "docFieldList" : [{" comment ":" city ", "name" : "country", "type" : "Java. Lang. String"}, {" com Ment ":" street ", "name" : "street", "type" : "Java. Lang. String}]," "docMethodList" : [{" docMethodParameterList ": []," docMethodReturn ": { "fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers": ["public"],"name":"getCountry","seeList":[],"signature":"getCountry()"},{"docMethodParameterList":[{"docAnnotationList": [],"name":"country","type":"java.lang.String"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["pu blic"],"name":"setCountry","seeList":[],"signature":"setCountry(country)"},{"docMethodParameterList":[],"docMethodReturn ":{"fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifier s":["public"],"name":"getStreet","seeList":[],"signature":"getStreet()"},{"docMethodParameterList":[{"docAnnotationList" :[],"name":"street","type":"java.lang.String"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["pu blic"],"name":"setStreet","seeList":[],"signature":"setStreet(street)"}],"docTagList":[{"lineNum":5,"name":"author","par Ameters: "[]" binbin. Hou ", "value" : "binbin. Hou"}, {" lineNum ": 6," name ":" since ", "parameters" : [" 0.0.1] ", "value" : "0.0.1}", "full Name":"com.github.houbb.idoc.test.model.Address","modifiers":["public"],"name":"Address","packageName":"com.github.houbb .idoc.test.model"} [INFO] ------------------------------------ Finish generate docCopy the code

More generation methods

Of course, you can see that this is just output metadata to the console, not meaningful.

We can customize the implementation to generate classes as required.

For example, you can use the built-in MarkdownDocGenerator to output markdown files.

<plugin>
    <groupId>com.github.houbb</groupId>
    <artifactId>idoc-core</artifactId>
    <version>0.3.0</version>
    <configuration>
        <generates>
            <generate>com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator</generate>
        </generates>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>com.github.houbb</groupId>
            <artifactId>idoc-ftl</artifactId>
            <version>0.3.0</version>
        </dependency>
    </dependencies>
</plugin>
Copy the code

The effect can be referred to:

Heaven Document Directory

Ps: Heaven project is a tool kit that I have been working on for years, with hundreds of classes and handwritten documents.

designed

To save time

Java documentation has always been a big problem.

Many projects don’t document, and when they do, it can be painful for developers.

The disadvantages of not writing documentation are not trivial, but the disadvantages of writing documentation manually are also obvious:

  1. It’s a waste of time, and it makes mistakes.

  2. Timely updates cannot be guaranteed. The code has changed, but the documentation needs to change at the same time. Enforcers are needed to maintain this consistency. It is difficult.

Why not Swagger-ui

There are several types of Java documentation:

  1. JDK built-in doc generation. This practice has been used before by others who use C# and find it painful to see the default documentation in Java.

Even we Java developers hate looking at JDK documentation. Look not beautiful, also very tired.

  1. Swagger-ui is a Document generation tool based on Java annotations. Relatively elegant and very powerful.

But there are drawbacks. Developers write the original JDK comments + annotations. There are so many annotations that it’s a pain to write, and most developers give up later.

So the question is, right? How can we make it as palatable as possible to both developers and document readers?

The DOC that comes with the JDK is based on the Maven plugin, as is this project.

The differences are as follows:

  1. Make it as consistent as possible with Java native annotations and easy for developers to use.

  2. Be as comprehensive as possible, but keep the documentation brief. Let the reader of the document enjoy the same experience as a handwritten document.

  3. Distinguish between the acquisition and generation of information. It is convenient for users to define their own output mode.

Parameter Configuration description

To achieve flexible document generation and document metadata generation, provide the following parameters

Introduction to plug-in configuration properties

attribute If required instructions The default value note
encoding no Project code UTF-8
includes no The metadata contains file information **\/*.java All Java files are scanned by default
excludes no Metadata excluded file information There is no Default not excluded
isOverwriteWhenExists no Whether to overwrite the document while it exists true
isAllInOne no Whether a single document is generated for all class information true Command line document generator, this property is meaningless.
generates no Document generation class Command line documentation generates information More than one can be specified simultaneously. Class name full name. User-defined see User-definedcom.github.houbb.idoc.api.core.genenrator.IDocGenerator
generateFilters no Document generation class filter There is no More than one can be specified simultaneously. Class name full name. User-defined see User-definedcom.github.houbb.idoc.api.core.filter.IDocGenerateFilter
targetDir no Generate the target file directory There is no Custom specifies the folder in which documents are generated

isAllInOne

Simple documents are recommended to be generated directly in a file.

If it is more complex, it can be set to false, and the

Issues related to generates

The default command line document is used for demonstration and information viewing.

It is recommended to introduce idoc-ftl module and use MarkdownDocGenerator.

More than one can be specified simultaneously.

Idoc-api can be introduced to define their own.

GenerateFilters advice

The actual documentation is primarily concerned with the methods defined.

We can filter only Service method documents for DocClass package names.

If it is on the previous basis, you can add information such as @since @version filtering.

More than one can be specified simultaneously.

Idoc-api can be introduced to define their own.

A custom Filter

Refer to the IDOC-test module of the current project.

The overall configuration is as follows:

<build>
    <plugins>
        <plugin>
            <groupId>com.github.houbb</groupId>
            <artifactId>idoc-core</artifactId>
            <version>0.3.0</version>
            <configuration>
                <isAllInOne>true</isAllInOne>
                <generates>
                    <generate>com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator</generate>
                </generates>
                <generateFilters>
                    <generateFilter>com.github.houbb.idoc.test.filter.MyGenerateFilter</generateFilter>
                </generateFilters>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>com.github.houbb</groupId>
                    <artifactId>idoc-test</artifactId>
                    <version>${project.version}</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
Copy the code

Specifying the document generator

Specifies the use of the Markdown document generator. You can specify more than one at a time.

<generates>
    <generate>com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator</generate>
</generates>
Copy the code

Introduction of package

MarkdownDocGenerator needs to introduce corresponding dependencies in idOC-FTL module.

Of course idoc-core depends on idoc-ftl by default.

Specifies the filter for the file generation class

If you do not define your own class generation filter, all class information will be generated.

In general, we only care about the Service method, so we added a filtering implementation of the class.

The implementation is as follows:

Introducing the idoc – API package

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>idoc-api</artifactId>
    <version>${project.version}</version>
</dependency>
Copy the code

Implement IDocGenerateFilter

package com.github.houbb.idoc.test.filter;

import com.github.houbb.idoc.api.core.filter.IDocGenerateFilter;
import com.github.houbb.idoc.api.model.metadata.DocClass;

/** * Custom generated filter *@author binbin.hou
 * @since0.0.1 * /
public class MyGenerateFilter implements IDocGenerateFilter {

    @Override
    public boolean include(DocClass docClass) {
        if("QueryUserService".equalsIgnoreCase(docClass.getName())) {
            return true;
        }
        return false; }}Copy the code

Plug-in configuration for use

<generateFilters>
    <generateFilter>com.github.houbb.idoc.test.filter.MyGenerateFilter</generateFilter>
</generateFilters>
Copy the code

Note that you also need to add a dependency to the JAR where you define the filter, otherwise the corresponding class information will not be found.

<dependencies>
    <dependency>
        <groupId>com.github.houbb</groupId>
        <artifactId>idoc-test</artifactId>
        <version>${project.version}</version>
    </dependency>
</dependencies>
Copy the code

Class code information

The User information

/** * User information *@author binbin.hou
 * @since0.0.1 * /
public class User {

    /** * name *@requireIs *@remarkChinese name, please fill in */ carefully
    private String name;

    /** * age */
    private int age;

    /** ** birthday */
    private Date birthday;

    /** * address */
    private List<Address> addressList;

    /** ** partner */
    private User mate;
    
    / /...
}
Copy the code

I-doc defined label

@require indicates whether the current field is required as a method parameter.

@remark Remark Information about the current field.

Method class information

  • QueryUserService.java
/** * Query user service class *@author binbin.hou
 * @since0.0.1 * /
public interface QueryUserService {

    /** * Query user * based on user information@paramUser User information *@returnResults *@sinceHundreds, 2019/02/12 * /
    public User queryUser(final User user);

}
Copy the code

Perform the plugin

MVN com. Making. Houbb: idoc - core: 0.3.0: idocCopy the code
  • Log information
[the INFO] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - Start the generate doc [INFO] a total of [4] a file to be processed, please be patient. The schedule is as follows:  ==================================================================================================== 100% [INFO] Generator doc with docGenerator: Com. Making. Houbb. Idoc. FTL. API. The generator. The MarkdownDocGenerator [INFO] Markdown document files all in one path: / Users/houbinbin/code / _github idoc/idoc - test/SRC/main/resources/idoc - gen/idoc - test - full documentation. Md/INFO ------------------------------------ Finish generate docCopy the code

Document information

The current file path log is printed, for example:

/ Users/houbinbin/code / _github idoc/idoc - test/SRC/main/resources/idoc - gen/idoc - test - full documentation. The md

Document generation effect

See documentation:

Idoc-test – all documentation. Md

Field type alias support

Refer to the IDOC-test module of the current project.

Why is it needed

Sometimes pages display type, hopefully more friendly.

So the system has some built-in alias display, but also supports custom alias.

Alias for the type field

The built-in

The current version of the system provides common aliases.

See com. Making. Houbb. Idoc. Core. Util. JavaTypeAliasUtil

type Nickname (s)
java.lang.Float floating-point
java.lang.Double floating-point
java.util.Date The date of
java.time.LocalDateTime Date/time
java.util.Currency currency
float floating-point
java.lang.Integer The integer
long Long integer
java.math.BigDecimal digital
java.lang.Character character
java.lang.Long Long integer
java.lang.Short Short integer
java.util.Map mapping
java.time.LocalTime time
java.lang.Boolean Boolean value
java.math.BigInteger digital
java.lang.String string
java.lang.Byte byte
double floating-point
byte byte
java.util.Collection A collection of
int The integer
java.util.List The list of
boolean Boolean value
java.time.LocalDate The date of
char character
short Short integer
void empty
array An array of

Custom mode

You can specify custom field nicknames via typeAlias.

<configuration>
    <generateFilters>
        <generateFilter>com.github.houbb.idoc.test.filter.MyGenerateFilter</generateFilter>
    </generateFilters>
    <isAllInOne>true</isAllInOne>
    <typeAliases>
        <typeAlias>
            <key>java.lang.String</key>
            <value>String Custom description</value>
        </typeAlias>
    </typeAliases>
</configuration>
Copy the code

priority

The user-defined field alias has a higher priority than the default value.

The aliases defined later directly override the previous aliases.

Test code demo

Object definitions

/** * Alias test *@author binbin.hou
 * @since0.0.1 * /
public class TypeAliasSimpleBean {

    /** * name */
    private String name;

    public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name; }}Copy the code

The test log

The run test log is as follows:

{" comment ":" alias test ", "docAnnotationList" : [], "docFieldList" : [{" comment ":" name ", "name" : "name", "type" : "Java. Lang. String", "typeAl Ias ":"String custom description "}],"docMethodList":[{"docMethodParameterList":[],"docMethodReturn":{"fullName":"java.lang.String","nam" e":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"getName","seeLi st":[],"signature":"getName()"},{"docMethodParameterList":[{"docAnnotationList":[],"name":"name","type":"java.lang.Strin G, "" typeAlias" : "String custom instructions"}], "docMethodReturn" : {}, "docTagList exceptionList" : [], "" : []," modifiers ": []" public ", "name" : "se tName","seeList":[],"signature":"setName(name)"}],"docTagList":[{"lineNum":5,"name":"author","parameters":["binbin.hou"] , "value" : "binbin. Hou"}, {" lineNum ": 6," name ":" since ", "parameters" : [" 0.0.1] ", "value" : "0.0.1}]," fullName: com. Making. Houbb .idoc.test.model.TypeAliasSimpleBean","modifiers":["public"],"name":"TypeAliasSimpleBean","packageName":"com.github.houb b.idoc.test.model"}Copy the code

Where typeAlias is the alias of the field type, we can use it to display the field information in a more friendly way.

Other thoughts

The convenience of customizing the approach

The custom approach is more convenient when using XML-based approaches.

However, when the number is large, it is not so convenient. I originally considered adding the corresponding configuration attribute interface, but I still used XML configuration after weighing.

Do you use comment information?

If a field does not have an alias, do you use comment information instead?

This parameter is recommended. This parameter is not processed in the current version.

  • Why use

Most people prefer explanations to lengthy class information.

If it’s for a homogeneous system (both in the Java language), it makes sense.

This is not easy to understand if you are working on a heterogeneous system (such as PHP in the foreground).

  • Why not?

Most of the interfaces are common fields with low cost performance.

There may be cases where the field does not have some comment, which leads to the complexity of judgment.

If the user does not want to use an alias

Modify the template directly, using the original field type attribute.

Open source address

github.com/houbb/idoc

Of course, the project still has a long way to go.

If you like, welcome to Fork Star ~