2024-04-14 15:54:33
大概计算了一下,我在GitHub上所有的代码行数早已超过100k行了。三年下来,我在开发上的投入越来越大块,甚至已经吞噬了我的许多其他活动,甚至到了我很多次反思这到底是不是应该在大学期间干的事。
虽然如此我还是义无反顾地干下来了。兴趣所在,原因不明。
说是重复练习积累经验也对,说是重复的过程中找到新的规律从中创新也对。总之,开发活动本身也是一种渐进式的活动。从一开始的编写Hello, World到后来编写一个完整的项目,这中间增长的是复杂度,一同增长的也有开发者自身对于代码的掌控力,以及对于复杂度的控制能力。
大量代码必然大块重复,其上的思考有助于抽离重复部分,丰富复用代码片段库。
增长的复用片段库最终会形成新的范式,或者新的工具,乃至思想。
开发难点在于代码正确性验证,以及消除undefined behavior。测试驱动的开发一方面帮助我们消除ub,另一方面帮我们快速验证和开发模块。好处是,开发进度明确,并且开发完成之后可用程度基本拉满。
同时对比以前的完整编译再运行整个系统的做法,TDD更加敏捷。同时编写测试用例能帮我们理解自己的代码行为和逻辑。
文档的必要性在于对整个代码的形式规约——文档本身也是一种应对复杂度的手段。文档的编写,构建和发布值得我们好好打磨。从注释生成,还是代码即注释,这些都可以,根据情况决定。
好的工具值得我们花费时间熟悉,看起来古老的工具,比如Vim,build-essentials,gnu core-utils以及bash都值得学习。并不是因为它们强大,而是让你学会如何使用基于这些工具构建的现代IDE/构建流程背后的逻辑,思想以及原理,同时让你不被任何现代IDE约束于其中,能完成几乎所有超出IDE能力的任务。
不仅适用于代码编写,也适用于工具哲学。继承是严格的约束,组合是松散的,约定大于规范的约束。pipe,xargs和gnu core-utils等工具能构建出让人难以置信的工具。KISS,同时只做一件事并把它做好,明确单一工具行为,谨防undefined behavior。
另,关于GNU/Linux以及无底洞systemd,组合确实适合构建一些特定的工具,但是对于general-purpose类型的,面向最终用户的接口,还是提供一个相对稳定,严格的规约比较好,不过大量吞噬其他工具这一点大可不必。
大学以来第一个大型项目NanoOJ,很长一段时间处于漫无目的的开发阶段:知道要做的东西是什么,但是不知道现在应该做什么。不熟悉软件工程的经验教训,文档是大段废话和幻想,对于开发毫无帮助。
程序本质是数据的变换工具,因此规划出明确的数据流之后进行开发就可以了。这个阶段的前一步,是需求整理,原型设计。
符合软件工程中需求和文档为先,驱动程序开发的架构。这也是自顶向下设计的一种,适合多人团队项目开发。前后端先约定好接口,根据数据模型进行开发。
针对前后端开发,后端可以使用测试用例驱动;前端可以使用假数据驱动开发,开发完成后对接后端即可。
GNU/Linux是工具的集合。不仅是gnu core-utlis,也指代它的项目源代码库,以及提供的各种库库。使用组合式的实践,可以轻松创建出来稳定可用的,属于自己的工具合集。
Linux系的发行版是越用越爽的:它提供了近乎无穷的原料,让你能尽情发挥创造力——对比Windows,你需要不断学习Windows的各种工具,并很难有手段将它们组合使用——作为用户,你难以创造。不过随着Powershell的改进,这点倒是在逐渐改善。
关于系统的学习顺序,有时间的话最好从系统的启动过程,文件系统,服务管理,网络系统管理,以及性能监测和分析这方面开始学习。如果要从其他方向开始学习也不是不行,因为Linux本身也是渐进式的:学多少基本都能用起来。比较遗憾的是,我是从搭MC服务器/部署网页服务器开始学的(
刚开始听说是在Vue介绍中。后来实践中理解了是什么,为什么,以及怎么做。
渐进式指功能可以被逐渐学习,逐渐集成,比如Linux,第一天删除文件时只会直接rm [filename]
,第二天知道了后面可以跟随多个文件名,第三天知道了可以使用正则来匹配所有要删除的文件。在这个过程中,你一开始就能完成需要的功能,而之后的学习让你将大部分任务耗时降低到可接受范围内。Vue支持从JS,Web
Component和SPA到SSR,SSG多种开发方式,但是你无需学完才能开始编写代码:它的各种工具和概念是相对解耦的。
为什么呢?这和一般人的学习习惯有关。最代表性的例子是数学的学习,实际上我们是顺应着数学的发展历史逐渐向时间轴正向前进学习的。刚开始使用Visual
Studio开发时,我经常因为不知道这东西各个部分怎么用而打开又关闭。用VS
Code就舒服多了,基本功能简单,组合插件带来各种功能的能力也很强。VS
Code打开就能直接写代码,但是VS必须经过系统全面的学习才能不阻碍完整的开发流程。或者这方面,Vim可能是个更好的例子:起初只需要学会i
,Esc
和:wq
以及hjkl
就能把它当记事本简单用用,之后每学到一个键/功能都能直接提升你的效率和体验。
在我的开发学习过程,我一般不使用完整的项目基座,而是从官方给出的最简单的底座和实例开始,一点一点向上搭建。当我做到某一部分时,我会知道这部分需要使用什么新的插件,而不是一开始就从一个打满插件的项目开始——这样的开发体验并不好。当你发现自己的项目已经和其他脚手架/基座功能比较接近时,这时候你就有了新的选择:迁移到完善的大型框架上进行开发。这时候的开发体验应该是如鱼得水的:你理解了应如何组合工具来编写这种复杂度的项目,你也能看懂底座提供的若干功能的逻辑和目的。这个阶段,对框架的使用才是提升效率的手段。
不过这种开发方式仅适用于习阶段,实际大型项目开发最好花时间看看成熟框架的文档和实例。