Write documentation

As a developer, everyone has to write code.

At work, almost every developer has to write documentation.

Because work is a collaboration between people, requirements documents must be written for products, detailed design documents and interface documents must be written for development.

However, as a lazy person, one of the most annoying things is writing documents.

在这里插入图片描述

The most uncomfortable part of writing the document is that the code remarks need to be changed again, and then the document is changed again.

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

So, I often think, can I just write it once?

i-doc project introduction

idoc generates project documentation for java projects.

Based on native java annotations, generate brief documentation as much as possible. Users can customize their own templates to generate the documents they need.

Implementation principle: based on maven plug-in, similar to javadoc. Can be more flexible, allowing user customization.

characteristic

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

(2) Support markdown by default to simplify document generation and support custom templates

(3) Support user-defined document generator

(4) Support user-defined class filters for generating documents

(5) Add field type aliases, support user customization

Quick start

need

jdk1.8+

maven 3.x+

Introduced by maven

Use maven to import the current idoc plugin.

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

Creation of test objects

To demonstrate the document, we created an Address object.

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

/**
 * 地址
 * @author binbin.hou
 * @since 0.0.1
 */
public class Address {

    /**
     * 城市
     */
    private String country;

    /**
     * 街道
     */
    private String street;

    public String getCountry() {
        return country;
    }

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

    public String getStreet() {
        return street;
    }

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

Execution plugin

mvn com.github.houbb:idoc-core:0.3.0:idoc

Command line log information

[INFO] ------------------------------------ Start generate doc
[INFO] 共计 【1】 个文件待处理,请耐心等待。进度如下:
==================================================================================================== 100%
[INFO] Generator doc with docGenerator: com.github.houbb.idoc.core.api.generator.ConsoleDocGenerator
[INFO] ------------------------------------ 文档信息如下:

[类名] com.github.houbb.idoc.test.model.Address
[类信息] {"comment":"地址","docAnnotationList":[],"docFieldList":[{"comment":"城市","name":"country","type":"java.lang.String"},{"comment":"街道","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":["public"],"name":"setCountry","seeList":[],"signature":"setCountry(country)"},{"docMethodParameterList":[],"docMethodReturn":{"fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"getStreet","seeList":[],"signature":"getStreet()"},{"docMethodParameterList":[{"docAnnotationList":[],"name":"street","type":"java.lang.String"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"setStreet","seeList":[],"signature":"setStreet(street)"}],"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.github.houbb.idoc.test.model.Address","modifiers":["public"],"name":"Address","packageName":"com.github.houbb.idoc.test.model"}

[INFO] ------------------------------------ Finish generate doc

More ways to generate

Of course, you can find that this is just outputting metadata to the console, which is of little significance.

We can customize the implementation of the generated class according to the needs.

For example, in the following way, you can use the built-in MarkdownDocGenerator output to a markdown file.

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

The effect can refer to:

heaven Document directory

ps: heaven The has been organized by individuals for many years. There are hundreds of categories and handwritten documents are estimated to take a long time.

Original design intention

save time

Java documentation has always been a big issue.

Many projects do not write documentation, and even writing documentation is very painful for developers.

The disadvantages of not writing documents are not much, and the disadvantages of manually writing documents are also obvious:

  1. It's a waste of time and can make mistakes.
  2. There is no guarantee of timely updates. The code has changed, but the document needs to be modified simultaneously. Need to force people to maintain this kind of consistency. This is difficult.

Why not swagger-ui

There are several types of java documentation:

  1. Jdk comes with doc generation. This practice has been used by others before, and others use C#, and it feels painful to see the default documentation of java.

Even if we are java developers, we hate to read the jdk documentation. It looks unattractive and very tired.

  1. swagger-ui is a document generation tool based on java annotations. Relatively speaking, it is elegant and very powerful.

But there are also disadvantages. Developers need to write jdk original comments + annotations. Too many comments made it painful to write, and most developers later chose to give up.

So the question is coming? What can we do to make developers and document readers as happy as possible?

The doc that comes with jdk is based on the maven plug-in, as is this project.

The differences are as follows:

  1. As much as possible to ensure that it is consistent with Java's native annotations, so that developers can use them easily.
  2. The information is as comprehensive as possible, but the document is concise. Let the readers of the document enjoy an experience equivalent to that of a handwritten document.
  3. Separate the acquisition and generation of information. It is convenient for users to define their own output methods.

Parameter configuration description

In order to achieve more flexible document generation and document metadata generation, the following parameters are provided

Introduction to plugin configuration properties

AttributesIs it requiredillustrateDefaultsRemark
encodingnoProject codeUTF-8
includesnoFile information contained in metadata**\/*.javaScan all java files by default
excludesnoFile information excluded by metadatawithoutNot excluded by default
isOverwriteWhenExistsnoWhether to overwrite when the document existstrue
isAllInOnenoWhether to generate a single document for all types of informationtrueCommand line document generator, this attribute is meaningless.
generatesnoDocument generation classCommand line documentation generation informationYou can specify multiple at the same time. The full name of the class. User-defined see com.github.houbb.idoc.api.core.genenrator.IDocGenerator
generateFiltersnoDocument generation filterwithoutYou can specify multiple at the same time. The full name of the class. User-defined see com.github.houbb.idoc.api.core.filter.IDocGenerateFilter
targetDirnoGenerate target file directorywithoutCustomize the folder generated by the specified document

isAllInOne

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

If it is more complicated, you can set it to false, and it will follow

generates related questions

The default command line document is mainly used for demonstration and information viewing, and has no practical significance.

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

You can specify multiple at the same time.

You can introduce idoc-api define yourself.

generateFilters suggestions

The actual documentation is mainly concerned with the defined method.

We can filter the package name of DocClass to generate only Service method documents.

If it is based on the previous, you can add @since @version and other information filtering.

You can specify multiple at the same time.

You can introduce idoc-api define yourself.

Custom Filter

You can 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>

Specify the document generator

Specify the Markdown document generator, you can specify multiple at the same time.

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

Import package

MarkdownDocGenerator needs to introduce the corresponding dependency in the idoc-ftl

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

Specify the filter of the file generation class

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

In general use, we only care about the service method, so the filter implementation of the class is added.

The implementation is as follows:

Introduce idoc-api package

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

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;

/**
 * 自定义生成过滤器
 * @author binbin.hou
 * @since 0.0.1
 */
public class MyGenerateFilter implements IDocGenerateFilter {

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

}

Configuration and use in the plug-in

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

Note that you also need to add dependencies to the jar where you define this filter, otherwise the corresponding class information cannot be found.

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

Class code information

User information

/**
 * 用户信息
 * @author binbin.hou
 * @since 0.0.1
 */
public class User {

    /**
     * 名称
     * @require 是
     * @remark 中文名称,请认真填写
     */
    private String name;

    /**
     * 年龄
     */
    private int age;

    /**
     * 生日
     */
    private Date birthday;

    /**
     * 地址
     */
    private List<Address> addressList;

    /**
     * 伴侣
     */
    private User mate;
    
    //...
}

Tags defined by i-doc

@require indicates whether the current field is required, when it is used as a method to enter the parameter.

@remark represents the remark information of the current field.

Method class information

  • QueryUserService.java
/**
 * 查询用户服务类
 * @author binbin.hou
 * @since 0.0.1
 */
public interface QueryUserService {

    /**
     * 根据用户信息查询用户
     * @param user 用户信息
     * @return 结果
     * @since 0.0.2,2019/02/12
     */
    public User queryUser(final User user);

}

Execution plugin

mvn com.github.houbb:idoc-core:0.3.0:idoc
  • Log information
[INFO] ------------------------------------ Start generate doc
[INFO] 共计 【4】 个文件待处理,请耐心等待。进度如下:
==================================================================================================== 100%
[INFO] Generator doc with docGenerator: com.github.houbb.idoc.ftl.api.generator.MarkdownDocGenerator
[INFO] Markdown 生成文档文件 all in one 路径: /Users/houbinbin/code/_github/idoc/idoc-test/src/main/resources/idoc-gen/idoc-test-全部文档.md
[INFO] ------------------------------------ Finish generate doc

Document information

The current file path log will be printed. For example, what I tested myself is:

/Users/houbinbin/code/_github/idoc/idoc-test/src/main/resources/idoc-gen/idoc-test-all documents.md

Document generation effect

See documentation:

idoc-test-all documents.md

Field type alias support

You can refer to the idoc-test module of the current project.

Why need

Sometimes the page display type, hoping to be more friendly.

Therefore, the system has built-in alias display, and also supports custom aliases.

Alias of type field

Built-in system

The current version of the system provides common aliases.

See com.github.houbb.idoc.core.util.JavaTypeAliasUtil

typenickname
java.lang.FloatFloating point
java.lang.DoubleFloating point
java.util.Datedate
java.time.LocalDateTimeDate time
java.util.Currencycurrency
floatFloating point
java.lang.IntegerInteger
longLong integer
java.math.BigDecimalnumber
java.lang.Charactercharacter
java.lang.LongLong integer
java.lang.ShortShort integer
java.util.MapMapping
java.time.LocalTimetime
java.lang.BooleanBoolean value
java.math.BigIntegernumber
java.lang.StringString
java.lang.Bytebyte
doubleFloating point
bytebyte
java.util.Collectiongather
intInteger
java.util.ListList
booleanBoolean value
java.time.LocalDatedate
charcharacter
shortShort integer
voidnull
arrayArray

Custom way

You can specify a custom field alias through 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自定义说明</value>
        </typeAlias>
    </typeAliases>
</configuration>

priority

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

The aliases defined later will directly override the previous aliases.

Test code demo

Object definition

/**
 * 别名测试
 * @author binbin.hou
 * @since 0.0.1
 */
public class TypeAliasSimpleBean {

    /**
     * 名称
     */
    private String name;

    public String getName() {
        return name;
    }

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

Test log

The running test log is as follows:

{"comment":"别名测试","docAnnotationList":[],"docFieldList":[{"comment":"名称","name":"name","type":"java.lang.String","typeAlias":"String自定义说明"}],"docMethodList":[{"docMethodParameterList":[],"docMethodReturn":{"fullName":"java.lang.String","name":"String","packageName":"java.lang"},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"getName","seeList":[],"signature":"getName()"},{"docMethodParameterList":[{"docAnnotationList":[],"name":"name","type":"java.lang.String","typeAlias":"String自定义说明"}],"docMethodReturn":{},"docTagList":[],"exceptionList":[],"modifiers":["public"],"name":"setName","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.github.houbb.idoc.test.model.TypeAliasSimpleBean","modifiers":["public"],"name":"TypeAliasSimpleBean","packageName":"com.github.houbb.idoc.test.model"}

Among them, typeAlias is the alias of the field type, we can use it to display field information more friendly.

Other thinking

Convenience of customization

The custom way is more convenient to use the xml-based way.

However, it is not so convenient when the number is relatively large. Originally, I considered adding the corresponding configuration attribute interface, but I still used the xml configuration method under the trade-off.

Do you use comment information?

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

It is recommended to use, the current version will not be processed.

  • Why use

Most people are more willing to see explanations than lengthy information.

If it is for a homogeneous system (all java language), you can understand.

If it is for a heterogeneous system (for example, the front desk is PHP), it is not easy to understand.

  • Why not deal with

Most of the interfaces are common fields, and the price/performance ratio is not high.

There may be situations where the field does not have some comments, which will cause the complexity of the judgment.

If the user does not want to use an alias

type modify the template directly, just use the original field 0616d5ac7b7d83 attribute.

Open source address

https://github.com/houbb/idoc

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

If you like, welcome to fork star~

在这里插入图片描述


老马啸西风
191 声望34 粉丝