【AICon】AI 基础设施、LLM运维、大模型训练与推理,一场会议,全方位涵盖! >>> 了解详情
写点什么

敏捷水手——单体法到微服务之旅

  • 2017-01-21
  • 本文字数:8824 字

    阅读完需:约 29 分钟

本文要点

  • 探究持续四年多的渐进式改革是什么样子;
  • 探索为什么在变革软件和组织设计时要遵循康威定律;
  • 看看如何将领导力应用到不同的团队、领域和层级;
  • 举例说明变革管理如何依赖于理念和一贯的长远目标;
  • 了解从职能型团队到跨职能团队的变革需要做多少工作以及能带来多少回报。

简介

过去几年,eSailors IT Solutions 在技术和组织层面进行了重大变革:从功能筒仓到跨职能团队,从看似装配线的工作流到动态循环,从单体平台到微服务,从层次化的命令 - 控制到团队运作的领导力。本文将简要介绍他们的变革之旅。本文将带你了解大约四年之前我们从哪里开始,经历了哪三个主要的变革阶段才成为现在这个样子。对于每个阶段,本文都将概要地介绍以下几个方面的内容:

  • 我们当时的组织设置;
  • 主要的技术栈;
  • 我们面临的最重要的挑战;
  • 我们希望取得的变革成果以及我们实际取得的成果;
  • 我们的经验教训以及它们如何推动了进一步的改进。

贯穿本文的一个重要主题是康威的假说“设计系统的组织……其产生的设计和架构等价于组织间的沟通结构。” 1 我们将把这一理论作为一面特殊的镜子,用它来照一照我们自己的历史。将组织设计和软件设计对照有什么意义?我们从对公司沟通模式的探究中学到了什么?为什么康威定律仍然在伤害着我们?

我们从哪里开始

以前,在汉堡,对于那些只有 75 名工程师、全部员工大约只有 120 多人的小型软件公司而言,生活很简单。面对着大约 300 万的客户,我们的点子来自当事人、市场或法律部门。我们的平台平均要服务于大约 35 万活跃客户,每年 2.5 亿订单。工作流程是由项目经理组织的。知识被职能筒仓完全隔离:软件部门负责编写特性,质量保证部门负责保证质量,运维部门负责确保软件的稳定运行。如果我们需要修改任何基础设施组件(如增加新服务器、不同的操作系统程序包),一个隶属于其他部门(及国家)的团队就需要进行必要的安装准备。由于各种各样的预算、合作和 / 或沟通问题,这种方法经常导致严重的延期。

图 1:eSailors 的装配线

我们那时的组织设置是什么样子?

我们那时的组织设置是什么样子?如图 1 所示,我们的工作流组织非常像老式工厂里的一条装配线。大多数员工都是在那五个部门(项目管理 / 市场营销、设计、开发、QA、运维)的其中一个部门里工作。每个部门都有自己的管理结构,都有团队负责人和部门主管。遵循着特定的冲刺周期和步骤,软件工件从一个部门传递到下一个部门:

  • 步骤 1:市场营销部门、法律要求或项目经理界定特性,但不进行有效的预验证或评估;
  • 步骤 2:设计部门根据经验进行设计;
  • 步骤 3:开发部门在一个软件工件中实现功能,团队使用 Scrum,但对于 UI 变更,会咨询一个专门的前端团队(3 周);
  • 步骤 4:QA 部门测试(2 周);
  • 步骤 5:为了防止基础设施方面的更改,基础设施团队会准备系统;
  • 步骤 6:Ops 团队将软件工件部署到生产环境,并对其进行维护;
  • 步骤 7:一个专门的团队进行 Bug 修复。

简而言之,我们的价值流是瀑布式 Scrum 2 。就是说,我们在传统结构下实现了 Scrum,我们的敏捷理念所关注的是局部,而不是整个系统。此外,我们在很大程度上还是筒仓形式的组织,采用传统方式进行管理,以决策制定为中心,沟通通常是单向的,由自上而下的策略和自下而上的报告所主导。我们的组织设置如图 2 所示:

图 2:eSailors 最初的组织设置

为了变得更加敏捷,每个产品开发团队都竭尽全力。图 3 展示了我们的团队设置。在本图及后续出现的图片中,DEV 表示开发人员,QA 表示质量保证,PM 表示项目经理。即使每个团队都有一名质量工程师,最终的质量检查和软件审批也还是由一个专门的质量部门所完成。团队的质量工程师必须以一种质量部门审批时能够执行的方式准备测试。

图 3:eSailors 最初的开发团队设置

我们的技术呢?

我们一点也不感到奇怪,这种模式反映在了我们的软件架构中。技术被设计成一个单体平台,基于一个紧耦合的代码库构建,总是作为单个软件进行部署。我们的代码大约有 80% 都打包在一个工件中。eSailors 的工程师习惯将这个平台称为“大泥团”,因为它没有一个可理解的架构,而且很难扩展和维护。部署是通过一个复杂的工具完成的,而且还受限于版本控制系统的逻辑。有时候,提交几个小时后才看到单元测试失败。由于构建和部署过程的复杂性,这个技术栈让变更变得相当困难。

我们如何设法变革我们的流程?

康威定律指出,“设计系统(广义而言)的组织其产生的设计和架构等价于组织间的沟通结构”。我们那时从对现状的审查中了解到了什么?我们如何行动起来设置这两种结构?我们的计划是什么,而我们实际上取得了什么样的成果?

我们从康威定律中汲取的其中一个最重要的教训是:转化成创新性产品以及缩短上市时间不能只依赖于技术变革。相反,组织变革和技术息息相关,需要对这两个维度都进行检查和相应的调整。虽然这在概念上听起来很简单,但改变我们的组织设置和思维花费了我们很长时间,而且现在仍然是我们需要首先处理的问题。

图 4:第一步:新的团队设置

检讨我们的装配线问题,我们决定创建跨职能团队,由他们对整个系统开发的生命周期负全责。为了达到这个目标,我们从组织设置入手。我们解散了 Bug 修复团队,让特性团队为自己的错误负责。这也可以帮助他们更好地理解操作上的需求。我们认为,跨职能团队应该包含全栈职责,所以我们将原先共享的前端团队的成员分配到特性团队。同时,我们将冲刺周期改为两周,一周用来开发,一周用来测试。

我们希望从这些组织变革中得到什么呢?从根本上说,我们希望提高软件质量,缩短交付时间。我们实际上得到了什么呢?好了,我们的结果让人觉得有点矛盾。一方面,加大团队的自主权和责任感让人们更清楚问题所在。但是,所有团队都开始寻找可持续的解决方案,而不是修复问题。这种情况就是由图 4 所示的新的组织设置所导致的。

让开发团队负责 Bug 从许多方面改善了运维和开发部门之间的沟通。DevOps 交流项目启动(开发人员在一个冲刺期间呆在 Ops 部门,反之亦然)。开发人员主动请求参与呼叫中心的工作及使用监控工具。组织文化日益趋向于端到端职责,这种变化越来越明显。开发人员、运维人员和基础设施人员开始定期讨论系统和管理问题。这是进一步改进的关键。简化后的装配线如图 5 所示。

图 5:第一步:管道

不出所料,领导力在许多层面得到了增强。过去,作为功能专家,工程师们习惯于构建自己的 I 型技能集。现在,他们开始让自己向着跨职能团队的 T 型领导者发展。团队自己承担了技术决策的职责,而不是专注于一种核心的架构。

另一方面,我们的共享代码库还是保持不变,还是会导致小的改进开发成本很高。

而且,我们开始认识到,我们的 Scrum 方法在许多方面都是失败的。它没有为我们提供正确的指导,却首先增加了我们的负担。我们经常因为需要修复即将出现的 Bug 而完全忽视了我们的冲刺承诺。将大的特性分割成较小的故事然后排定它们的优先级,这项工作费时费力。也许,最大的阻碍是作为我们主要客户的项目管理和市场营销部门的无法撼动的瀑布式思维。我们使用 Scrum 框架,但是在实现过程中没有采用特性范围。团队的产品经理充当了管理者,将瀑布项目计划分割成较小的不可变部分,而不是减少前期文档以及检查和调整每一个小的开发步骤。而且,我们的前端开发人员的工作流程很难管理。有许多次,团队的其他人员都停下来,等待 UI 修改完成。在其他冲刺中,他们又无事可做,这种让人沮丧的境况导致部分前端开发人员离职。

我们如何改变了航向?

我们从自己的变革中学到了什么?我们哪里违背了康威定律的观点?这如何促进了进一步的提升?下面是我们找到的部分答案:

  • Scrum 并不适合所有的团队、所有的情况。那就是为什么我们必须要求人们检查和调整自己的工作流程以满足需要,并鼓励他们了解业务的全局。
  • 所以,我们需要敏捷团队关注端到端的价值流程,而不是仍然面向筒仓的 Scrum。而且,我们需要敏捷教练有企业家的跨部门的视野,而不是像 Scrum 主管那样只专注于一个团队。
  • 我们还认识到,不只是领导者需要一个更趋向于 T 型的技能集,所有的工程师都需要。在特定领域拥有知识深厚的 I 型专家挺好,只要他们能够并且愿意涉及其相应技术之外的主题。在理想情况下,将来我们的工程师既对跨部门协作持开放态度,又乐于改进软件质量,而不会等到有了明确的业务需求才那么做。
  • 承担起 Bug 修复的职责增进了我们对系统性问题的了解。另一方面,在使用一个大型共享数据库的情况下,全心全意地投入到业务领域及相关软件仍然相当困难。为了提升我们的速度和敏捷性,我们越来越迫切地感觉到要减少对业务端和技术端的依赖。
  • 如果不给团队的产品经理充分授权,让他们可以推动产品愿景的实现,那么他们就无法增加价值。我们只有对每个团队充分授权,让他们在整个开发过程中自主地创建、检查及调整他们的特性,而不只是执行来自外部的需求,我们才可以有所作为。
  • 自上而下推动的决策过程无法达到预期的结果。为了鼓励更多的创新,我们也必须支持自下而上的过程。
  • 虽然团队授权是该做的事情,但跨不同团队和部门的沟通以及协作仍然是一个大问题。
  • 只是改革我们的组织设置及创建新的角色是不够的。作为一项分层桥接的跨职能的团队活动,为了建立领导力,我们还必须解决所有管理角色之间的冲突。

简而言之,我们认识到,我们必须投入更多的精力,以便使用正确的方法构建正确的东西,而不是忙个不停。而且,我们必须加快我们的整体流程,并为此定义清晰的职责。为此,我们设定了新的改进指标。

首先,我们提升了 UX 和产品管理的重要性。在最高管理层的推动和外部培训师的支持下,我们实现了一个包括用户测试、用户实验室和团队 UX 工程师在内的 UX 流程。同时,产品经理承担为我们的客户开发有价值的软件的全部职责。为了减少众所周知的沟通障碍,测试部门成了工程部门的一部分。如图 6 所示,这形成了一个新的组织设置和工作流程。图 7 展示了新的团队设置。

图 6:新的组织设置和工作流程

图 7:第二步:新的团队设置

不再坚持“纯粹的”Scrum,团队开始寻找新的敏捷方法。团队改变了自己的组织方式。这是以一系列的团队建设专题讨论会为支撑的。我们通过这些研讨会评估现状,定义可以作为构建基础的基本优势,商定新的规则和价值观。同时,通过运用各种不同的同伴反馈方法,我们培养了开放沟通和相互帮助的文化。

管理团队也关注团队建设。他们在整个业务部门内进行元回顾,定义可以作为构建基础的优势,深入问题和解决方案。一项重要的改进是,我们开始共同合作,创造性地评估相互矛盾的角色,提取出了精益领导力的第一个概念。任务重叠,界限模糊,决策策略让人困惑,对于这种有些混乱的局面,我们如何有效地进行简化?实际上需要什么样的指导?每一种领导角色都增加了什么价值?需要多少角色?那些角色之间的职责如何划分?

为了培养更多自下而上的流程,我们还修改了我们用来管理变更方案的方法。作为其中的一部分,我们开始在那些方案中包含更多的功能专家。我们新增了所谓的变更团队,而不只是执行由高级管理人员定义的策略。该团队的成员来自那些受变更影响最大的团队,他们被赋予了自主权,可以在一个清晰的界限内研究并实现自己的解决方案。这与其他增强所有权的策略是一致的,比如各种社区实践、有关松弛时间或联合黑客马拉松的明确协议。

我们主要关注的是提升人们提出更多思路和解决方案的内在动机,而不是试图通过诸如金钱、奖金等这些由高级管理人员定义的外部动力来激励人们。为了消除这种外部动力,其中一项改革是将薪金的一些动态部分移到了固定部分。由于其中的部分指标不再由上层管理人员定义,所以团队自己设置自己的指标。

同时,我们继续将我们的软件拆分成微服务。在咨询了外部软件架构师之后,我们为了实现那个目标开启了一项重大的重构计划。通过这项计划,我们希望可以获得完整的跨职能团队,通过独立部署缩短上市时间。我们希望创建对特定领域的技术和业务全权负责的团队。

在建立了重构团队并提取了第一个微服务后,项目终止了。高级管理人员的整体参与度还是太低,而且作为一个整体进行重构太大太冒险。由于重构计划停止了,所以周期时间仍然很长,创新成为意外而不是惯例。我们的技术债务仍在增加。这反映出,我们的组织结构仍然妨碍改进。我们把大量的时间浪费在了权限讨论上,而不是提升软件质量或者实现新的技术。为了有效地实现微服务,我们需要给产品团队更大的自主权,让他们选择自己的工具,并全权负责包括部署在内的整个软件生命周期。即使在上述大规模的重构计划终止以后,工程师们还是深信,将共享的遗留代码库迁移到更小的服务不可避免。现在,我们的新做法是,只要有新需求添加到相应的代码区域就删除旧有的业务逻辑部分。

作为改进工作的一部分,团队改变了维护内部部署和测试框架的习惯做法。他们停下来开发自己的解决方案,致力于保持现有工具的稳定性。我们一致同意使用一种新的策略,让我们可以使用开源的部署和测试工具部署每一个新的服务,而不是使用旧有的内部工具。这样,产品团队变得日益强大,对有效地改进东西越来越有信心,他们开始推动创新。

发现新大陆

所有这些指标把我们带到了哪里?什么有了实际的提升,什么保持不变,而什么变得更糟?以下是对我们 2015 年及 2016 年前 2 个季度一直忙于开展的工作的总结。

在技术方面,我们继续向着独立的微服务发展。同时,我们改善了基础设施部门和工程部门之间的合作。基础设施部门的人员开始向工程师们的实际需求看齐,而不是或多或少地独立创建和维护他们自己的服务,忽视了依赖。

逐渐地,部分产品团队承担起了为新服务创建所需基础设施以及运维新服务的职责。因此,团队现在可以从操作系统层面开始加入自己的技术。这是逐步建立 DevOps 文化的其中一个先决条件。

我们还实现了工程工具的现代化。工程师现在可以自由选择自己的工作站或者笔记本电脑,而不是一个中央虚拟机。一方面,他们有更大的自由来创建自己的环境和工具,另一方面,他们必须增强自己的主人翁意识。此外,我们使用 GitHub 开辟了新的软件开发路径。

在组织设置方面,我们继续向着精益领导力发展。如图 8 所示,我们删除了 ScrumMaster 的角色。对于这个角色,我们认为其作为敏捷催化剂的功能已经完成,团队已经足够成熟,可以实现自组织。我们一举建立了一个精益 - 敏捷教练(LAC)池,可以提供支持团队及管理者的新途径。

图 8:现在的开发团队设置

我们还加大力度,使重要的信息尽可能地透明。可视化管理系统的问题变得愈加重要。产品经理引入了所谓的“墙”来展示有关当前业务选项和即将到来的变更的信息。图 9 展示了设在办公室中央开放空间里的这块板子的最新版本。通过这种方式,我们增加了业务流程的透明度,从通过评估和选择创建业务选项,到开发、验证和完成——这块看板增强了人们的求知欲,促进了沟通交流。

图 9:“墙”

谈及透明度,整个公司都开始每个季度会面,分享团队在最近一个季度里完成的工作以及他们希望在下一个季度里达到什么目标。以新方法为基础,我们还构建了更为透明的变更方案。变更团队的实施方案会同各方面的利益干系人进行公开讨论,例如,使用鱼缸讨论法的形式。这种方法更容易让那些受影响的人参与进来,了解工作进展,促进总体投入。这还有助于直接传递变更的内容和原因,让人们对变更的实现方法有一个统一的认识。变更的能量来自于面对面的交流和协商一致的行动,而不是官方公告、正式的启动会议或者专家的总体规划。

我们提供了一系列的领导力培训,例如,关于如何领导一个人员来自各个领域的自组织团队。第一次,来自不同领域的领导者,如产品经理、团队负责人、董事和 HR,都致力于就未来如何管理公司达成共识。为了有效地支持自组织,需要什么?就能力和实践来说,这意味着什么?共同探讨精益和敏捷领导力的原则,他们还增进了彼此之间的了解,增加了信任和相互理解。

所有这些方案帮我们减少了筒仓逻辑,培养了专注于整个价值流的跨团队协作。与此同时,整个工程部门还形成了一种事后反思和回顾的新文化。实际问题和重大事宜现在都是直接沟通,而不是背后指责和议论。不管是在系统层面,还是在个人层面,提供和接收诚实的反馈都是非常有价值的。

我们现在的状况

所有这些变革对我们的业务有什么影响?我们的变革之旅对我们现如今的自我组织方式有什么意义?再次对照康威定律,图 10 和 11 展示了我们现在的组织结构。

图 10:2016 年 eSailors 的组织方式

图 11:2016 年 eSailors 的组织结构

在摆脱了装配线流程后,现在,跨职能产品团队成为我们关注的焦点。它们是我们保持高效、作出所有重要决策以及推动任何必要变革的引擎。产品团队的重点工作不再是根据特定的规范开发软件产品,然后交付给或多或少不连通的部门,相反,他们既可以决定实现什么,又可以决定如何实现。其他部门提供支持服务,比如数据、基础设施或者咨询。每个团队都可以独立地部署和监控他们的软件。不过,他们通常会合理利用运维部门提供的工具。类似地,团队可以自己做些用户研究,但会有一个用户实验室为他们提供支持。

图 12 说明了现如今的产品团队如何涵盖了整个开发周期。该循环始于识别客户需求和痛点。基于在这个发现阶段了解到的内容,我们可以发现商机,并使用一个特定的画布对它们进行评估。接下来是设计原型以及用户测试,从中我们可以了解到实现正确的功能所需要的一切信息。经过一定数量的循环后,这些功能就不会发布到生产环境里了,然后我们会进行监控,并通过 A/B 测试进行微调。

图 12:eSailors 的开发周期

我们的技术也发生了极大的变化。从原先一个很小的技术集和占主导地位的“大泥球”,我们设法减少了后者,并增加了前者的多样性。我们不再什么系统都仅使用一种数据库解决方案(Oracle),而是在生产环境中使用多种不同的数据库(Oracle、Mongo、Redis、Elasticsearch、Cassandra)。我们不再仅仅关注一门编程语言(Java),我们现在使用不同的语言(Java、Scala、Go、Swift)。还有其他新的工具和库,例如,docker、ansible、vagrant、angularJs、consul 或 openstack。每个团队都有特定的功能领域。他们现在有权自己选择最适合团队需求的技术栈,为他们的特性构建解耦合的微服务。通过选择恰当的工具,而不是实现某项共享技术的变通方案,将新特性交付到生产环境变得越来越快越来越简单。这是可能的,因为团队的工程师现在可以专注于自己的部分,并对自己所开发的服务的全生命周期负责。如果不是对技术栈全权负责,如果需要向其他部门进行彻底地交接,那么这种技术的异构性是不可能的。

我们还没有完成我们的微服务架构,但是我们使用微服务实现了所有的特性。我们还在继续逐步地改进我们的架构。发布新服务的提前期也有了显著的改善。现在,新服务几分钟内就可以构建、标记、测试和部署到生产环境。有时候,从构思到完全实现只需要一天,而不是几周。

虽然我们取得了许多成果,但是我们仍然面临着巨大的挑战。一方面是技术挑战,比如我们的架构的复杂性、我们接下来的微服务旅程或者保证设施随时可用的困难。同时,我们面临着组织和业务上的挑战。在通向始终如一的精益敏捷企业的道路上,我们还面临着一项挑战,就是团队没有真正的得失责任。即使一个产品团队成功地使其价值流的所有干系人都参与进来,其工作的整体成本和回报对这些人来说也是不透明的。

完备的企业产品管理职责是当前困扰我们的一个问题。产品经理关注收益(收入、注册量……),而成本本身(人员编制、工资、硬件、外部服务、培训……)是工程成本中心的一部分。内部基础设施的成本或者产品的营销成本根本没有体现到产品团队上。

为了追踪行动的成本和收益,我们在数据及 KPI 可视化方面取得了很大的进步。但是,因为无法将实现成本、基础设施的成本和工作映射到这类行动上,所以通常很难评价一项实现是否增加了任何价值。

跨团队交流和整个系统的公共视图是困扰我们的另一个问题。现在,我们还不是很清楚应该如何改进我们的端到端工作流。目前,我们即将研究如何使用我们的“墙”(见图 9)作为一种方法来更好地管理我们的价值流——即所谓的看板“飞行高度(flight level)”3 4 。通过扩大业务视角,我们可以从一步一步的价值创造流程中获得新的视角……而且,为了统一监控和积极控制整个公司里正在发生的事情,我们考虑将所有领域的代表都包含进来。我们坚信,这可以提升我们的能力,让我们可以更好地区分选项,改善提前期,通过较小的努力提供更大的价值。

参考资料

  1. How Do Committees Invent? ” Melvin E. Conway
  2. 分析师瞭望:Water-Scrum-fall 是敏捷的现状”Dave West
  3. 领导自组织团队” Siegfried Kaltenecker(免费下载)
  4. 看板的飞行高度” Klaus Leopold

关于作者

Michael Gruczel esailors 移动 App 团队的团队负责人。在实际的工作中,他像仆人一样工作,但有时候又是一名具有破坏性的领导者。他曾经做过咨询顾问,为德语版的 Java Magazin 和 jaxenter 写过一些技术文章。感兴趣的读者可以通过 linkedin 、twitter( @mgruc )联系他,或者通过他的 github 个人资料了解他。

Sigi Kaltenecker是 Loop Consultancy 的联合常务董事,专注于精益和敏捷变革。他已参与了多家国际性公司的改革,包括 Alcatel、bwin.party、eSailors、Kaba、ImmoScout24、Magna、RWE、Swiss Federal Railways 或 Thales Group。Sigi 是《领导自组织团队》《看板改革领导力:创建持续改进文化》(Wiley 2015))的作者,并在“Peer Feedback Loops”上发表了一系列的文章。感兴趣的读者可以通过电子邮件(siegfried.kaltenecker@loop-beratung.at)联系他。

Hans Gruber是 eSailors 汉堡公司的工程负责人和董事总经理。他有很强的工程背景,在类似 Tele2 和 bwin.party 这样的国际性企业里逐步建立起自己的专长。他致力于通过采用精益和敏捷实践来改善团队,因为他坚信,技术和产品团队可以做到精益求精,并借此提供卓越的客户价值。感兴趣的读者可以通过 linkedin 联系他。

查看英文原文: Agile Sailors - A Journey from a Monolithic Approach to Microservices

2017-01-21 16:122333
用户头像

发布了 1008 篇内容, 共 374.9 次阅读, 收获喜欢 341 次。

关注

评论

发布
暂无评论
发现更多内容

研发过程中的文档管理与工具

Java 文档 构架 文档管理

Java避坑指南:涉及金钱计算时使用BigDecimal如何避坑

Beaver

你了解SpringBoot启动时API相关信息是用什么数据结构存储的吗?

宁在春

Java 源码 springboot 7月月更

消息队列消息数据存储MySQL表设计

泋清

#架构实战营

开源当周上Github趋势全球第三的HTAP数据库,大家都在关注它什么?StoneDB社区答疑第一期来啦!

StoneDB

数据库 云原生 OLAP HTAP StoneDB

最新发布!阿里巴巴专家亲自撰写,Dubbo 3.0 分布式实战(彩印版)

冉然学Java

Java 分布式 dubbo 框架 RPC 协议实现原理

架构实战营|模块8

KDA

#架构实战营

深度剖析 Apache EventMesh 云原生分布式事件驱动架构

老周聊架构

云原生 全球架构师峰会 ArchSummit 8月月更 Apache EventMesh

阿里技术大牛耗时几个月整理出这份Spring Cloud Alibaba学习笔记

了不起的程序猿

程序员 java\ SpringCloud Alibaba

行走的Offer收割机!首次公布Java10W字面经,Github访问量破百万

冉然学Java

MySQL Java 面试 Spring Boot CLI JVM; Redis 数据结构

Java线程

GalaxyCreater

Java

CWE4.8 -- 2022年危害最大的25种软件安全问题

Tom(⊙o⊙)

软件安全 静态代码安全

Java面向对象

GalaxyCreater

Java 面向对象

啃完阿里老哥这套Java架构速成笔记,我都能拿30K

王小凡

Java MySQL spring 程序员 面试

Apache EventMesh 分布式事件驱动多运行时

老周聊架构

云原生 事件驱动架构 全球架构师峰会 ArchSummit 8月月更

【PIMF】OpenHarmony 啃论文俱乐部—盘点开源鸿蒙三方库【3】

离北况归

OpenHarmony

这款悄然崛起的国产API接口管理工具,你一定要晓得

王小凡

Java 程序员 开发工具 后端开发 API

Jenkins + Docker + Github 实现自动化部署 Maven 项目

宁在春

Docker 运维 jenkins 签约计划第三季

自动化测试如何创造业务价值?

老张

自动化测试

Unity 之 图集属性详解和代码示例 -- 拓展一键自动打包图集工具

陈言必行

7月月更 签约计划第三季

我从Vuejs中学到了什么(一)

真嗣

前端 vuejs

架构实战营模块8消息队列表结构设计

地下地上

架构实战营

架构实战营模块 8 作业

Naoki

架构实战营

《ArchSummit:时代的呐喊,技术人听得到》

后台技术汇

后台开发 架构师 ArchSummit

elasticsearch实战三部曲之三:搜索操作

程序员欣宸

Java elasticsearch 7月月更

leetcode 665. Non-decreasing Array 非递减数列(中等)

okokabcd

LeetCode 贪心算法 算法与数据结构

架构实战营模块八作业

融冰

Python中关于函数的那点事

Java学术趴

7月月更

Java编程

GalaxyCreater

Java

深入浅出边缘云 | 4. 生命周期管理

俞凡

架构 边缘计算 网络 深入浅出边缘云

国内市场上的BI软件,到底有啥区别

石臻臻的杂货铺

7月月更

敏捷水手——单体法到微服务之旅_Scrum_Michael Gruczel_InfoQ精选文章