Write Methods That Read Like a Business Flowchart
A few days ago, after writing that article about firing a bad programmer, I received some private messages asking: what does a good programmer's code look like? Today, I'll use a real order-placement interface from our project as an example to show you how an expert uses 'methods' to make the business flow 'visible at a glance'.
Today we won't talk about object-oriented programming; we'll just focus on using methods to encapsulate logic. Using methods well, besides the well-known benefit of improving reusability, has two other important advantages:
- First: you can see the core business flow at a glance, without needing to dive into code details;
- Second: every time I modify his code, my error rate is much lower;
At my age, when reading code, I first focus on what the business flow of this module is. If you write a single large method and throw all the code details into it, understanding the key core business flow becomes very laborious. On the contrary, I like to see code like this:
public Long submitOrderDocs(SaveOrderDocsCommand saveOrderDocsCommand) {
//1. Check if the order input parameters are correct
checkCreateOrderParam(saveOrderDocsCommand);
//2. Calculate the time the order can be pushed to the ERP system
buildOrderCanPushTime(saveOrderDocsCommand);
//3. Create the order
Long docsId = createOrder(saveOrderDocsCommand);
//4. Overtime orders go through the OA approval process (must not affect the main flow)
createOaDocs(saveOrderDocsCommand, docsId);
//5. Publish the domain event that the order has been generated
eventPublisher.publishCreateEvent(docsId, ORDER);
return docsId;
}
The method above presents itself as a series of method calls. Just by looking at these few methods, I know the entire core chain of 'placing an order'. If I'm interested in the details, I will click into each method to see them myself. If I click into a method, for example, the Long docsId = createOrder(saveOrderDocsCommand); method, and see code like the following, then congratulations, the programmer who wrote this module is a good programmer:
private Long createOrder(SaveOrderDocsCommand saveOrderDocsCommand) {
//1. Create the purchase order
Long orderId = createOrderDocs(saveOrderDocsCommand);
//2. Split the order: break it down into corresponding delivery orders based on the supplier
createDeliveryDocs(saveOrderDocsCommand, orderId);
return orderId;
}
Notice the code above, it's the same style. Without looking at the code details, you know the core flow is creating the main order and splitting the order.
This is very good; it completely reflects the core use case. The core business runs exactly like this, and that's enough. It truly achieves a perfect mapping from business flow to code.
The code above is: beautiful code.
If you are not yet accustomed to writing this way, please establish this habit as soon as possible. After deeply understanding the business flow, perfectly map it out through code.
Please remember this sentence: Clear code should be able to very simply reflect the core business flow.
So, how does this style of code I just mentioned make modification easy?
For example, suppose there is a requirement to add a new validation when creating an order. Then you just directly modify the checkCreateOrderParam(saveOrderDocsCommand); method. The rest doesn't need to be touched. Why?
Because the code above also embodies an important coding technique:
The code is at the same level of abstraction.
Everyone is at the same level, each performing their own duties. It's not a mix of details, core business, and then something else.
I hope you are not the type to immediately write a messy, large, and all-encompassing method like the one below:
Above is my understanding of why we should use methods well.
Finally, a heart-piercing question for everyone: In your current projects, do you have this kind of code where you can 'see the flow at a glance'? Or, for the sake of progress, has everyone long since written it into a 'heap of loose sand'? Let's discuss in the comments; I want to see how many people are struggling in mountains of legacy code.
Top 1 from juejin.cn, machine-translated. The original thread is authoritative.
I really like this code I wrote. var allResults =Lists.partition(idList, batchMax).stream().flatMap(s->getDataByIds(s).stream()).toList();