【译】我是一个平庸的程序员

1,862 阅读8分钟
原文链接:https://dev.to/sobolevn/i-am-a-mediocre-developer--30hn

我个人认为有一些程序员就是天才,他们可以轻而易举地创造一些了不起的软件产品。因为这群天才的存在,我们对这个行业充满了期待。但是有一个悲伤的事实是:不是每一个人都是大师级的程序员。

实际上这就是我,一个平庸的程序员。这篇文章将指导你,作为一个非天才程序员,如何在这个行业中生存。

我一直用google搜索最简单的技术

我记不住很多东西。比如,标准库里的函数和方法,参数的位置,依赖的包名,样板代码等等。

所以,我需要用google搜索,每天如此。我也从旧的项目里复用代码,有时也从StackOverflow或者GitHub上复制别人的代码。是的,我是一个面向StackOverflow编程的程序员。

但我不是一个人在战斗,很多很多程序员都像我一样。Ruby on Rails的作者曾经发过一个很火的twitter

image

这样子写代码有什么不好呢?有如下几点坏处:

  • 你可能从别人那拷贝的,是糟糕的设计或者很烂的代码。
  • 容易形成一个坏的心态:如果不能从网上搜索到你想到的,那么就是“休斯顿,我们遇到麻烦了”。
  • 如果没有网了,那么你就无法工作了。

但是,我并不认为这是一个大问题。它甚至可以作为你的秘密武器。我有几点建议减轻这些负面影响。

生存法则1

  • 使用IDE的代码自动补全和提示,你就不用去搜索语言的基础用法了。
  • 记住你在什么地方或使用什么方法解决了这个问题。下一次遇到同样的问题,找出来看一下就可以了。
  • 你提交到项目中的所有代码,都应该在之后进行分析、重构和评审。这样做,就不会用糟糕的代码降低项目的质量,而是帮助它获得快速的解决方案。

保存事情的简单性

我们说什么,机器做什么。有时候,机器做了错误的事情,仅仅是因为我们下了错误的指令。因此软件开发中的主要问题,不是机器,而是开发人员的思维能力。这种能力是有限的。所以,我们作为一个平庸的程序员,不要浪费脑子去创建复杂的抽象设计、编写晦涩的算法或不可读的长代码块。保持简单性

然而,我们怎么区分这段代码是简单的还是复杂的?我们需要使用WTFs/分钟的方法去衡量代码质量。(译者注:WTF = What the Fu**)

image

这条规则非常简单易懂。你发现代码中有一些你看不懂的东西,那它就是复杂的。你应该怎么做?

  • 重写代码,让人看起来清晰
  • 提供文档
  • 在最难懂的地方添加注释。但是记住,过多的注释本身,就是代码的坏味道。(译者注:参见22种代码味道

生存法则2

  • 使用正确的变量名、函数名和类名
  • 确保你代码每一部分只做一件事件
  • 优先使用纯函数,而不是常规函数
  • 优先使用常规函数,而不是类
  • 只在非常必要的情况下,才使用回调

我不相信我自己

一些开发者已经证明他们能提交高质量的代码。像下面这位女神:Margaret Hamilton,阿波罗计划的首席软件工程师。这张图里,她旁边的等身高的纸,就是为登月任务编写的代码。

image

不过,但于我而言,无论我编写任何代码,我不相信我自己。即使是做项目里最简单的部分,我也能把事件搞得非常糟糕,可能包括:

  • 语言错误
  • 逻辑错误
  • 设计错误
  • 演示错误
  • 安全性错误
  • WTF错误(我最喜欢的)

世界上并没有一本关于“如何编写无bug代码”的魔法师,所以这些错误都是正常的。所有的软件都有bug,处理掉它就是了。

实际上,任何人都不允许编写带有明显错误的代码。所以至少我们应该尝试做到这一点。我应该怎样保护我自己的项目呢?下面有几条建议。

生存法则3

  • 编写测试用例,编写大量的测试用例。大到集成测试,小到单元测试。在每次拉取请求前执行CI持续集成,这将减少你的一些逻辑错误。
  • 使用静态数据类型或者可选静态类型。例如,我们在python中使用mypy,在javascript中使用flow(译者注:现在应该使用Typescript)。这样做的好处是:清晰的设计和编译时类型检查。
  • 使用自动样式检测工具。每种语言都有大量的样式检查工具。
  • 使用质量检测工具。有些工具在你的代码库上运行一些复杂的启发式算法来检测不同的问题,比如这行内部逻辑太多,不需要这个类,这个函数太复杂。
  • 检阅你的代码。在合并到主分支之前代码,有时候在合并之后也需要review。
  • 花钱让别人审核你的代码。这样做有相当大的好处,因为当别的程序员第一次看你的代码时,很容易看出不一致的地方和糟糕的代码设计。

不应该只在我的电脑上有效

image

差不多十年前,当我的团队开发完第一个大型软件项目时,我们将其作为java源文件发布。在我们呈现给客户前的几个小时,它在目标服务器上编译失败了。这算是个大事故。虽然最终我们修复好了并运行起来,但这是个终身难忘的经历。

这是因为在构建管道里,有着大量的配置和大量的复杂性。我们没有能力去正确管理该系统的复杂性。从那天开始,为了减少这一步的复杂性,我尝试将程序打包在独立的环境中,并在实际部署之前在此环境中进行测试。

这几年,随着docker(以及一般的容器)的兴起,这件事情开始变得简单起来。docker允许你在完全相同的独立环境下进行开发、测试和生产上线。采用这种方式,你不会遗留任何重要的事情。

不好吗?说说我自己,在搭建服务、初始化配置或者链接一些东西的时候,我总会遗漏掉一部分。因为有许多东西需要记住。幸运的是,我们仍然可以实现自动化。有许多很棒的工具可以进行自动化部署。如:terraform, ansible, and packer。查看他们的文档,找到适合你的工具。

我也尝试设置CI/CD进行持续集成和持续部署。当在测试和部署的自动化构建失败时,我会收到报告通知。

生存法则4

  1. 一切使用自动化部署
  2. 使用docker作为开发、测试和生产环境
  3. 使用部署工具

在部署应用后,我仍然不相信我自己

最后,我的应用已经在生产环境上线了,它已经在运行了。我可以打个小盹儿了,什么事儿都不会发生。等一下,不,一切都将崩溃。是的,一切。

实际上,有一些工具可以很容易的发现和修复现在问题。

  1. Sentry. 任何一个你的用户产生异常时,你都会收到通知。Sentry已经支持几乎所有的开发语言。
  2. 各式各样的服务工具,可以将多个程序的日志收集到一个地方。
  3. 服务监控.你可以对CPU、硬盘、网络和存储器配置监控。你甚至可以在用户实际压垮你的服务之前,确定需要进行服务扩容的时间。

简单来说,我们需要在生产环境上进行监控。有的时候你需要上述所有工具,有的时候你只需要一部分。要根据自己的情况进行判断。

持续学习

哇,有好多需要学的东西。但这就是我的生存方式。如果我们想写好代码,我们就需要持续学习。成功路上没有捷径,你需要做的就是学习如何一天比一天好。

总结来说,我们需要理解两个基本原则:

  1. 每个人都会遇到问题。最关键的是,我们对这些问题,准备好了吗,准备到什么程度。
  2. 我们可以把问题的根源降低到可接受的程度。

这与你的思维能力或心态无关。