Blog: bugstack.cn

Precipitation, share, grow, let yourself and others can gain something! 😄

One, foreword

How to ensure code quality?

Business requirements, product planning, r & D to achieve, test and test process. The coordination of the four roles is necessary to ensure that a requirement comes online. In the overall requirement delivery quality level division, R & D and testing is a very important link, if the r & D proposed to test the code is not high quality, there will be different levels of BUG fixing, rework and even redo risk.

So how do you improve code quality? Developers are generally required to write unit tests to verify their code logic as they develop code. If the final unit test coverage is insufficient, it can be rejected by the test.

However, the code for the implementation of the whole requirement is proposed and tested after the completion of all development, which is the last link near the online, we can know whether the implementation of a certain functional domain of a research and development has the conditions for proposing and testing. If the code quality is not high at this time, then the project risk is next. Pressure test time, adjust the line time, in short, sick dragging the final disease!

Of course, you can check your code regularly during the development of the project, give progress feedback on a daily basis, and so on. However, it is difficult to meet the requirements of large-scale project development with complex process, and the project risk control is also unpredictable.

Therefore, we want to capture the implementation of r & D in the development process, risk judgment ahead of time. For example, when you develop an interface and start testing, our plug-in can collect all the information about the interface, including: interface name, input parameter type and content, output parameter type and content, exception information, call relationship chain, etc. And then submit the summary of these information to the server, generate all the interface actions under the branch of the requirement code, as well as the relationship between the links between the systems, and with the latest generation of interface documents and one-key test verification function. Later testers can refer to all test cases in the coding process and check the coverage of the whole function when they are involved. In addition, the data in the testing process of testers will also be retained. Now with these data information, we can completely generate a set of R & D test quality delivery overview chart, so that the whole project development delivery quality assessment transparency.

Next, we will develop a case experience in accordance with the above descriptive content. Start!

Two, technical implementation preparation

  1. Bytecode staking, because we need to collect interface execution information, we need to use bytecode staking components to enhance the interface method. This implementation is somewhat similar to Google’s Dapper, a large-scale distributed architecture for non-intrusion monitoring. It’s just that we need to collect more descriptive information. For bytecode staking, you can learn about ASM, Javassist, and byte-Buddy, which all do this work.
  2. IDEA plug-in development, because we need to collect in the development process of r&d personnel, and do not destroy the operation habits of research and development. So the best way to do that is embedIs up and runningAs long as there is an action of running code in the development process, the corresponding interface information will be collected.
  3. Finally, data transfer and processing can be done using MQ or directly using Netty. The process of data processing is relatively complex. In this process, valuable data should be analyzed, data of the same kind, data of an execution link should be combined, and related interface documents and engineering service maps should be generated.

Three, the bytecode staking

The bytecode staked component we use here is byte-Buddy, a code generation and manipulation library for creating and modifying Java classes at runtime without the help of a compiler. In addition to the code generation utility that comes with the Java class library, Byte Buddy allows you to create any class and is not limited to implementing an interface for creating run-time proxies. In addition, Byte Buddy provides a convenient API to use Java proxies or manually change classes during the build process.

  • It is easy to manipulate bytecode and control classes and methods using simple apis without understanding bytecode instructions.
  • Java 11 is supported, the library is lightweight and depends solely on the visitor API of ASM, the Java bytecode parser library, which itself does not require any additional dependencies.
  • Byte Buddy has some performance advantages over JDK dynamic proxies, Cglib, and Javassist.

1. Method entry

public static void premain(String agentArgs, Instrumentation inst) {
    AgentBuilder.Transformer transformer = (builder, typeDescription, classLoader, javaModule) -> {
        return builder
                .method(ElementMatchers.any()) // Intercept any method
                .intercept(MethodDelegation.to(MonitorMethod.class));
    };
    new AgentBuilder
            .Default()
            .type(ElementMatchers.nameStartsWith(agentArgs)) 
            .transform(transformer)
            .installOn(inst);
}
Copy the code

Premain is familiar to you if you have worked with Javaagent development. If you don’t know, you can think of it as a method entry when the program starts, and you can intercept the method you want from that entry and then bytecode enhance it. It’s basically writing code on the fly, adding your code to a method to collect method information.

2. Collect information

@RuntimeType
public static Object intercept(@Origin Method method, @SuperCallCallable<? > callable,@AllArguments Object[] args) throws Exception {
    long start = System.currentTimeMillis();
    Object resObj = null;
    try {
        resObj = callable.call();
        return resObj;
    } finally {
        System.out.println("Method name:" + method.getName());
        System.out.println("Input parameter number:" + method.getParameterCount());
        for (int i = 0; i < method.getParameterCount(); i++) {
            System.out.println("Input parameter Idx:" + (i + 1) + "Type:" + method.getParameterTypes()[i].getTypeName() + Content:" + args[i]);
        }
        System.out.println("Output parameter type:" + method.getReturnType().getName());
        System.out.println("Parameter result:" + resObj);
        System.out.println("Method time:" + (System.currentTimeMillis() - start) + "ms"); }}Copy the code

This is the information you can collect using byte-Buddy, and you can annotate the parameter to get all the information about a method. Method name, number of input parameters, input parameter type and content, output parameter type and result, and calculation of method execution time.

Iv. IDEA plug-in development

Knowledge about IDEA plug-in development content more, you can search some information out and refer to the official document: plugins.jetbrains.com/docs/intell…

Demo case here about the content of the plug-in development is simpler, mainly inherits com. Intellij. Execution. The impl. DefaultJavaProgramRunner, Override the doExecute method, add the content you need.

The core of this addition is to add our bytecode staking program when the program starts, as follows:

@Override
protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException {
    JavaParameters parameters = ((JavaCommandLine) state).getJavaParameters();
    // Get information
    PsiFile psiFile = env.getDataContext().getData(LangDataKeys.PSI_FILE);
    String packageName = ((PsiJavaFileImpl) psiFile).getPackageName();
    // Add bytecode instrumentation
    ParametersList parametersList = parameters.getVMParametersList();
    parametersList.add("-javaagent:" + this.getClass().getResource("/").getPath().substring(1) + "ProjectProbe.jar=" + packageName);
    return super.doExecute(state, env);
}
Copy the code

The key here is that -javaagent loads the projectprobe. jar jar package of the ProjectProbe program. The rest is about using the PsiFile API. You can read the official documentation.

5. Effect demonstration

Installing a plug-in

  • Install the plug-in as we would normally install it, but it is currently under development, so it needs to be installed locally.

Running effect

  • This is an example of the runtime, where we output the complete runtime interface information to the console.
  • In the actual use process, the information is sent back to the server, which analyzes it and displays it on the page.

Six, summarized

  • Based on IDEA plug-in and bytecode staking technology, can do a lot of functions. This paper is just one of the solutions that have been developed to test the pain points. If you are interested, you can study them together.
  • When you look at examples like this, hopefully, it gives you the sense that not all of these skills are meant to build rocket conversations for interviews. When you really put it on the ground, you will understand that you need a lot of knowledge.
  • This article does not introduce too much about plug-in development and bytecode technology. If you are interested in bytecode programming, you can visit our official account:Bugstack wormhole stackReply,Bytecode programming. With 117,000 words and 20 chapters, the book covers the use of three bytecode frameworks (ASM, Javassist, byte-Budy) and JavaAgent, along with the entire case source code!

Seven, series recommendation

  • Math, how close is it to a programmer?
  • A code review, almost failed the trial period!
  • “Java Face Book manual” PDF, 5 chapters, 29 sections, 417 pages, 115,000 words, complete and published!
  • Work two years resume to write like this, who want you!
  • Work 3 years, see what data can monthly salary 30K?