在这篇文章中,我们将介绍10个能让你成为更好开发者的原则。这些原则将使你成为一个更全面的专业人士,提升:
-
你编写代码的可维护性
-
写代码时应该关注的重点
-
提高应用程序的安全性
-
可观察性,以便监控你的生产应用程序
让我们一起来看看这10个原则。
当生产用户正在使用并符合验收条件时,才算完成,而不是代码提交时。
我们是软件工程师;我们开发软件。那些尚未投入生产使用的软件有什么价值呢?很可能是零。当我们的应用被实际用户使用时,我们的应用会产生收入、提高效率和客户满意度。
DevOps 运动始于13年前,让开发人员更贴近运维责任。相信我,这将改变你的生活。每写一行代码,你都会思考:
-
用户在这种情况下会看到什么?
-
如果出现问题,凌晨2点会不会有人叫我起床?
-
这里我需要处理多少请求/秒?
如果你必须解释一个笑话,那它很可能不好笑。对代码也是同样道理。
我在代码库中看到的90%的注释都不值得。注释有多个缺点:
-
它们与实现分开,所以代码很可能会发生变化,而注释却忘记更新
-
冗余的注释没有任何价值,只会让代码变得更长,并受到更新问题的影响:
- TODO:这些通常会被遗忘。它现在是否很重要?如果是,请立即处理;否则就别费心了。
何时应该使用注释? 有时,你必须解释一些方法和类名称无法传达的奇怪行为,例如代码保护的生产事故或我们不得不添加的解决方法。这是一个罕见的情况。
始终确保你提交的代码比之前更好。即使是最微小的改进也会提高代码库的整体质量。
如果提交的代码从未使代码库变差,理论上它永远不会变差。它可能会变得更大、更复杂,但从本质上讲永远不会变差。
这是重构的绝佳契机。对于工程师来说,重构就像外科医生洗手一样。我们不会问病人是否希望我们不重构。我们这样做是作为我们工作的一部分。在现有代码库中开发新功能时,如果代码被重构,添加功能会更容易吗?还是试图胡乱操作,使混乱更加难以理解?
当然,不要仅仅因为想要而重构。要成为一个有意图的务实专业人士,并平衡产品优先事项。
如果你必须做超过两次,就自动化它。如果你必须写超过两次,就重构它。
这不仅适用于代码,也适用于手动流程。 想象一下,你的部署流水线中有一个只需5分钟的手动任务,所以你不会花1小时去自动化它。 这5分钟,会累积,今天5分钟,明天又15分钟,3次部署就是15分钟。 很快,你的5分钟就会变成几个小时,最好还是自动化它。因此,第三次必定成功。
编写干净、简单、优雅的代码,符合良好的工程原则,包括SOLID、KISS、DRY、YAGNI和Tell-Don't-Ask。如果不在验收标准中,就不要添加。如果你发现自己想要创建一个IRepository
,那就去冷水澡吧。
我多次看到这种情况,试图过度泛化代码,痴迷于减少DRY,但忽略了关键点:“重复比错误的抽象更便宜。” 代码最终会出现无关的抽象。让我举个典型的例子。
假设你正在编写一个Web API,并且有一个设计系统,控制器将处理HTTP层,然后将处理委托给一个服务。因此,所有控制器都需要执行一个服务。
你可能会看到这样的接口:
现在所有控制器都可以调用IService.DoStuff(),我们重用这个接口。这就是MediatR模式的作用:提供IDoStuff接口的花哨语法。
缺点:
-
代码导航变得可怕;你无法跳转到定义,必须知道如何通过名称模式找到处理程序。(祈祷你不会感到困惑或找到旧版本。我曾经历过)
-
你失去了宝贵的命名能力。当你为每个服务命名时,你可以传达服务正在做什么,而不是I Execute()。
-
内聚性问题。一起变化的事物应该保持在一起。处理程序的注册在一个单独的文件中,很可能只使用一次。
我建议保持简单:每个服务的接口隔离,不需要编写泛型。事实上,在保持简单的同时,你很少会使用泛型 <T>
。 一旦你想使用 <T>
,重新思考一下,你是否保持简单?
简单是终极的复杂。
你几乎肯定不是第一个解决这个问题的人。在尝试之前去找找。
大多数时候,你会处于未知领域,做着你尚未掌握的业务或技术。作为一名软件工程师,你最重要的技能是知道如何搜索。
如果出现错误,你可以搜索错误代码或只搜索错误消息的关键部分。80%的时间,你会在StackOverflow上找到答案。另外20%的时间,你可能需要查看你正在使用的包的GitHub问题。
在搜索时,你给出的每个词都对结果有影响,所以不要添加无关的内容。例如: 臃肿的:如何在c#中插值字符串 简洁的:插值字符串 c#
性能是规模化工作的关键部分,但优化是基于业务需求和基于性能测试结果的。如果你发现自己花费时间试图从本地机器上的一个方法中削减毫秒,那就去冷水澡吧。
if-else和三元运算符哪个更快?这并不重要。 用户不会在纳秒甚至几毫秒的优化中感受到,即使是几毫秒。
基于生产数据和遵循帕累托原则来优化性能。
我只在算法达到O(n²)时才会预先关注性能,通过及早发现避免Big O平方。这种情况常见于在C# Linq或JS集合方法中隐藏for循环的语法糖。
如果你看不到问题,就无法解决它。始终从一开始就编写日志记录和仪表板,并确保它能被你和其他需要的人看到。在半夜破译神秘消息应该留给MI5、丹·布朗笔下的人物和戴锡安帽子的人。
对于这个原则,我额外补充了如何记录日志。 请不要在代码库的每个地方都添加一行告诉正在发生什么。
这会使代码库的大小增加两到三倍,并为你提供神秘的数据。在过去,我们有像log4net这样的工具,你可以有一个单一的文本文件,看起来像这样: 03/22 08:51:06 INFO 用户已将产品123添加到购物车 03/22 08:51:06 INFO 用户已点击“去结账” 03/22 08:51:06 INFO 用户已购买
但是当你有十个并发请求时会发生什么?所有日志行都会交错,你会感觉自己像是艾伦·图灵。
你可以使用APM(应用程序性能监控)工具吗?一些工具可以为你提供每个请求的日志上下文、请求计数、失败率、延迟等等。
到目前为止,Azure的AppInsights对我来说是最好的。它可以在5分钟内实施,并且运行成本低廉。
如果你能给一个方法或类起一个很好的名字,那它很可能只做一件事,这意味着你已经找到了一个不错的方法来分离你的关注点。如果你发现自己想要称呼某物为“管理器”,那就去冷水澡吧。
我经常看到的最大代码异味是糟糕的命名,如果我们看到的东西被命名为“utils”、“helper”或“manager”。找出某物是否遵循单一职责原则的最简单方法是写一个关于这个类职责的短语。一旦在这个短语中出现关键词“AND”、“OR”,它的含义就不仅仅是一件事情。另一个理解单一职责原则的方式是,这个类应该因为唯一的原因而发生变化。
陌生人: "闭上眼睛,张开嘴巴" 你: "不行!你可以往里面放任何东西!"
对于验证输入也是一样的道理 - 如果你不检查别人往你的系统里面放的东西,当它变成一些不好的东西时,不要感到惊讶。
在开发 Web API 时,我希望你能意识到自己就像一个靶子。攻击者可能随时对你的应用发动攻击。因此,坐在那里允许任何输入进入你的应用将导致问题。
这不仅适用于业务规则,确保验证规则得到应用,还适用于安全目的。在多次攻击中,攻击者必须向系统中添加疯狂的输入,以在不应该出现的地方注入 JS/HTML 或 SQL。
如果你看到这里,恭喜你。你正在努力成为一名更优秀的开发者。这些原则并非万能,但它们能为你指明方向,所以我建议每隔几个月重新审视它们。
你将如何应用它们?