这篇文章是对自我完善的呼吁。你可以这样做。成为一名工程师。 像往常一样,先说说注意事项: 工程师绝对应该而且确实在使用框架。它们是美丽的工程,能够以一种可维护的方式完成工作。框架不是这篇文章的敌人。太棒了,框架。好了,说得够多了。 对不起,什么是框架?框架是一种软件工具,为完成特定类型的软件项目提供一个脚手架。因此,如果你想用TypeScript编写一个单页的网络应用,你不必从头开始做,因为有Angular。想在Python中做一些机器学习吗?请允许我介绍我的朋友Scikit-Learn和Keras。想用C#写一个后端吗? 哦,天哪,你真时髦。)我相信你已经知道ASP.NET了。我可以在接下来的1500字中这样做,但你会明白的。 如果你知道一个框架,你通常可以得到一个标题中有 “工程师 “字样的工作,可能还有 “机器学习”。如果你知道两个框架,你可能会得到一份标题中也有 “全栈 “字样的工作。但是,如果你想在下一份工作中获得成功,你的技能组合需要比框架深入得多 — 你被雇用是因为你的简历上有3–5年的 “工程 “经验。否则,在90天的审查中,你将会坐在一个非常不舒服的椅子上。 你可能需要进行一次旅行。从框架师到程序员到工程师。让我们来看看这段旅程中的每个阶段。我将描述每一个阶段,并谈谈该阶段的专业进展是什么样的。 框架工程师仅仅因为你主要在一个(或两个)框架中工作,并不意味着你是一个框架师。但你可能是。 框架允许Frameworker构建软件产品,其方式类似于宜家允许我构建货架单元。当工作完成后,我做了一个货架单元吗?是的。我应该把自己说成是一个架子工程师吗?可能不是。 框架工程师缺少什么? 编程语言知识框架者通常对框架所使用的编程语言有相当初级的了解。更重要的是,他们可能没有意识到自己的知识匮乏,因为框架被有意设计为提供抽象,使其用户免于许多类型的编程。因此,Frameworker在用有限的编程工具箱解决少数问题方面获得了大量的经验。 知识的深度在他们使用框架来解决的软件问题上,框架制定者也缺乏深度的知识。一个框架代表了实现软件产品概念的特定方式(实现)。这种底层实现通常是抽象的,框架用户可以通过基类、装饰器和[自动生成的]模板,以一些直接的方式将代码注入底层实现中。 框架使用者可以成为框架的熟练操纵者,而不了解框架的基本原理:设计模式、算法(CS或ML)、异步或分布式编程,等等。有时,理解这些底层概念可以通过防止对框架的一些误用而提供直接的好处,但通常人们可以在没有什么深度的知识的情况下充分使用框架。然而,所有这些 “更深 “的知识是有价值的。首先,它具有很大的可迁移性 — 不仅仅是在特定软件产品的直接领域内,而是在各种编程中。更重要的是,如果没有这种深度的知识,Frameworker就没有足够的能力来决定某个特定的框架选择是否能完全满足项目的要求。 但是,这有什么关系吗? 框架建设的结果框架化对Frameworker的职业生涯和他们所在的组织都有负面影响。框架设计师在写框架代码的时候会陷入困境,这些代码足够好,可以合并,但缺乏能力,无法通过长期的可维护性和可扩展性测试。很多不成熟的程序化代码只是被丢到了正确的位置,不熟悉的问题被用反模式处理,而组织的代码质量却在不断下降。 但是从职业的角度来看,Frameworker的前景更加暗淡。具有相同的可转移技能(即使用框架)的编码员每天都会被大约50个新的 “在线学院 “大规模地制造出来。如果一个框架设计师最终找到了一份理想的工作,可以做更多有趣的项目,当他们的知识差距变得明显时,他们可能会经历一个粗暴的觉醒。 附注:他们可能只是被任命为经理,在这种情况下,他们可能会做得非常好。 那么,如果一个框架师想成为一名工程师呢?我建议他们从成为程序员开始。 程序员我将在本文的前提下,在某种意义上使用程序员这个词,这在某种程度上是特异性的。程序员是生活在代码中的人。通过这种模糊的表达,我指的是两件事: - 程序员会阅读大量的代码。
- 程序员正在编写许多不同种类的代码。
让我们依次讨论这些问题。在这里,我将换回第二人称,因为我相信你们应该得到这种个人接触。 程序员会阅读大量的代码你一定会听到有人说,阅读好的代码是学习写好代码的最好方法之一。当你在很早的时候,这是学习语法新方面的一个好方法。这也是学习写出对特定编程语言来说是习以为常的代码的关键。你将学会覆盖边缘情况,并像专业人士一样处理异常情况。但还有一个更好的理由来阅读大量的代码。 阅读代码的最好理由就是要成为真正擅长阅读代码的人。有效阅读和理解新代码的能力可能是工程师将拥有的最重要的单一技能(程序员正在成为一名工程师),因为构成 “核心堆栈 “的技术、语言和库在不断变化。当然,永远都需要好的文档,但是能够通过自己阅读来理解代码是无可替代的。当进入一个新的工作场所时,这一点尤其正确。 幸运的是,外面有大量的代码可以阅读,在做第二件事时可以遇到。 程序员正在编写许多不同种类的代码摆脱Frameworker困境的方法之一是写一些对你来说不典型的代码。这并不一定意味着你在写一种不同的应用程序。如果你用Python做机器学习,你可以有一个自己实现ML算法的副业项目。(如果你用C/C++来做,就会得到奖励。)当然,这可能意味着你在写一种不同的应用程序。试着在你每天运行的一些脚本上面写一个桌面GUI,只是为了好玩。你是做网络前端的吗?试试写一个基于文本的角色扮演游戏吧。 需要注意的是,你并不只是想从一个框架切换到另一个框架。你正在努力学习。你想在一个比你习惯的更低的水平上使用你的编程语言,然后在此基础上创建你自己的抽象层。你应该学习像I/O、套接字、事件循环、缓冲区、哈希生成和尾部递归这样的东西。当你增加抽象层时,你应该学习像多态性、继承性、接口、状态机和设计模式这样的东西。而且你应该获得一个词汇表。 那么,我什么时候才能成为一名工程师? 作为一个程序员的局限性作为一个程序员,你会发现你可以用代码做一些事情,而这些事情对你作为一个框架师来说是不可能的。但也有可能做一些了不起的事情,但仍然是一个可怜的工程师。 想象一下,你正在用零件建造你自己的汽车。但当你组装汽车时,每当你需要把一个不动的部件连接到另一个部件上时,你不是用螺母和螺栓,而是把它们焊接起来。你有可能造出一辆非常好用的汽车。起初是这样。但是,想象一下,里面有什么东西坏了,而且是那种很难拿到的东西 — 你真的需要拆掉一些其他部件才能拿到它。所有这些焊接都是一个糟糕的选择。想象一下,你只想升级汽车的一个部分 — 如果那个部分可以直接弹开,然后把新的部分弹上去,那就真的很好。 我并不是说作为一个程序员(在这个意义上)意味着你完全忽略了良好的工程原则。但是这个编程阶段的目标与工程阶段的目标是不同的。如果说编程是一个或多或少获得某些技能能力的线性旅程,那么成为一个工程师将是一个艰难的直角。换个比喻,你可以把它想成是语言发展:作为一个程序员,你正在获得对你工作的语言的母语流利性。作为一名工程师,你将开始写学术散文。 工程师那么,定义工程师的这种神秘的优先级转变是什么呢?工程师计划和编写的软件能够平衡稳定性和变化。稳定性是一个简单的概念,许多程序员在他们的代码中提供了稳定性。而规划可以改变的代码则更难以捉摸。平衡这两者是使你成为工程师的原因。 稳定性大多数人都理解稳定性的主要概念: 第一个概念是,软件应该做它应该做的事。它不应该是错误的。它应该是可靠的。第二个概念是,软件的使用方式不应该快速和频繁地改变。这在两种意义上是正确的:随着时间的推移,界面应该是相对稳定的,而且界面在整个软件中应该是一致的。 我不打算在这些方面花更多的时间,但我只想强调,当我说接口时,我指的是广义的 — 它可以指你明确声明的东西(就像C/C++中的头文件或Java/C#中的接口等),它可以指一组一致的数据类型和被交互的对象的名称,无论是在状态还是在操作上(就像Python、Scala等),或者它可以指你的 “商业 “用户体验的图形界面。定义一个稳定的界面是非常重要的,不仅是为了稳定本身,也是为了改变。 改变工程师在编写软件时,要能适应变化。更确切地说,工程师能够预测他们的软件可能需要改变的方式,并据此进行编写。这种预测未来的能力肯定会随着时间的推移而增长,但有几种类型的变化足以让我们在此提及。 漏洞。工程师假设他们生产的每件软件都有问题。为了改变(修复)bug,代码应该是有组织的,可读性强,并使用日志记录。这里我就不深入介绍了。至少,工程师知道如何将代码组织成可重用的区块,无论这些区块是函数还是类,并且知道如何将这些代码区块松散地结合起来,以便尽可能地隔离错误,并且只需要有限的修改。 作为数据和行为的用例。我记得在一次电话会议上,我和一个正在完成针对单一客户的MVP的团队领导通话。我问道:”你是否设计了这个[软件],使其可以通过引用配置文件用于其他客户,或者需要进一步开发软件才能将其用于其他客户?” 电话那头停顿了很久,这告诉了我需要知道的一切。当工程师为一个项目 — 甚至是MVP — 收集需求时,他们不断地评估所需的行为,以确定这些行为是否有可能以一种可以在数据层中捕获的方式改变。 一个例子。客户A把他们的数据以Excel文件的形式通过电子邮件发给你,然后转到一个共享驱动器上。客户B有一个API。客户C让你连接到ftp并下载CSV文件。(暂时不考虑这在你的业务-技术整合中所暗示的问题。)这里有三种不同的行为。你的软件可以支持所有这三种行为,同时依靠配置文件(每个客户端一个)来确定使用哪种行为。然后,当客户端C最终得到一个API时,你就不必再做软件开发了。你只需用他们的API信息替换他们配置文件中的ftp信息。 所有这些都是可能的,因为你,工程师,从开发的一开始就知道从共享驱动器中导入Excel文件是一种可能会改变的行为。所以你计划你的软件通过抽象来处理数据导入,而不是硬编码load_client_a_data_from_u_drive() 函数。(你笑了,但我所见过的事情……)你还定义了一个数据层来处理配置。 扩展。在某些情况下,用例的变化大大超出了你的预期或你愿意支持的范围。继续我们的例子,也许你不想为每个不同的云提供商的blob存储支持一个数据加载器。如果你已经明确定义了加载数据的接口,你就不必这样做。下游开发者仍然可以通过编写实现该接口的代码来使用你的软件从S3导入数据,只要你留下了这个机会 结论那么,你在你的旅程中处于什么位置?你是否已经准备好超越那份入门级的简历,为你的工作头衔中可能已经有的 “工程师 “这个词赋予一些引力?成为一名工程师不一定是终点,但如果你准备好要冲出框架,这是一个很好的去处。
|