我最近申请了我现在的公司的一个职位,我被问到的一个问题是“什么是好的申请?
我以前从未想过。因此,将我自己对优秀软件应用程序的愿景形式化是一个非常好的练习。这是一个技术职位,所以我的答案是从开发人员的角度出发的。自从我给出我的答案以来,我再次考虑了这个问题,这是我对良好应用的愿景。
一个简单的应用程序
当我设计应用程序时,我总是认为“越简单越好”。开发人员应该只关注需求,而只关注需求。我真的很讨厌:
- 过度设计(过度使用设计模式)
- 过度优化
- 过度开发
- “灵活”的架构
没有什么比容易掌握的简单的东西更胜一筹了。大多数时候,为潜在的未来需求而设计的过于复杂的架构永远不会100%(甚至50%)使用,因为:
- 需求已经改变,
- 期望太高和/或太远(谁能预测5年后会发生什么?
- 该项目的预算已经减少了很多,
- 企业战略已经改变。
这就是为什么我更喜欢简单的东西,如果架构不足以满足未来的需求,则需要进行大规模的重构。
例如,为什么需要一个大数据集群来构建一个刚刚启动的应用程序,因此处理的数据很少?作为一名大数据开发人员,我面试过的大多数候选人都在从事大数据项目,处理(非常)数百万的数据。当我问他们为什么使用大数据时,有些人告诉我“因为有很多数据”,而另一些人则“因为将来应用程序可以处理更多的数据”。几年前,我在一家大型银行工作,我们用“只有”关系数据库处理数亿数据。在掌握的关系数据库和有缺陷的Hadoop集群之间(由于人们的知识很少,分布式平台的复杂性以及不断发展的技术本身而变得错误),选择很简单。例如,Criteo(一家重定向广告初创公司)从Microsoft SQL服务器开始。他们只在2011年夏天才改用Hadoop,现在他们拥有欧洲最大的Hadoop集群。
对我来说,更复杂的意味着:
- 更昂贵(因为它更难理解,因此需要更多的时间)
- 更多的错误(再次,因为它更难理解,因此更难测试)
- 更难监控(再次,因为它更难理解)
当然,如果未来的需求是100%确定的(例如,在设计一个非常大的公司的未来参考时,将在3年内完全使用),那么设计一个复杂的架构是值得的。
可读的代码
一个好的应用程序的一个关键是可读的代码。由于应用程序将由许多开发人员编写和读取,因此他们不要花费太多时间来理解遗留代码,这一点很重要。
在对象编程中,这意味着具有短函数(具有很少的循环复杂性)和具有很少职责的类的代码。我是松散耦合的忠实粉丝,它增加了组件的隔离性,因此有助于在开发人员之间共享工作。
另一个关键点是代码的一致性。在大型项目中,数百名开发人员修改源代码。如果有人按照自己的意愿编码,那么代码很快就会变成一场噩梦,有很多风格的代码。这就像读一本书,有时用英语,有时用法语,有时用德语,有时用俄语......开发团队必须收敛到唯一的代码约定,并且代码必须归任何人所有。我真的很喜欢自我解释的代码:大多数时候,使用函数,类和变量的显式名称,而不是编写注释的音调。当然,仍然需要编写文档(我更喜欢直接在类和函数中编写它)。
我读过的最好的例子之一是Spring框架:它有超过一百万行代码,但我读过的几个部分(关于Spring Core,Spring Batch和Spring Data),其中连贯性和命名约定非常全面(但有些人不喜欢Spring使用的代码约定的冗长性)。此外,Spring文档很棒。一个不好的例子是一个非常著名的C库:libavcodec。大多数应用程序使用此库来处理音频和视频流的压缩、解压缩和动态转码。这个库所做的工作非常令人印象深刻,但是,当你是一个初学者并试图理解它时,这完全是一场噩梦。我花了大约15个小时来理解它的某些部分,以便在空闲时间制作音频流服务器,但我放弃了它:没有足够的文档,代码约定不够明确(对我来说)在没有文档的情况下快速理解。
经过测试的代码
当我开始工作时,一位同事告诉我关于单元和集成测试的信息,我在想“伙计,为什么我需要测试,大多数时候我的代码都是第一次工作”。说实话,我的一部分仍然认为是一样的...但我的愿景已经改变了很多。
当我编码时,我总是想:“它是可单元测试的吗?这是一个非常好的练习,因为它迫使我总是(当我有足够的时间)应用松散耦合。此外,集成和验收测试允许您折射代码并修改其他人的代码,而不必担心修改应用程序的行为。
但是,好吧,假设你有单元测试,集成和验收测试,具有非常好的代码覆盖率,最重要的是测试是自动化的(例如Jenkins)。但这些测试是否相关?我给你两个糟糕(和真实)的例子:
- 在之前的一个项目中,人们伪造了大部分测试,只是为了增加代码覆盖率,使其看起来像一个非常好的项目。他们没有时间编写真正的测试,并且必须具有高代码覆盖率。
- 在另一个项目中,我对别人的代码进行了审计,发现这个人测试的不是代码的行为,而是测试测试中使用的模拟的行为。
在这两种情况下,代码覆盖率都很高,但应用程序并没有真正经过测试。
只有当开发团队真正了解客户的需求和测试背后的概念时,才有可能进行相关的测试。当然,这也需要有足够的时间。
可利用的应用程序
太好了,你有一个很好的应用程序,但是:
- 它是否运行良好?3个月后还会是这样吗?
- 您是否被黑客入侵?你被黑客入侵了吗?
- 是否确定?
为了回答问题,您需要能够监视您的应用程序。
为此,您必须拥有一个具有不同日志记录级别的良好日志记录系统,以便在您确实不了解 Bug 时可以在更详细的情况下以更详细的方式“切换”生产应用程序。
此外,当问题发生时,您需要记录重要事项。我已经处理过很多次生产中的崩溃,有时我唯一得到的是“错误”。很好,但是是什么导致了这个错误?在这次崩溃之前,变量和用例是什么?我很难理解一些根本原因(这让我想要杀死制作##的开发人员)
另一个方面是编写技术和功能指标来监视应用程序行为。例如,内存使用情况,当前进程的数量,客户/合同的数量/每天创建的任何内容......这些指示器可能有助于您检测异常行为。也许内存和CPU被过度使用,因为你被黑客入侵了。也许自上次安装以来创建了太多客户,因为您有一个重复创建的新错误。下面是一个糟糕的可利用应用程序的示例:在以前的项目(在一家大公司)中,我们发现在黑客攻击2周后,我们被黑客入侵,只是因为黑客变得过于贪婪,我们的集群服务器在负载下崩溃了。有了一个好的监控系统,我们可以更快地检测到入侵。
所有这些日志和指标都需要存储在某个地方。再一次,我喜欢简单的事情。对于简单的应用程序,仅使用平面文件就足够了。但是,如果您的应用程序有许多服务器,则使用集中式日志记录解决方案(如 logstash/kibana/elastic search)非常有用。我从事一个项目,生产中有超过30台服务器,没有集中式系统,让我告诉你,阅读每个日志以查看一切是否正常是浪费时间。
客户满意
我见过许多开发人员只受技术驱动。但应用程序不是关于技术,而是关于满足客户的需求。
我喜欢技术(尤其是新的和闪亮的技术),但有时我会选择我不喜欢的“旧”技术,因为它完全符合客户的需求。
此外,大多数时候,了解一种语言的特殊性是没有用的,但了解你正在从事的业务领域是有用的。我从来不理解那些不关心业务领域、只关心技术(通常只有几种技术)的开发人员。例如,在处理巴塞尔II规范(为避免银行破产而制定的欧洲规范)的银行项目(处理数亿数据的项目)上,该项目中的许多开发人员从未读过有关巴塞尔II规范的文章,也没有试图了解这些规范的基础知识。他们本可以在核电站或网络爬虫上工作,这将是相同的:他们只是在不了解其开发用途(甚至一点点)的情况下实现他们被要求的东西。
对我来说,这一点是最重要的。即使你的代码完全是一场噩梦,如果你交付的东西让客户满意,那也很重要。要做到这一点,你需要了解客户的业务领域。
客户满意度应始终是重中之重。
几句话
你刚刚读到我对一个好的应用程序的愿景,它非常接近敏捷哲学。我没有谈论人体工程学或可用性,因为有许多类型的应用程序(用户界面,批处理,Web服务......
这是一个非常主观的,因此有争议的话题。那么,您认为什么是好的应用程序?