This article is shared from huawei cloud community “How to eliminate a large number of parameter lists in the code mountain?” , by JavaEdge.

Experienced programmers have seen that a method has dozens or hundreds of arguments.

1 Why do methods have parameters?

Because different methods need to share information.

But in addition to parameter lists, global variables can also be used to share information between methods. But global variables can always be a pleasant surprise, so eliminating them is a major language trend. The argument list becomes the only option, so whenever you think of something to pass to a method, you add it directly to the argument list, making the argument list longer and longer!

2 What’s wrong with long argument lists?

Once the argument list gets too long, it’s hard for a Crud boy to master the logic. So the key is the number, the key is to reduce the number of parameters.

3 Solution

3.1 Every little helps make a great tower

A simple way to create a blog:

public void createActicle(final String title, 
                          final String introduction,
                          final URL coverUrl,
                          final ActicleType type,
                          final ActicleColumn column,
                          final String protagonists,
                          final String tags,
                          final boolean completed) {
  ...
  Acticle acticle = Acticle.builder
    .title(title) 
    .introduction(introduction)
    .coverUrl(coverUrl)
    .type(type)
    .column(column)
    .protagonists(protagonists)
    .tags(tags)
    .completed(completed)
    .build();
    
  this.repository.save(acticle);
}
Copy the code

The parameter list contains all the information that a blog should have, such as: blog title, introduction, cover URL, type, attribution column, main character name, tag, is it over…

If you just want to understand the logic, you might also think that this list of arguments is a good way to pass the information needed to create a blog post to a method, which is the first way most people understand a problem when faced with a piece of code. While writing code this way is easy to understand, it’s not enough to find problems.

Now the product requires to add a message in the blog, to mark whether this blog charges, how to do? It’s easy! I’ll just add a parameter. A lot of shit mountain so come, a little makes a mickle, quantitative change cause qualitative change!

All parameters are required to create a blog, so what you can do is encapsulate these parameters into a class, a parameter class for creating a blog:

public class NewActicleParamters { private String title; private String introduction; private URL coverUrl; private ActicleType type; private ActicleColumn column; private String protagonists; private String tags; private boolean completed; . }Copy the code

This leaves the argument list with only one argument:

public void createActicle(final NewActicleParamters parameters) {
  ...
}
Copy the code

So encapsulate the argument list as an object!

Wouldn’t it be unnecessary to just wrap a list of arguments into a class and then pull them out one by one as you use them? Something like this:

public void createActicle(final NewActicleParamters parameters) {
  ...
  Acticle acticle = Acticle.builder
    .title(parameters.getTitle()) 
    .introduction(parameters.getIntroduction())
    .coverUrl(parameters.getCoverUrl())
    .type(parameters.getType())
    .channel(parameters.getChannel())
    .protagonists(parameters.getProtagonists())
    .tags(parameters.getTags())
    .completed(parameters.isCompleted())
    .build();
    
  this.repository.save(acticle);
}
Copy the code

If you think that way, you haven’t formed an understanding of software design. Instead of simply encapsulating parameters into classes, we introduce a new model from a design perspective.

The encapsulation of a model should be based on behavior.

We didn’t have this model before, so we couldn’t think of what behavior it should have, but now that we have this model, it should have its own behavior.

The model’s behavior is to build a blog object, and the code can be refactored further:

public class NewActicleParamters { private String title; private String introduction; private URL coverUrl; private ActicleType type; private ActicleColumn column; private String protagonists; private String tags; private boolean completed; public Acticle newActicle() { return Acticle.builder .title(title) .introduction(introduction) .coverUrl(coverUrl) .type(type) .column(column) .protagonists(protagonists) .tags(tags) .completed(completed) .build(); }}Copy the code

The way to create a blog is greatly simplified:

public void createActicle(final NewActicleParamters parameters) {
  ...
  Acticle acticle = parameters.newActicle();
    
  this.repository.save(acticle);
}
Copy the code

This way, if later requirements are extended to add content to create a blog, the parameter list is immutable, which means it is stable!

3.2 Static and static Separation

What if this class expands into a large category? After all, not all arguments belong to the same class:

Public void getSections(final long acticleId, final HttpClient HttpClient, final SectionProcessor processor) { HttpUriRequest request = createChapterRequest(acticleId); HttpResponse response = httpClient.execute(request); List<Section> sections = toSections(response); processor.process(sections); }Copy the code

In terms of the number of parameters, there are not many. If you just look at this method, it’s hard to see the direct problem. Absolute numbers are not core, and argument lists should be as small as possible.

But notice that each time the argument is passed in:

  • The acticleId changes from request to request
  • The httpClient and Processor parameters are the same because they have the same logic. That is, the frequency of acticleId changes is different from the frequency of httpClient and Processor parameters.

** Different data movement directions are also different concerns. ** This is typical of dynamic data (acticleId) and static data (httpClient, Processor), which are different concerns and should be separated.

For this case:

  • Static data can be a field of the method’s class
  • Pass only what changes each time as a parameter

Therefore, the code can be refactored as follows:

public void getSections(final long acticleId) {
  HttpUriRequest request = createChapterRequest(acticleId);
  HttpResponse response = this.httpClient.execute(request);
  List<Section> sections = toSections(response);
  this.processor.process(sections);
}
Copy the code

This bad taste is a software design problem. The code doesn’t have the structure it should, so parts of the code that should be static are passed around as dynamic parameters, causing the parameter list to become longer.

A long argument list can be wrapped in a class, but it can be wrapped in a class only if the arguments belong to the same class and have the same reason to change!

If the parameters of the method vary in frequency, it depends. For the static part, as the examples in this section have shown, it can be part of the software architecture and can encapsulate multiple parameter classes if there are multiple varying frequencies.

3.3 Goodbye, mark!

public void editChapter(final long chapterId, 
                        final String title, 
                        final String content, 
                        final boolean apporved) {
  ...
}
Copy the code

The ID, title, and content of the section to be modified. The last parameter indicates whether the modification is approved.

The first few parameters are necessary to modify a chapter, but the last parameter is the focus. In business terms, if the author makes the edit, then there is a review, and if the editor makes the edit, then the review goes through, because the editor acts as the reviewer. So, as you can see, this parameter is actually a marker to indicate that the next processing flow will be different.

The use of marked parameters is often used by programmers learning to program. It is this technique that works so well that it causes flags to fly around in the code. There are markers not only in variables, but also in parameters. There are many long parameter lists that contain various marker parameters.

In real code, you have to be careful to determine the current value of each tag before you can do anything about it.

An easy way to deal with tag parameters is to split the different paths that tag parameters represent.

The method here can be split into two methods, one for “general edits” and the other for “directly approved edits.”

Public void editChapter(Final Long chapterId, Final String Title, Final String Content) {// Public void editChapter(Final Long chapterId, Final String Title, Final String Content) { }Copy the code
Public void editChapterWithApproval(Final Long chapterId, Final String Title, Final String Content) {... }Copy the code

Token arguments can take many forms in code, such as bools, enumerations, strings, or integers. They can be taken apart by means of a split method. In refactoring, this is called removing Flag Argument.

Short code is the best way to get a handle on it, and writing short code requires separation of concerns.

conclusion

The main way to deal with long argument lists is to reduce the number of arguments, most directly by encapsulating the argument list as a class. However, not all cases can be encapsulated into classes to solve, and we need to analyze whether all parameters have the same frequency of change.

If the frequency of changes is the same, it is encapsulated into a class. If the frequency is different:

  • Static, can be part of the software architecture
  • Multiple frequency variations can be encapsulated into several classes

In addition, marker parameters often appear in parameter lists, which is another important reason parameter lists get longer. One solution for such tag parameters is to split the method into multiple methods based on the tag parameters.

Click to follow, the first time to learn about Huawei cloud fresh technology ~