- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
在数字化时代,每一个组织的经营都是建立在数字化的系统之上的,而数字化系统的构建,必然就会带来技术债务,这是每一个数字化团队都要面临的一个问题,如何有效的管控技术债务.
技术债务的产生,是技术团队不断迭代构建系统过程中,无法一次性预设所有的需求,而随之产生了系统设计上的扭曲失真.
在了解了技术债务产生的原因后,就可以将技术债务和团队的作为或不作为联系起来,使用一些有效的策略和方法,来最大限度的减少技术债务的积累,保持系统的持续健康.
有效控制技术债务最小化的方法,可以从现代性的软件设计模式中去借鉴思路: 垃圾回收算法.
相信熟悉JAVA和Golang等现代开发语言的人,对内存垃圾回收的概念,是非常熟悉的。其实,一个项目的技术债务的产生和积累,也就如同一个程序的内存分配和管理是一样的.
对内存垃圾收集的描述为:
运行程序会创建垃圾(garbage),即已分配但未使用的内存。垃圾的产生是不可避免的,因此我们必须偶尔停下来收集垃圾。如果停顿是可预测的,而且很短,那就更好了。有各种各样的垃圾收集算法,它们具有不同的属性.
对团队技术债务的描述,也可以如此:
运行有时间限制的迭代会产生技术债务,即使用过时的设计编写代码。创造技术债务是不可避免的,所以我们必须偶尔停下来重构代码。如果这些停顿是可预测的、短的,那就更好了。存在各种具有不同属性的迭代软件开发过程.
一个团队的软件开发过程是一个由团队自己运行的算法,它产生并清理了一种我们称之为技术债务的垃圾.
那依次延伸,软件开发过程,就可以使用两种方法来控制技术债务:
团队可以在技术债务存在后,通过清理的方式来处理债务.
通常情况下,一个团队在不考虑现有设计的情况下“仓促”完成一个功能,确定技术债务,然后才进行重构以清除债务。有时清理工作会立即进行,但也可能要很晚才得以开展.
小问题可以在几分钟内重构,但大问题可能就需要几天、几周,甚至几个月的投入。当开发人员在编写功能时停下来解决技术债务时,这就像垃圾收集器停下来清理垃圾一样,把时间花在重构上意味着花在新特性上的时间更少,同时当问题越大时,重构所需的时间也就越长.
因为清理债务需要从新功能的构建中去挤占时间,团队会发现自己面临着减少重构的压力,特别是大型系统重构。导致的后果就是,他们只清理了小问题,却延迟了大问题的清理,比如系统的架构。推迟一个小的清理会把它变成一个大的清理,因为随着时间的推移,代码会围绕这个问题构建起来,它也必须被重构.
团队也可以通过减少技术债务的产生来控制技术债务,也就是说,尽可能的预防技术债务.
譬如,团队通过考虑设计方案,并选择产生最少技术债务的方案来做到这一点。当被要求添加一个新功能时,团队会考虑当前的设计能在多大程度上适应该功能。如果设计已经是合适的,他们就添加功能。但如果设计不合适,他们会先更新设计,然后再添加功能.
对许多开发人员来说,避免问题听起来要比解决问题更好。然而,遗憾的是,一些技术债务是不可避免的,迟早,新的功能需求会成为令人不快的惊喜.
同时,团队也会担心,技术债务规避是一个变相的瀑布式流程,或者更糟,是一个预先设计好的大项目。其实不然,因为瀑布式流程会让团队查看所有的需求,并交付一个系统来完成所有需求。技术债务避免意味着团队迭代地处理需求,在每次迭代中交付一个工作系统.
另外,团队也会担心,技术债务规避会导致分析瘫痪。大部分的时候,团队依然会在每一次的迭代中持续交付新功能.
在基本的2个策略的基础上,我们可以进一步延伸,扩展出一个四象限的策略组合:放任自流,被动清理,主动预防,双管齐下。具体如下图所示:
技术债务是一个不可完全驯服的怪物。 ,我们无法彻底的根除,只能选择合适的策略与之共存.
所以,所有最好的算法,任何团队,都要根据自身具体的情况,譬如团队的结构,系统的规模、业务领域的复杂度、团队能力和经验,以及进度的压力等,综合来选择适合的策略.
在一些场景下,团队可以对技术债务采取放任自流的策略.
譬如,你为自己编写了一个快速处理数据的脚本,并且也不打算重用它,为什么要担心技术债呢?
同样,这个策略也可以适用于大一点项目,譬如,大型的电脑游戏,开发者知道他们将为下一款游戏开始新的系统,所以在游戏发行之前,只需忍受技术债务的困扰就可以了.
类似的一次性的系统,放任自流,也是一种可选的策略.
被动清理,就是团队只使用技术债务的清理策略.
这是现在大多数团队所采取的策略。团队的重点始终在构建新功能之上,只是抽空来清理一些细小的技术债务.
因此,更大的清理工作就变的有挑战了,所以早期的错误会一直存在,导致的就是以后重构的代价会更大,这是一个潜在的隐患.
当然,识别问题比规避问题要容易的多,所以在开发人员的设计能力有限时,被动的清理依然是有意义的.
这种只使用技术债务提前规避的主动策略,在今天大部分团队内是并不常见的.
其实,如果你能通过一些事先的思考,来避免技术债务的产生,这要比陷入明显的问题要有效得多.
另一方面,如果你对正在使用的技术没有充足的经验,你可能会因为错误的假设而浪费了时间。尽管努力避免技术债务,但它还是会发生,所以使用主动预防策略的团队,可能会切换到双管齐下的策略之上去.
当团队希望自身技术债务更低更可控的时候,大部分时候都是采取双管齐下的策略,将清理和预防都使用起来.
譬如,在每次迭代的开始,团队讨论新的功能需求将如何影响当前的设计,这样可以保持迭代设计的重点,并让每个人都对设计有理解和掌握度.
团队可能对系统未来的新功能有一定的前瞻的预期假设,即使他们现在没有在做这些需求,但是因为知道未来会发生什么,可能有助于他们更好的思考今天的设计和决策.
有的时候,一个新功能很难添加到现在的设计中,因为它可能与当前领域的假设是相矛盾,或者很难在当前架构中来构建的.
如果开发人员可以重做设计,并在当前迭代中添加功能,那就太好了,如果不能,他们还可以和产品负责人沟通。在做出决定之前,他们会权衡干系人诉求,进度压力和工程风险等.
最终的答案,可能是先推出该功能,然后再清理技术债务,或者完全推迟交付该功能,或者介于两者之间等.
其实,决定那中策略适合当前团队的关键因素,是在于团队是在 玩什么模式的游戏:有限游戏 or 无限游戏.
有限游戏有输也有赢,无限游戏可能会失败,但胜利只意味着你可以继续玩下去。技术债务有点像一场无限游戏:如果你能控制它,你就能继续玩下去。否则,你输了,并宣布技术债务破产.
有严格Deadline的团队是在玩有限的游戏。团队需要按时的完成任务,那就会积累了大量的技术债务.
初创企业也是一系列有限游戏。为了达到下一个里程碑,团队采取了孤注一掷的模式,因为失败意味着公司的终结.
团队缺乏经验,也会迫使你玩一个有限的游戏。如果开发人员不了解问题领域或实现技术,他们就会陷入有限的游戏中,直到他们能够构建一些可行的东西.
当然,从有限游戏,转换到无限游戏时,也会导致技术债务的破产。如果你接受破产,并重启新的游戏时,就需要重新评估你的策略的选择了.
不能试图一直使用一种针对有限游戏的策略,来希望玩转一个无限游戏.
无限游戏更适合双管齐下的平衡策略,既可以通过良好的设计实践避免技术债务,又可以通过重构清理不可避免的债务.
避免技术债务破产的核心:就是 最小化技术债务.
在迭代构建软件时,就 无法避免到技术债务的产生 ,因为我们永远也无法预期所有的功能需求,系统是在生长演进之中,那我们的设计和代码,就会存在设计上局限性和扭曲.
管理技术债务就如同程序内存分配和管理一样,通过优化和改进团队的开发过程,来控制技术债务的产生和积累, 将团队的技术债务最小化,以提升数字化团队的效能和交付价值.
最后的最后, 技术债务不能完全消灭,只能合理管控.
以上为学习: https://ieeexplore.ieee.org/document/9520328/ 论文的一些笔记,具体内容可参见原文.
最后此篇关于用GC的策略,管理团队的技术债务的文章就讲到这里了,如果你想了解更多关于用GC的策略,管理团队的技术债务的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
在我们对延迟敏感的应用程序中,我们有缓存数据(驻留在 TG 中)和在 YG 中消亡的短暂对象。我已经看到次要 GC 时间和主要 GC 时间有显着差异。我怀疑这与TG的尺寸相对较大有关。谁能解释 GC
我看到了多个建议运行 GC.Collect(GC.MaxGeneration) 的答案。 既然方法GC.Collect()会收集所有存在的分代,那么两者有什么区别吗? 也许如果只有两代而不是三代,GC
我们正在使用 UseParallelGC。 GC 日志看起来像 2016-06-09T19:38:17.362+0000:655312.397:[完整GC(人体工程学)[PSYoungGen:2291
我最近看到了两个非常好的和有教育意义的语言讲座: This first one由 Herb Sutter 撰写,介绍了 C++0x 的所有漂亮和酷炫的特性,为什么 C++ 的 future 似乎比以往
我们正在运行 gerrit 2.10.7,我们偶尔会遇到损坏的对象没有被 gerrit gc 修复的问题,即使 git gc 可以很好地修复它们。 另一方面,我读到 gerrit gc 会创建优化其他
我试图避免 Full GC(来自下面的 gc.log 示例)在生产中的 Tomcat 中运行 Grails 应用程序。关于如何更好地配置 GC 有什么建议吗? 14359.317:[完整 GC 143
我试图通过在析构函数中使用 console.WriteLine() 来确保释放某个类的实例,但输出从未出现。 我仔细搜索了任何挥之不去的引用资料以及事件订阅,但没有找到。只是为了我自己的理智,在我继续
之前看过一篇文章,说FGC影响时序,导致application出错结果。 代码示例如下: long start = System.currentTimeInMillis(); doSomething(
在 Java 中,我们可以使用 System.gc() 方法来建议 GC。今天我从this link开始了解C#中的GC.Collect()方法。 . 但我对解释有些不清楚。 第一行。 Forces
我理解 Python GC 有两种工作方式: 1) 基本引用计数 - 当“name”设置为“Tom”时,“John”下方的引用计数为零 name = "John" name = "Tom" (Refe
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
今天我们使用并发标记清除,具体如下: -XX:+UseConcMarkSweepGC 我看到一些文章推荐使用这种形式的附加参数: -XX:+UseConcMarkSweepGC -XX:+CMSInc
当我运行我的程序时,logcat 显示很多 GC Activity 喜欢 GC freed 10324 objects/ 510376 bytes in 103 ms GC freed 10324 o
2013-11-26T10:19:30.011+0800: [GC [ParNew: 2432484K->19997K(2696640K), 0.0378270 secs] 5560240K->315
在执行 GC 时,JVM 会遍历 Activity 对象,并清除未标记的对象。 根据: How to Tune Java Garbage Collection “Full GC的执行时间相对Minor
我有一个分布式缓存应用程序(内存绑定(bind),由于与集群中其他节点的交互而具有网络 I/O)在 JVM 1.7.0_51 中运行,带有 G1 垃圾收集器。这是 JVM 配置: -server -X
首先,我想让您知道,这是一个理论问题而不是实际问题,我只是好奇弱引用对象是如何被释放的。让我们快速记住 Java 中的弱引用是什么。粗略地说WeakReference意味着当没有指向“我”的强引用时,
这是运行大约 10 分钟后的输出。 Heap PSYoungGen total 7040K, used 0K [0x24060000, 0x247c0000, 0x26790000)
我正在运行一个应用程序,在 Weblogic 上使用 java 5 和 CMS 垃圾收集器。在垃圾收集日志中,我看到了消息日志,其中大部分消息我可以使用 Sun 的 Java HotSpot 虚拟机中
我有一个 ConcurrentMap> map = new ConcurrentHashMap>(); 并且希望当 SoftReference 的引用被 GC 时从映射中删除键/值对。 我该如何实现这
我是一名优秀的程序员,十分优秀!