官术网_书友最值得收藏!

Go interfaces, structs, and functions

At the interface and struct level, applying SRP results in many small interfaces. A function that complies with the SRP has few inputs and is quite short (that is, it has less than one screen of code). Both of these features inherently address the code bloat smells we mentioned in Chapter 1, Never Stop Aiming for Better.

By addressing the code bloat, we find that one of the less-advertised advantages of SRP is that it makes code easier to understand. Simply put, when a piece of code does one thing, its purpose is clearer.

When applying SRP to existing code, you will often break the code into smaller pieces. You may experience a natural aversion to this, due to the feeling that you might also then have to write more tests. In cases where you are splitting a struct or interface into multiple parts, this may be true. However, if the code you are refactoring has high unit-test coverage, then you probably already have many of the tests you need. They just need to be moved around a little bit.

On the other hand, when applying SRP to a function to reduce bloat, no new tests are required; the tests for the original function are perfectly acceptable. Let's look at an example of a test for our loadUserHandler(), which was shown in the preceding example:

func TestLoadUserHandler(t *testing.T) {
// build request
req := &http.Request{
Form: url.Values{},
}
req.Form.Add("UserID", "1234")

// call function under test
resp := httptest.NewRecorder()
loadUserHandler(resp, req)

// validate result
assert.Equal(t, http.StatusOK, resp.Code)

expectedBody := `{"ID":1,"Name":"Bob","Phone":"0123456789"}` + "\n"
assert.Equal(t, expectedBody, resp.Body.String())
}

This test can be applied to either form of our function and will achieve the same thing. In this case, we were refactoring for readability, and we don't want anything to discourage us from that. Additionally, testing from the API (either a public method or a function called by others) is more stable, as the API contract is less likely to change than the internal implementation.

主站蜘蛛池模板: 苏尼特左旗| 阳新县| 莱州市| 南安市| 吉木乃县| 成武县| 玛多县| 西乌珠穆沁旗| 绵竹市| 吴堡县| 星座| 正定县| 鄂托克前旗| 田林县| 河源市| 辽阳县| 牡丹江市| 土默特右旗| 临武县| 阳谷县| 普陀区| 贡山| 陇西县| 六枝特区| 库车县| 江口县| 庐江县| 环江| 万盛区| 德州市| 蒙山县| 新巴尔虎左旗| 龙岩市| 若羌县| 金湖县| 金阳县| 陈巴尔虎旗| 寻甸| 洪泽县| 郑州市| 金阳县|