開源日報 每天推薦一個 GitHub 優質開源項目和一篇精選英文科技或編程文章原文,堅持閱讀《開源日報》,保持每日學習的好習慣。
今日推薦開源項目:《以及表情包合集 ChineseBQB》
今日推薦英文原文:《Your Code Really Stinks, This is How to Improve It》

今日推薦開源項目:《以及表情包合集 ChineseBQB》傳送門:GitHub鏈接
推薦理由:你能在各種聊天軟體中看到各式各樣的表情包——老年人有老年人的請你吃蘋果.jpg ,年輕人有年輕人的熊貓頭佩琪狗媽等等。表情包可以說成為了快樂之源,如果你有一些有意思的表情而它們還沒收錄在這個倉庫里,你就可以為這個倉庫貢獻一份力量。記住,當你傳遞一張表情包的時候,你不是在傳遞一張發綠的老梗。你傳遞的,是古典互聯網精神最後的火炬!
今日推薦英文原文:《Your Code Really Stinks, This is How to Improve It》作者:Eric Girouard
原文鏈接:https://medium.com/better-programming/your-code-really-stinks-this-is-how-to-improve-it-3cfbb6b7785
推薦理由:一些跡象的出現可能預示著代碼中存在問題

Your Code Really Stinks, This is How to Improve It

How utilizing your sense of smell can improve your coding ability


Photo by Steve Harvey on Unsplash

We』ve all read code that smells bad. There are few things worse in life than being on-boarded to a new project, firing up your favorite editor, and getting smacked in the face by a putrid stench.

Wading your way through unfamiliar code may snap you back to a time when your roommate never washed his socks, your Uber driver 「forgot」 to put on deodorant, or worse — your high-school locker room after practice.

We know what bad code looks like, and we have a general idea of how to refactor it to be not-so-bad. What we lack is a solid way to know when and how to refactor bad code. For this, we can turn to Kent Beck』s priceless words of wisdom on the topic of child-rearing philosophy:
「If it stinks, change it.」

Photo by Gary Chan on Unsplash

In Refactoring, Kent Beck and Martin Fowler famously relate the identification of Refactoring Patterns to 「bad smells」 in code. They found that just because we know how to refactor doesn』t mean we know when it is best to do so. So Fowler wrote a book detailing common code anti-patterns and how to best refactor them.

I opened by stating that we』ve all read code that smells bad, to go even further, we』ve all written code that smells far worse. Through this arduous-wafting process, we can become adept at identifying these odors and work to prevent them before they start to reek. For legacy code, we can use these trends as cues to know when it is time to refactor.

The existence of any of the following anti-patterns implies that your code has yet to reach its final form and could use a little TLC-R (tender, loving, care and refactoring) to reach perfection. Keeping this list in the back of your mind while coding will reduce the need for refactorings, as you will begin to simply get it right the first time around. Plus, you』ll learn a handful of buzz-words to use during your next code review to one-up your team-mates.
「Just because we know how to refactor doesn』t mean we know when it is best to do so.」 — Martin Fowler

Catalog of Smells

  • Duplicated Code
  • Large Class
  • Long Method
  • Long Parameter List
  • Divergent Change/Shotgun Surgery
  • Feature Envy
  • Data Clumps
  • Switch Statements
  • Middle Man
  • Comments

Duplicated Code

Any time the same code exists in two separate places, a cheap smell lingers in its wake. Your code will undoubtedly be better off if you managed to find a way to join them.

If the same expression is used in multiple places in the same class, pull it out into its own method! Do two classes need the same method? Pull it up into their parent class! No Parent? Make one!

If the same code is used in very disjointed sections of a system, consider pulling it out into its own module or class. Your goal is to decide where each bit of code should live, and ensure it』s not hiding anywhere else.

Large Class

「The first rule of classes is that they should be small. The second rule of classes is that they should be shorter than that.」 — Robert C. Martin, Clean Code
Classes should do a single thing and do it well. With this smell, the first sniff you may whiff is that you struggle to find a name for your class. If you』re unable to think of one, your class is probably too long or has too many responsibilities.

Classes including 『weasel』 words such as Processor, Manager, or Super often bring with them smells indicating that they are aggregating too many responsibilities. In total, a class should only have a single reason to change — this is known as the Single Responsibility Principle. Follow this and your classes will be smell-free.

Long Method

Similar to classes, good methods are short and the best methods are even shorter than that. Newer developers tend to shove a ton of functionality into a single method, leaving a trail of comments to break their monstrosity into logical chunks. The longer a method is, the more complicated and confusing it tends to be.

A method should do one thing and do it well and should have a definitive name that clearly indicates its purpose. Any additional functionality should be extracted into its own method.

The key takeaway from this odor is to be aggressive about the decomposition of your methods. Do not fear a large number of methods — fear large methods.

Long Parameter List

Before Object-Oriented Programming, you had two options when it came to parameters: pass them all into a method or make them global. No matter how you skinned that cat the end result smelled horrendous.

Long parameter lists lead to confusion, mostly since developers are notoriously careless in variable naming. To fix this, we have a few options:

Objects

Rather than passing in a bunch of relevant variables into a method, we can compose objects that store all of these variables and pass just them into our methods. These are known as Data Transfer Objects (DTOs), or Data Clumps, and vary in popularity. Properly encapsulated, objects make a great place to store relevant chunks of data.

Utilize Query Methods for Common Data

Consider this method header:
public Float getChargesStatement(Float cost, Float taxRate, String itemName, long itemIDNumber);
That's a lot of parameters, none of which pop-out as easily remove-able. However, by implementing methods to fetch, or query, some of this data for us, we drastically reduce the amount of information needed to pass in:
public String getChargeStatement(Float cost, long itemIDNumber) {
 String itemName = getItemNameFromID(itemIDNumber);
 Float taxRate = getCurrentTaxRate();
 ...
 ...
}
Following this structure results in less duplication, cleaner code, and shorter parameter lists — smells fresh.

Divergent Change/Shotgun Surgery

The goal of structuring software is to support easy change, it is soft after all. If updates/changes to a class prove difficult, there is often one of these pungent smells lurking in the shadows.

For these patterns, suppose we need to make routine, common updates to our codebase, whether it be for the additions of new databases, new clients, or new products.

If each new update brings with it changes to multiple sections of a class, it is known as Divergent Change and should be avoided. Remember, a class should only have a single reason to change. Identify the pieces of your class that belong together, and extract them to their own class.

On the flip side of the smell, if a new change requires many small updates to many different classes, it is known as 『Shotgun Surgery』 and is arguably worse. When many small changes are required, developers are very likely to forget one, causing bugs and slowing down development time. The fix here is to collect all the little pieces and put them into their own class. Again, classes should have at-most a single responsibility.

Feature Envy

A favored stench of mine is when a method seems far more interested in the features of a class other than its own. The most common violation involves the use of foreign data. We』ve all seen cases where a method invokes scores of calls on some other object to calculate a value of its own — a rancid odor.

The fix here is easy: This problem method clearly wants to be a part of the other class, so let』s grant its wish and move it there. Keep a method in the class that it relies on the most. Extract the leftover pieces to the place that makes the most sense.

Data Clumps

A smaller, but still important issue, we often see sets of parameters or variables lumped together. A firstName almost always comes before lastName and email, for example. When we get a whiff of this, we should ask ourselves:

「If I remove one of these data variables, do the rest make sense in isolation?」

If not, they best belong together as a single data object.

Switch Statements

In general, switch statement stink. They tend to breed code duplication like none other, copying code from one part of a repository to the other. Often when you see a single switch statement, it also appears in several other places throughout your code, whenever that particular piece of logic is needed.

The best solution to switch statements is to avoid using them. The second-best solution is to apply polymorphism as the result of a switch statement, so a class can take over to apply all the relevant logic — wherever it may be needed. This way you avoid large switch blocks — the foulest of odors.

Middle Man

As software developers, we exude abstractions and encapsulation — sometimes at our own expense.

When the majority of the methods in a class simply delegate their work to others, you just created a middle man. Such classes are a waste and are especially difficult to read. When reading through the implementation, you find that half the time you need to hop over to other APIs to get a sense of the whole picture.

The solution is to just cut out the middle man, who needs him anyway?

Comments

Saving the best for last, comments are among the most putrid smells in any codebase, however, they have the potential to smell the sweetest. Used properly, a comment can be the most delightful aroma we come across while sifting through code.

A pleasant explanation for an odd line of business logic; A one-line comment detailing which date pattern is used in the variable date; or a break-down of what that complicated regular-expression is hunting for, are all examples of proper comments, and times when you should actually use them.

A majority of the time, comments are used as 『deodorant』, where they exist only to mask up other bad smells. A comment explaining what a method is doing should instead be reflected in the code. Try making several smaller methods, and naming them appropriately — the intent of the comment may now be held in the code itself!
「When you feel the need to write a comment, first try to refactor the code so that any comment becomes superfluous.」 — Martin Fowler, Refactoring

Gotta love that fresh code smell

Make It a Routine

We may not always be able to refactor bad code.

Many project teams work at such velocity that re-visiting old code, let alone changing class hierarchies and shifting module responsibilities, simply isn』t an option. Regardless of our project bandwidth, we can use these patterns to ensure the code we are in charge of doesn』t stink.

My morning routine consists of showering, brushing my teeth, and putting on deodorant/cologne, all to ensure I』m clean and never reek. I take a similar approach to my code: by keeping these patterns in mind and sniffing for odors as I code, the end result is a clean, smell-free product. If you apply these techniques to your own work and keep an eye out for patterns as you go, your code too can come stamped with a smell-free guarantee.

Follow this advice and at the end of the day, you』re going to like the way you code — I guarantee it.
下載開源日報APP:https://openingsource.org/2579/
加入我們:https://openingsource.org/about/join/
關注我們:https://openingsource.org/about/love/