如何编写软件:从经营企业中学到的 5 个经验教训
我大约一年前在我的博客上发布了这篇文章。如果你感兴趣的话,我大约每周都会在那里发布新内容。
我以前靠写软件谋生。事实上,我做了很多年。在这段时间里,我学到了很多软件编写的知识。
但我是从一名软件开发者的角度了解到这一点的。今天,我想回顾一下过去几年我的观点是如何演变的。
软件开发者软件与企业主软件
正如长期关注本博客的读者所知,我的职业生涯起伏不定。我最初写这个博客时,是一名软件开发人员,刚刚开始兼职。
最终,我进入了管理层,并开始从事开发者培训工作。之后,我又做了几年的咨询工作。最后,现在我主要经营着一家快速发展的公司。
我讲这些并不是为了给你提供一本未经请求的自传,而是为了设置背景并帮助解释我从上一份全职软件开发工作到现在一直在做什么。
最近,我又开始为 Hit Subscribe 编写软件了。不过,我可不是全职做这个的。
但我正在开发一款业务线应用,直接供我们四个人使用,间接供大约30人使用。所以这并非我的主要收入来源,但就其重要性和范围而言,也并非无关紧要。
花一些时间在这件事上让我反思我的观点是如何改变的。
别误会我的意思。我从来没有埋头假装“生意”不存在或不重要。
但话说回来,我从来就 不是 生意人。我从来没在玩弄我的钱。
既然如此,以下是一些思考。请记住,我并不是想把这些当作 你们 应该吸取的教训。
它们只是我的观点不同而已。
1. 我经常问:“这怎么不存在?!”
我不会详细讲述我正在开发的应用。这不是什么秘密——如果你想知道的话,这里有它的GitHub 仓库。对于行业外的人来说,它不够有趣,不值得详细描述。
不过,我想说的是,你可能会说,市面上有现成的 COTS 可以替代。我对此做了一些研究,但最终放弃了,因为成本太高,而且我更希望获得某种程度的可扩展性,虽然这在当时可能是不可能的。
所以我决定自己建造而不是购买。但这并非我轻易做出的决定。
这种哲学思想还延伸到了更细微的层面。
在我从事软件专业的日子里,我会打个响指说:“哎呀,真糟糕,我猜完美的客户端网格是不存在的,所以我只好自己构建一个了!”但现在,这种情况已经不多了。
无论它是一个框架、一个架构构造、一个库还是一个用户控件,我都会想,“ 现在肯定有人已经 把它建好了。都 2019 年了——怎么它还不存在?!”
我想花时间构建业务逻辑并实现应用的特定价值主张。我 不想 写世界上第 183,663 个日期选择器。
2. 我不认为亲手建造东西能塑造性格
下一点逻辑上建立在第一点之上。我不想再开发一个日期选择器,因为这浪费了我本来可以做其他事情的时间。我宁愿一个日期选择器就这么存在。
因此,我也不认为构建自己的程序员能够塑造我作为一名程序员的性格。
人们渴望了解底层工作原理,这是可以理解的。如果你编写 Web 应用,最好自己编写 Web 服务器,这样才能 真正 理解你的 Web 应用是如何运作的。
你写过 Web 服务器吗?试试写自己的内核逻辑或者操作系统吧。
这有点极端,但它反映了一种情绪。我记得我也有过这种情绪。
构建一些商业价值存疑的东西,或许对你的底线或当前处境无益。但它能为你提供更广泛的通识知识基础,供你在职业生涯中运用。
好吧,我已经彻底讨厌泛泛而谈了,这已经不是什么秘密了。我不认为写一个日期选择器能短期或长期改善我的前景。
这会让我成为一名更优秀的多面手程序员吗?当然,也许吧。
但为什么不构建一些真正服务于你职业生涯的东西,而不是进行一些杂乱的“练习”呢? 我宁愿在我选择的领域里更擅长自动化和解决深层次的问题,让自己作为专家越来越有市场竞争力。
3. 不要对任何事物进行推测性抽象
抛开你个人技能组合和重复造轮子的想法,我们来谈谈实际的软件设计。我对此的看法也发生了很大的变化。
回顾企业 Java 强制采用 N-Tier 架构的鼎盛时期,我曾是该架构的信徒。
想要开发一个玩具应用来对硬盘上的音乐文件进行排序吗?嗯,首先你需要的是数据访问层、领域层、服务层、表示层,当然还有标记。
还有接口。到处都是接口。
当然,今天你可能想用它来对磁盘上的 MP3 文件进行排序,但明天你或许会想用它来处理关系数据库中的链接或文档存储中的 Blob。如果你能将所有层级都连接起来,就能轻松替换整个持久化模型,而无需触及其他任何操作!
你想吗?管他呢!你能做到!
在离开工资软件行业之前,我在2000年代后期逐渐远离了这个行业,并和大多数人一样转向了YAGNI。但我从一开始就对架构感到担忧。
你需要接口,因为需要单元测试。你至少需要 一些 概念上的分层。
最近不太常去。我想测试一下我的代码,如果能测试成功就好了。
所以,除非我拥有多个实现,否则我不会对任何东西进行接口化。除非我拥有一个能够独立改变上下层事物的实际用例,否则我不会对事物进行分层。除非它们能够解决问题,否则我不会创建抽象。
所以我用Entity Framework,直接在控制器里操作上下文 ,一直这么做,直到找到一个令人信服的理由才改掉。我没时间去琢磨最佳实践设计。
4. 技术债务可以成为技术杠杆
你了解债务和杠杆的区别吗?这不仅仅是“千禧一代有债务,而富有的婴儿潮一代有杠杆”这种说法。这关乎 你欠钱的原因 。
如果你为了吃掉一个披萨而向我借了20美元,你就欠了债。你把那个披萨变成了……好吧,这么说吧,它可能没有任何货币价值。你欠我20美元,而且你用这笔钱的方式,让你根本无法提前还款。
但是假设你不买披萨,而是从我这里拿 20 美元购买一股股票。
你还欠我20美元,但现在你拥有的资产(目前)价值20美元。你可以随时还给我。
但更重要的是,你拥有一项可能升值的资产。它的升值幅度甚至可能比你支付给我的贷款利息还要大。这就是 杠杆。
杠杆比债务更具战略性。
在金融领域确实如此,在代码库中也是如此。
在我年轻的时候,我把技术债务完全视为“草率的设计”和团队的失败。我没有区分技术债务和技术杠杆。
但现在我知道了。
我最近用了一个库,它的不可测试设计渗透到了使用它的代码中。所以我把它的使用限制在代码库边缘的一个隔离区域。这个方法奏效了,但是一系列事件开始迫使业务逻辑被强行塞进这些未经测试的小方法中。
我坚持了一段时间,因为我们需要一系列相对快速的修改来推进那些迫不及待的工作。在这样做的过程中,我意识到我需要考虑一个隔离框架或我正在使用的库的包装器。我明白,每次提交时如果没有这样做,以后都会更加耗时。
但有一段时间,我还是坚持了下来。后来,终于,工作日有空闲时间了,我付出了代价。
这就是技术杠杆。我之前提到的宕机时间,就是因为背负了技术债。我节省的时间比自己付出的还多,而且我让代码重回正轨,从而保持了功能交付曲线的平缓。
5. 我对自己工作成果的自豪感无关紧要
最后,我想说说我的想法的最后一个演变。你或许可以称之为“精益”,或者用一句精辟的话来说,比如“如果你不为此感到羞耻,那你就等得太久才发布它了”,或者其他什么的。但我有不同的看法。
我认为这是一种务实的认识,“对代码的自豪感”与我们在这个行业中的目标无关。
噢,别误会我的意思。
我确实对快速交付产品或想出一种简洁易读的方法来重构某个方法感到自豪。而且,我更愿意将拥有漂亮 UI 的产品投入生产。
但这些都是虚荣心作祟,与生意无关。为了生意,我的自尊心无所谓。
所以我不能想“如果我是一名优秀的程序员,我会采用这种最佳实践,或者针对这种情况进行防御性编码,或者有一个尽职调查清单。”相反,我必须通过商业价值和投资回报的视角来构建所有这些事情。
回到之前的主题,如果把需要我们手动输入日期而不是使用日期选择器的东西投入生产,会不会很尴尬?当然,有点尴尬。
但是,如果用户告诉我,日期选择器几乎不会节省他们的时间,我会放弃它吗?是的,绝对会。
我想,最终,从程序员到企业家,再回到程序员的这段经历,为我带来了一个重要的区别。对于业余项目,我会磨锯子,同时进行自动化,磨练技能,做出令我自豪的东西。而对于有商业利益的项目,我会像经济学家一样编写代码。
我也会在这个博客上解答读者的问题。如果你想向读者提问,可以在“问我”页面上提问。
文章来源:https://dev.to/daedtech/how-to-write-software-5-lessons-learned-from-running-businesses-d64