- Hands-On Dependency Injection in Go
- Corey Scott
- 468字
- 2021-06-10 19:17:44
Code bloat
Code bloat smells are cases where unwieldy slabs of code have been added to structs or functions so that they have become hard to understand, maintain, and test. Frequently found in older code, they are often the result of a gradual degradation and lack of maintenance rather than intentional choices.
They can be found with a visual scan of the source code or by employing a cyclomatic complexity checker (a software metric that indicates the complexity of a piece of code) such as gocyclo (https://github.com/fzipp/gocyclo).
These smells include the following:
- Long methods: While the code is run on computers, it is written for humans. Any method of more than about 30 lines should be split into smaller chunks. While it makes no difference to the computer, it makes it easier for us humans to understand.
- Long structs: Similar to long methods, the longer a struct, the harder it is to understand and therefore maintain. Long structs typically also indicate the struct is doing too much. Splitting one struct into several smaller ones is also a great way to increase the reusability potential of the code.
- Long parameter lists: Long parameter lists also indicate that the method is likely doing more than it should. When adding new features, it is tempting to add a new parameter to an existing function to account for the new use case. This is a slippery slope. This new parameter is either optional/unnecessary for the existing use cases or is an indication of a significant increase in complexity in the method.
- Long conditional blocks: Switch statements are amazing. The problem is they are very easy to abuse and tend to multiply like proverbial rabbits. Perhaps the most significant problem, however, is their effect on the readability of the code. Long conditional blocks take up a lot of space and interrupt the readability of the function. Consider the following code:
func AppendValue(buffer []byte, in interface{}) []byte{
var value []byte
// convert input to []byte
switch concrete := in.(type) {
case []byte:
value = concrete
case string:
value = []byte(concrete)
case int64:
value = []byte(strconv.FormatInt(concrete, 10))
case bool:
value = []byte(strconv.FormatBool(concrete))
case float64:
value = []byte(strconv.FormatFloat(concrete, 'e', 3, 64))
}
buffer = append(buffer, value...)
return buffer
}
By taking interface{} as input, anywhere we wish to use it, we are almost forced to have a switch like this one. We would be better off changing from interface{} to an interface and then adding the necessary operations to the interface. This approach is better illustrated by the json.Marshaller and driver.Valuer interfaces in the standard library.
Applying DI to these smells will typically reduce the complexity of individual pieces of code by breaking them into smaller, separate pieces, which in turn makes them easier to understand, maintain, and test.
- Learn ECMAScript(Second Edition)
- 軟件項(xiàng)目估算
- Python自然語(yǔ)言處理實(shí)戰(zhàn):核心技術(shù)與算法
- 微服務(wù)與事件驅(qū)動(dòng)架構(gòu)
- Visual Basic程序設(shè)計(jì)教程
- Python漫游數(shù)學(xué)王國(guó):高等數(shù)學(xué)、線性代數(shù)、數(shù)理統(tǒng)計(jì)及運(yùn)籌學(xué)
- Linux命令行與shell腳本編程大全(第4版)
- Modern JavaScript Applications
- Learning Salesforce Einstein
- Java網(wǎng)絡(luò)編程核心技術(shù)詳解(視頻微課版)
- MySQL從入門到精通(軟件開發(fā)視頻大講堂)
- Essential C++(中文版)
- Laravel Application Development Blueprints
- Machine Learning for OpenCV
- 算法超簡(jiǎn)單:趣味游戲帶你輕松入門與實(shí)踐