技术债务有(至少)两种方式进入项目。首先是有意识的决定。有些问题不值得预先解决,因此有意识地允许它们累积为技术债务。二是无知。从事该项目的人不知道或没有意识到他们正在承担技术债务。这个问题涉及第二个问题。是否有一些技术债务被您引入到您的项目中,这些债务本来是微不足道的(“如果我只知道......”),但一旦它们被嵌入到项目中,它们的成本就会大大增加?
11 回答
完全忽略安全问题。
跨站点脚本就是这样一个例子。alert('hello there!')
在您弹出管理界面之前,它被认为是无害的(如果您幸运的话 - 脚本也可以静默复制管理员有权访问的所有数据,或向您的客户提供恶意软件)。
然后你需要昨天修复的 500 个模板。仓促修复会导致数据双重转义,并且不会堵塞所有漏洞。
将日期存储在本地时区的数据库中。在某个时候,您的应用程序将迁移到另一个时区,您将遇到麻烦。如果你最终得到混合日期,你将永远无法解开它们。只需将它们存储在 UTC 中。
其中一个示例是以不支持 Unicode 的模式运行数据库。它一直有效,直到您被迫在数据库中支持 Unicode 字符串。迁移路径很重要,具体取决于您的数据库。
例如,SQL Server 有一个固定的最大行长度(以字节为单位),因此当您将列转换为 Unicode 字符串(NCHAR、NVARCHAR 等)时,表中可能没有足够的空间来保存您已有的数据。现在,您的迁移代码必须做出关于截断的决定,否则您必须完全更改表布局。无论哪种方式,它都比从所有 Unicode 字符串开始工作要多得多。
单元测试——我认为在你去的时候没有写测试会招致难以弥补的巨额债务。尽管我是 TDD 的粉丝,但我并不关心您是在实现代码之前还是之后编写测试……只要您使测试与代码保持同步即可。
不要使用 javascript 框架和手动实现已经可用的东西来启动 Web 项目。维护手写的 javascript 变得很痛苦,我最终把它全部撕掉并用框架重做。
我真的在这个问题上挣扎,试图平衡YAGNI和“我经常被这件事烧伤”
我在每个应用程序上审查的事项清单:
- 本土化:
- 时区会变得重要吗?如果是,请在 UTC 中保留日期/时间。
- 消息/文本是否会本地化?如果是,则将消息外化。
- 平台独立?选择一个易于移植的实现。
可能产生技术债务的其他领域包括:
- 黑洞数据收集:一切都进去了,什么都没有出去。(没有归档/删除旧数据的长期计划)
- 未能在应用程序生命周期内保持 MVC 或层的清晰分离 - 例如,允许过多的逻辑潜入视图,使得为移动设备或 Web 服务添加接口的成本更高。
我相信还会有其他人...
可扩展性——特别是数据驱动的业务应用程序。我不止一次地看到一切似乎都运行良好,但是当 UAT 环境最终与接近生产的数据库表大小一起站起来时,事情开始左右下降。当数据库基本上将所有行都保存在内存中时,在线屏幕或批处理程序很容易运行。
在以前的一家公司,他们使用并强制 COM 用于不需要的东西。
另一家拥有 C++ 代码库的公司不允许 STL。(WTF?!)
我参与的另一个项目仅将 MFC 用于集合 - 不涉及 UI。那很糟糕。
当然,这些决定的影响并不大。在两种情况下,我们无缘无故地依赖可怜的 MS 技术,另一种情况迫使人们使用更糟糕的泛型和集合实现。
我将这些归类为“债务”,因为由于前期的愚蠢决定,我们不得不在项目后期做出决定和权衡。大多数时候,我们不得不解决这些缺点。
虽然不是每个人都同意,但我认为技术债务的最大贡献者是从任何类型的应用程序的接口开始,并在堆栈中向下工作。我开始了解到,通过实现 TDD 和 DDD 的组合,偏离项目目标的可能性更小,因为您仍然可以开发和测试核心功能,接口成为糖衣。
诚然,它本身并不是技术债务,但我发现自上而下的开发更像是一扇敞开的大门,它会邀请那些没有经过深思熟虑的决策——所有这些都是为了做一些“看起来很酷”的事情”。另外,我知道并非每个人都会同意或对此有相同的看法,因此您的里程可能会有所不同。团队动力和技能也是这个等式的一部分。
陈词滥调是过早的优化是万恶之源,这对于微优化来说当然是正确的。但是,在一个显然很重要的领域完全忽略设计级别的性能可能是一个坏主意。
没有预先有凝聚力的设计往往会导致它。如果你花时间经常重构,你可以在一定程度上克服它,但大多数人总是对不符合他们不断变化的需求的整体设计感到不满。这可能是您正在寻找的更普遍的答案,但确实往往是技术债务的更普遍原因之一。