[JAVA] Write code that is easy to maintain (Part 1)

0. What to talk about this time

1.First of all

This time, I've summarized my thoughts on how to write better code. Since it is planned to be serialized, only a small part will be introduced this time.

There is no 100% correct answer in coding. We will introduce the advantages / disadvantages as much as possible, so it is best to use them properly depending on the time and the case.

In addition, this article assumes "a system that will continue to be maintained and maintained in the future". It is not recommended for "systems that emphasize the amount of code and coding speed, even if it is a little difficult for others to understand".

2. Basic attitude

When a new engineer comes to the fore, he comes up with this idea.

Don't be afraid to misunderstand this, you should stop.

I will supplement from those who say "I will show you a processing method that seniors and everyone do not know". We welcome you to incorporate new technologies. However, what I would like you to think about as a set is information sharing and education for other members. I'm happy that the person grows steadily, but it's bad for the organization that no one can review the code. The person who opens up and the person who educates do not necessarily have to be the same person, but be sure to do it in pairs.

If you're surprised by a genius algorithm that only I can think of, don't do it if no one else understands your code. "Hmm, I don't know what it is, but Mr. ●● is making it, and the results are correct, isn't it?" Is no good as an organization. Even if it is a little long or a little wasteful of resources, "code that is easy to maintain" should be prioritized. As a guide, about 80% of the members can understand it by looking at the code and thinking a little. Of course, let's put education in between for the remaining 20%.

3. Technique collection

3.1. Don't think about anything and pass objects as arguments

Before correction


public class Item {
  //Unique item ID
  private int id;
  //Item name
  private String name;
}

//Delete item
public void deleteItem(Item item) {
 //Delete process
}

The above code assumes the process of receiving the key id from the browser and deleting it because there is already data registered in the DB. What do you usually need to perform the delete process? Yes, it's enough to have only an "id" that uniquely indicates what to delete. However, in the above example, we are not passing only the id to the method, but as an Item object.

If you want to use this deleteItem () elsewhere in the future, you need to bother to pass the Item object as new. At that time, do I have to enter a value for name? If you pass it as null because you don't use it, will you accidentally use the null name in future improvements? There are many things to consider.

Revised


public class Item {
  //Unique item ID
  private int id;
  //Item name
  private String name;
}

//Delete item
public void deleteItem(int id) {
 //Delete process
}

By doing this, it is obvious that "Oh, just the id is enough for the deletion process", and it will be easier to reuse.

However, suppose that in a future improvement, "I want to add a deletion history function, so I need the value of name when deleting so that I can see what I deleted!". This will change the interface of deleteItem () and will require modification and testing of all callers. If you knew there were such improvements, you might dare to pass the Item class.

Also, if the number of arguments is very large, you may choose to pass each Item object with an emphasis on readability, after weighing it against reduced reusability.

merit

Easy to reuse parts Easy to understand which parameters are required for processing

Demerit

If a fix is planned, all usage points will need to be fixed and retested.

3.2. When cutting a character string, be careful about how to cut it.

Before correction


function jumpToEditPage() {
  var urlStr = (isCreate) ? "Create" : "Edit"
  var url = "https://www.hoge.com/item" + urlStr;
  location.href = url;
}

It is a javascript code when transitioning to the input form screen. Suppose you want to see some conditions and change the screen with the url "itemCreate" for new registration and "itemEdit" for editing. In this code, in order to make it as common as possible, the branch is generated only by the different character strings "Create" and "Edit".

By the way, do you guys say, "Because the service has ended, let's delete the program after confirming that this screen does not appear from anywhere"? At that time, how do you confirm that "this screen does not occur"?

Would you like to search for html with the strings "itemCreate" and "itemEdit"?

In that case, this way of writing will not get caught in the search. Even if some people noticed, "Oh, you can't get caught here as it is, so be careful when searching!" It could be something like that.

Revised


function jumpToEditPage() {
  var urlStr = (isCreate) ? "itemCreate" : "itemEdit"
  var url = "https://www.hoge.com/" + urlStr;
  location.href = url;
}

Even if it branches, it seems easier to maintain if it is organized in this unit.

merit

Easy to maintain

Demerit

I think it's almost nonexistent

3.3. Stop deeply nested if statements

Before correction


public boolean test(){
  if(A == a){
    if(B != b){
      if(C == c){
        return true;
      }
    }
  }
  return false;
}

In this example, there are 3 layers, but if this becomes 10 layers and the conditional expression becomes long, it will be out of control anymore. Also, if it is indented to the right, line breaks will occur, which may reduce readability.

Revised


public boolean test(){

  if(A != a){
    return false;
  }
  if(B == b){
    return false;
  }
  if(C != c){
    return false;
  }

  return true;
}

how is it? In Japanese, before the correction, it is read as "This is it, and it is true at this time." It is an image to store all the conditions in the buffer and make a judgment. After the correction, it is read as "This is the case at this time. This is the case at this time. This is the case at this time. Other than that, this is the case." By processing each condition in order, it looks like an easy-to-understand code. Moreover, the hierarchy is not deep and the readability is unlikely to decrease.

merit

Readability degradation is suppressed

Demerit

It may be difficult for those who are not used to reading it.


This time is over. I will also summarize from a similar perspective.

Recommended Posts

Write code that is easy to maintain (Part 1)
Write code that is easy to maintain (Part 4)
Write code that is easy to maintain (Part 3)
Let's write a code that is easy to maintain (Part 2) Name
Write code that is difficult to test
"Let's write versatile code that is easy to use over time" (nth time)
Code that is difficult to debug and parse
Think of test code that is easy to understand through Comparator testing
How to write code that thinks object-oriented Ruby
Easy to maintain FizzBuzz
How to write good code
Java 14 new features that could be used to write code
[Java] Code that is hard to notice but terribly slow
Function is very easy to use
How to write easy-to-understand code [Summary 3]
[RSpec] How to write test code
How to identify the path that is easy to make a mistake
AtCoder is called TLE and talks about how to write beautiful code
Create assert_equal to make it easy to write tests
How to write test code with Basic authentication
To implement, write the test and then code the process
I tried to make FizzBuzz that is uselessly flexible
Use stream to verify that SimpleDateFormat is thread unsafe
Easy Null Check-I want to give you a chance to write good code. 6 [C # refactoring sample]