- Hands-On Dependency Injection in Go
- Corey Scott
- 457字
- 2021-06-10 19:17:47
Go packages
Applying SRP at the package level is perhaps harder to do. Systems are often designed in layers. For example, it's common to see an HTTP REST service with layers arranged in the following manner:
These abstractions are nice and clear; however, problems start to appear when our service has more than a few endpoints. We very quickly end up with monster packages full of entirely unrelated logic. Good packages, on the other hand, are small, concise, and clear of purpose.
It can be hard to find the right abstraction. Often, when I am in need of inspiration, I turn to the experts and examine the standard Go libraries. For example, let's take a look at the encoding package:
As you can see, each different type is neatly organized in its own package, but all of the packages are still grouped logically by the parent directory. Our REST service would break it down as shown in the following figure:
Our initial abstractions are on the right track, only from too high a level.
Another aspect of the encoding package that is not immediately apparent is that the shared code is in the parent package. When working on a feature, it's common for programmers to think I need that code I wrote earlier, and for them to be tempted to extract the code to a commons or utils package. Please resist this temptation—reusing the code is absolutely correct, but you should resist the allure of the general package name. Such packages inherently violate SRP by having no clear-cut purpose.
Another common temptation is to add the new code next to the existing code. Let's imagine that we were writing the encoding package mentioned previously and the first encoder we made was the JSON one. Next, we add the GobEncoder, and things are going great. Add a few more encoders, and suddenly we have a substantial package with lots of code and a large exported API. At some point, the documentation for our little encoding package becomes so long that it will be hard for users to follow. Similarly, we have so much code in the package that our extension and debugging work slows down because it's hard to find things.
SRP helps us identify reasons to change; multiple reasons to change indicate multiple responsibilities. Decoupling these responsibilities enables us to develop better abstractions.
If you have the time or the inclination to do it right from the start, fantastic. However, applying SRP and finding the correct abstractions from the beginning is difficult. You can counter this by breaking the rules first and then using subsequent changes to discover how the software wants to evolve, using the forces of evolution as the basis for refactoring.
- C++面向?qū)ο蟪绦蛟O(shè)計(jì)(第三版)
- Getting Started with CreateJS
- Full-Stack Vue.js 2 and Laravel 5
- Learning Network Forensics
- Microsoft System Center Orchestrator 2012 R2 Essentials
- Learning Python by Building Games
- Salesforce Reporting and Dashboards
- 持續(xù)輕量級Java EE開發(fā):編寫可測試的代碼
- Windows Embedded CE 6.0程序設(shè)計(jì)實(shí)戰(zhàn)
- C/C++數(shù)據(jù)結(jié)構(gòu)與算法速學(xué)速用大辭典
- Scala for Machine Learning(Second Edition)
- HTML+CSS+JavaScript編程入門指南(全2冊)
- Image Processing with ImageJ
- 軟件工程基礎(chǔ)與實(shí)訓(xùn)教程
- App Inventor少兒趣味編程動手做