软件开发主要有两种
by Jordy Baylac
乔迪·贝拉克(Jordy Baylac)
两种软件开发原理如何保存您的项目 (How two software development principles can save your project)
介绍 (Introduction)
In this post I will focus on explaining how one Design Pattern (Inversion Of Control) and one Practice (YAGNI) can reduce the possibility of having a failed software project. You can start applying these techniques right away.
在本文中,我将重点介绍一种设计模式( 控制反转 )和一种实践( YAGNI )如何减少软件项目失败的可能性。 您可以立即开始应用这些技术。
If you are an Engineering Manager, this is a good read if you want to reduce the volatility on the marginal cost of features ?.
如果您是工程经理,则希望减少功能的边际成本的波动性,这是一本好书。
控制反转(IoC) (Inversion of Control (IoC))
Did I mean Dependency Injection? Not really, but we can use Dependency Injection as the tool to achieve Inversion Of Control between dependencies.
我的意思是依赖注入吗? 并非如此,但是我们可以使用依赖注入作为工具来实现依赖之间的控制反转。
IoC can help in changing the dependency direction. It can help in situations when component A depends on component B, and now you want A to be unaware of the implementation details of B.
IoC可以帮助更改依赖关系方向。 当组件A依赖于组件B,并且现在您希望A不知道B的实现细节时,它可以提供帮助。
Current situation
现在的情况
Target situation
目标情况
With the last approach, component A does not depend on the specifics of component B. In fact, new implementations of IBehaviourB could be added to the project without even touching component A.
使用最后一种方法,组件A不依赖于组件B的细节。实际上,可以将IBehaviourB的新实现添加到项目中,而无需接触组件A。
代码示例 (Code example)
An unknown application having three well-known layers.
具有三个众所周知的层的未知应用程序。
UI -> REST API -> Database
Zooming into the REST API we found UsersController class. We noted that it is reading and writing from/to a SQLServer Database. Below is a possible implementation on C#:
放大REST API,我们找到了UsersController类。 我们注意到它正在从SQLServer数据库读取和向SQLServer数据库写入。 以下是在C#上可能的实现:
If you consider the above solution not to be a good design, you are right ?.
如果您认为上述解决方案不是一个好的设计,那么您对吗?
In the example, UsersController is tightly coupled with the SQLServer implementation. The postUser method makes it difficult to write Tests (remember that a unit-test should not hit databases or external services). As the application scales there will be a high dependency on the specific SQLServer library used. If somebody decides to split the application by domain area, it can be late ?.
在该示例中, UsersController与SQLServer实现紧密结合 。 postUser方法使编写测试变得困难(请记住,单元测试不应影响数据库或外部服务)。 随着应用程序的扩展,将高度依赖于所使用的特定SQLServer库。 如果有人决定按域划分应用程序,那就晚了吗?
This code example corresponds with the “current situation” presented at the beginning of the article. In this case:
此代码示例与本文开头介绍的“当前情况”相对应。 在这种情况下:
A = UsersController
A = UsersController
B = System.Data.SqlClient on .NET
B = .NET上的System.Data.SqlClient
But wait…
可是等等…
What if we apply Inversion of Control so that UsersController does not depend on a specific SQLServer implementation? What if we make the REST API unaware of what Persistence layer we are using?
如果我们应用控制反转使UsersController不依赖于特定SQLServer实现怎么办? 如果我们使REST API不知道我们在使用哪个持久层,该怎么办?
?, ok, let’s do it:
?, 好的,让我们一起做:
20 days later ?:
20天后 ?:
For simplicity’s sake, we have denoted three source files, but in practice, they could be split or located on separates assemblies or folders. This solution corresponds with the “target situation” presented at the beginning. In this case:
为了简单起见,我们已指定了三个源文件,但实际上,它们可以拆分或位于单独的程序集或文件夹中。 该解决方案与开始时介绍的“目标情况”相对应。 在这种情况下:
A = UsersController
A = UsersController
B = SQLUserService
B = SQLUserService
IBehaviourB = IUserService.
IBehaviourB = IUserService 。
We did it!
我们做到了!
Oh, but wait, how is the IUserService dependency injected on the constructor of UsersController? Well, the implementation details of that are out of the scope of this article. However, if you are interested, check out the tutorial I added at the end.
哦,但是等等,如何将IUserService依赖项注入到UsersController的构造函数中? 好吧,其实现细节不在本文讨论范围之内。 但是,如果您有兴趣,请查看我最后添加的教程。
好处 (Benefits)
Our architecture is open for extensions. Also, we reduced the necessity of modification in existing classes. Open/Close principle ?
我们的架构对扩展开放。 另外,我们减少了在现有类中进行修改的必要性。 开/关原则?
Tests are easy to write. We can inject a mock UserService when testing UsersController ?
测试很容易编写。 我们可以在测试UsersController时注入模拟UserService ?
Business logic is not coupled and does not depend on any persistence strategy. ⭐️
业务逻辑不耦合,也不依赖于任何持久性策略。 ⭐️
雅尼 (YAGNI)
You aren’t going to need it!
您将不需要它!
I consider that every developer should adopt YAGNI as one of their core practices. This principle can save you from over engineering and having unused code (untouchable). It can also save your job.
我认为,每个开发人员都应将YAGNI作为其核心实践之一。 该原理可以使您免于过度设计并拥有未使用的代码( untouchable )。 它还可以节省您的工作。
A funny small story:
一个有趣的小故事:
I worked in a project where Software Architects decided to represent almost all boolean columns in the database with a char datatype. At least they were using English — true was stored as “Y”, false with “N”. This makes sense right? When I asked how so magical a solution was conceived, they replied:
我在一个项目中工作,在该项目中Software Architects决定用char数据类型表示数据库中几乎所有的布尔列。 至少他们使用的是英语-true被存储为“ Y”, false被存储为“ N”。 这有道理吧? 当我问到解决方案的构思多么神奇时,他们回答:
“In this way, we are open to the possibility that a third state can come in”.
“通过这种方式,我们对进入第三国的可能性持开放态度”。
I never understood how a true/false thing can have a third state (perhaps they thought about qubits). As you may note, this ended up being a really bad decision and the consequences were present all over the code. I found things like:
我从未理解过真假事物如何具有第三种状态(也许他们想到了量子位)。 您可能会注意到,这最终是一个非常糟糕的决定,其后果在整个代码中都存在。 我发现类似:
if (supportVisa === "Y" || supportVisa === "y") { ...
Code readability was affected, and SQL queries were also affected.
代码的可读性受到影响,SQL查询也受到影响。
But this didn’t stop there. With time, the software added internationalization to its user interfaces. Some configuration and catalogs were provided by the client itself using a GUI application. We get to the point in which some of our boolean columns had “S” and “N” (Si and No in Spanish).
但这并不仅限于此。 随着时间的流逝,该软件在其用户界面中增加了国际化的功能。 客户端本身使用GUI应用程序提供了一些配置和目录。 我们到了一些布尔列具有“ S”和“ N”的位置(西班牙语为S i和N o)。
The code was really unmaintainable. I don’t want to talk about the solution they proposed ?.
该代码确实无法维护。 我不想谈论他们提出的解决方案?。
结论 (Conclusions)
According to Uncle Bob, good developers will try to maximize the number of decisions not made. Do not write something that you believe is going to be helpful in six months. Instead, wait the six months, take a look at your architecture, see how much it has evolved, and then, do the work. Apply YAGNI.
根据Bob叔叔的说法, 优秀的开发人员将尝试使未做出的决定数量最大化 。 请勿在六个月内写出您认为会有所帮助的内容。 相反,请等待六个月,看看您的体系结构,看看它已经发展了多少,然后进行工作。 应用YAGNI。
You should manage your dependencies properly. Inversion of Control will guide you on that.
您应该正确管理依赖项。 控制反转将指导您这一点。
I hope to get into your conscious and help you be a better developer.
我希望能引起您的注意,并帮助您成为更好的开发人员。
“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” ― Martin Fowler
任何傻瓜都可以编写计算机可以理解的代码。 好的程序员编写人类可以理解的代码。” ― 马丁·福勒
阅读更多 (Read more on)
Please share your thoughts and ask any questions. I’ll be glad to answer them. ? Find me on twitter.
请分享您的想法并提出任何问题。 我很乐意回答他们。 ? 找到我不 喜欢的人。
软件开发主要有两种