By Ma Feixiang, nicknamed Zepan at Alibaba.
Have you ever encountered this kind of situation? After a few weeks or months after writing some code, you go to look over it again and feel as though it's not even proper code, and then doubt your abilities as a coder.
At least with my team, we deal with code every day. However, when asked what is good code, many people give unfocused or unclear explanations, rather than a simple and clear definition. Today we will discuss what good code is.
In a word, the only valid measurement of code quality is WTFs/min, as noted by Robert C. Martin.
Image source: https://www.osnews.com/story/19266/wtfsm/
Robert's understanding of what makes code good is interesting and truly inspiring to me. In addition to being used for machine execution that produces the expected results, the code we wrote is more often read by people, which may later be O&M personnel. It is even more often read by ourselves after a period of time.
Any fool can write code that computers understand. Good programmers write code that humans can understand. -- Martin Fowler
So, when it comes to good code, the first word that jumps to my mind is clean. Good code must be clean, giving readers a pleasant feeling.
Clean code reads like well-written prose.-- Grady Booch
It is pretty difficult to define what is good code. I believe that many people, like me, do not think that clean code is necessarily good, but good code must be clean. So, "cleanliness" is a necessary condition for good code. Clean code must feature high cohesion and low coupling, and must be readable and easy to maintain.
High cohesion and low coupling is a term that's familiar to any programmer's ears, but this term is a bit too broad to get down deep into the bottom of things. Smart programmers have put forward several object-oriented design principles to measure the positives and negatives of code. These include:
These principles must be familiar to everyone, and are guidelines when we write code. Code developed based on these principles features high cohesion and low coupling. In other words, we can use these principles to measure the quality of code.
However, these principles are not rigidly dogmatic. We often violate or abandon some principles because of other trade-offs, such as readability and complexity. For example, if a subclass has a feature, we may violate the Liskov substitution principle. To provide another example, the single responsibility principle sometimes conflicts with the interface segregation principle. In this case, we often abandon the interface segregation principle and maintain the single responsibility principle. Code that we write with violation of one or more of these principles is not necessarily bad as long as there are sufficient reasons for the violation.
Is high cohesion and low coupling enough for code? Not necessarily. I think code must be easy to read. Good code should have a readable style, structure, and design. You can consider the following aspects to make the code more readable.
Naming is a very serious matter. You need to consider good names for a project, package, class, method, variable, parameter, or even a temporary variable.
/**
* 创建后的天数
**/
int d;
int daysSinceCreation;
As shown above, the latter name is much better than the former, and the reader can immediately understand the meaning of the variable.
getAccount()
and getAccountInfo()
. In this case, it is difficult for you to determine which one to use for a call, and you need to check the implementation code.Good code formatting is also an important part of readability. The code format can be vertical or horizontal.
public class Demo {
@Resource
private List<Handler> handlerList;
private Map<TypeEnum, Handler> handlerMap = new ConcurrentHashMap<>();
@PostConstruct
private void init() {
if (!CollectionUtils.isEmpty(handlerList)) {
for (Handler handler : handlerList) {
handlerMap.put(handler.getType(), handler);
}
}
}
public Result<Map<String, Object>> query(Long id, TypeEnum typeEnum) {
Handler handler = handlerMap.get(typeEnum);
if (null == handler) {
return Result.returnFailed(ErrorCode.CAN_NOT_HANDLE);
}
return handler.query(id);
}
}
If the blank lines are removed, the readability is greatly reduced, as shown below.
public class Demo {
@Resource
private List<Handler> handlerList;
private Map<TypeEnum, Handler> handlerMap = new ConcurrentHashMap<>();
@PostConstruct
private void init() {
if (!CollectionUtils.isEmpty(handlerList)) {
for (Handler handler : handlerList) {
handlerMap.put(handler.getType(), handler); } } }
public Result<Map<String, Object>> query(Long id, TypeEnum typeEnum) {
Handler handler = handlerMap.get(typeEnum);
if (null == handler) {
return Result.returnFailed(ErrorCode.CAN_NOT_HANDLE);
}
return handler.query(id); }
}
Class static variables and entity variables should be defined at the top of the class. Methods in a class are defined in the following order: the public or protection method > private method > the getter or setter method.
NullPointerException
(NPE) type, and sometimes such an exception can be eliminated through a null object.Now that we have discussed the necessary conditions for good code, let's take a look at the negative conditions for what makes code not so great. In other words, let's dive right into what makes code bad code. Kent Beck uses smell to describe the timing of refactoring. In my opinion, when the code smells bad, this also represents that it is not good code.
Duplicate code is the root of all evil in software design. --Robert C. Martin
An excessively large class always covers various actions and it has too much duplicate code.
If a parameter is too long, it may be difficult to understand and cause errors when being called.
If a single change is made to the methods of multiple classes simultaneously, shotgun surgery exists. You should consider putting the methods to be modified in the same class.
Also, if a function uses the methods of another class to excess, feature envy exists. In this case, you should consider moving the function to the class to which it should belong.
This article first summarizes the necessary condition for good code, which I think is cleanliness. Then it analyzes the characteristics of clean code, and finally explores the negative conditions for good code by looking at what makes code bad. These are only my opinions, of course.
I hope this article can help you in future programming and perhaps maybe also inspired you to tackle on your coding mistakes of past.
ApsaraDB - February 16, 2023
JDP - June 10, 2022
Alibaba Clouder - January 2, 2019
afzaalvirgoboy - October 29, 2019
Your Friend in a need - July 16, 2020
OpenAnolis - November 20, 2023
An all-in-one service for log-type data
Learn MoreVisualization, O&M-free orchestration, and Coordination of Stateful Application Scenarios
Learn MoreElastic and secure virtual cloud servers to cater all your cloud hosting needs.
Learn MoreLog into an artificial intelligence for IT operations (AIOps) environment with an intelligent, all-in-one, and out-of-the-box log management solution
Learn More