跳到主要内容

保存的文章

在我的机器上工作

Dave Nicolette |领导敏捷
戴夫王匡
读: 在我的机器上工作

连续交付的最危险障碍之一(以及普遍存在的软件交付中的连续流动)是工作机器的现象。任何在软件开发团队或基础架构支持团队工作过的人都经历过。工作的人这样的团队听到期间(未遂)演示说出这句话。问题是如此普遍,甚至还有它徽章:

也许你已经赢得了自己这个徽章。我有一些。你应该看看我的奖杯室。

敏捷团队有一个长期以来的传统,可能起源于世纪之交的ThoughtWorks。它是这样的:当有人违反了古老的工程原则,“不要故意做任何愚蠢的事情,”他们必须支付罚款。惩罚可能是往球队的零食罐里扔一美元,或者更糟糕的事情(对于内向的技术人员来说),比如站在球队面前唱歌。用“<耸耸>在我的机器上工作!”< /耸耸肩>”资格。

可能不可能在所有情况下都避免这个问题。就像阿甘说的,你知道他是怎么说的。但我们能够通过关注一些明显的事情,最大限度地减少问题。(是的,我明白了“明显”是被特意用了一个词。)

缺陷1:遗留的配置

问题:从以前的工作中的剩余配置使代码能够在其他环境中失败时为开发环境(以及测试环境也是如此)。

陷阱2:开发/测试配置不同于生产

这个陷阱的解决方案与陷阱1的解决方案非常相似,所以我将把这两种方法分组。

解决方案(TL; DR):不重复使用环境。

常见情况:许多开发人员设置了他们喜欢的笔记本电脑/桌面或团队共享开发环境的环境。环境从项目到项目的增长,因为添加了更多库,并设置了更多的配置选项。有时,配置彼此冲突,团队/个人通常会根据此刻的项目处于活动状态进行手动配置调整。开发配置与目标生产环境的配置变得非常不同。在生产系统上可能不存在于开发系统上存在的库。假设您可以使用与生产中的不同版本的不同版本的产品相同的产品来运行本地测试。在开发,测试和生产环境中发生的性能和不可预测的差异。这种情况不仅在开发期间创造了挑战,而且在我们试图复制报告的行为时,在生产支持期间也会产生挑战。

解决方案(长):为每个项目创建孤立的专用开发环境

实际的方法不止一种。你可能会想到几个。以下是几种可能性:

  • 提供新的VM(本地,在您的机器上)。(我不得不添加“本地,在您的机器上”,因为我了解到在许多较大的组织中,开发人员必须跳过官僚程序才能访问VM,而VM是由一个单独的功能筒仓来管理的。去图。)
  • 你是在一个孤立的环境中进行开发吗(包括在测试自动化金字塔的较低级别中的测试,如Docker或类似。
  • 在基于云的开发环境中进行开发这是在定义新项目时由云提供商提供的。
  • 设置您的持续集成(CI)管道为了为每个构建/测试运行提供新鲜的VM,以确保从最后一个构建中留下任何可能污染当前构建结果的内容。
  • 设置连续交付(CD)管道为更高级别的测试和生产提供新的执行环境,而不是将代码和配置文件推广到现有环境(出于同样的原因)。请注意,此方法还为您提供了在构建/部署循环的正常过程中浏览,样式检查和验证配置脚本的优势。方便的。

所有这些选项对于每个可想到的平台或堆栈都不会是可行的。选择并选择自己卷起。一般来说,如果您在Linux上工作,所有这些事情都很容易。所有这些都可以为其他* NIX系统完成一些努力。他们中的大多数与窗户相当容易;有许可的唯一问题,以及贵公司有企业许可证,您都设置了。对于其他平台,例如IBM ZOS或HP NORSTOP,期望做一些手工滚动工具。

凡是在你的情况下是可行的,并且可以帮助您隔离您的开发和测试环境会有所帮助。如果你不能做所有这些事情在你的情况,不用担心。只要做你能够做。

在本地提供新的VM

如果您正在运行Linux,FreeBSD,Solaris,Windows或OSX的桌面,笔记本电脑或共享开发服务器,那么您处于良好状态。您可以使用虚拟化软件,如VirtualBox或者VMware默默站起来拆除当地的VM。对于较少的主流平台,您可能必须从源代码构建虚拟化工具。

有一件事我通常建议是,开发培育懒惰的态度本身。那么,合适的懒惰,即。您不应该觉得不止一次地感到完全高兴地配置服务器。在第一次供应练习期间花时间脚跟你沿途发现的东西。那么你不必记住它们并再次重复相同的错误步骤。(嗯,除非你请享用当然是这一类的事情。)

例如,以下是我在需要设置开发环境时想到的一些配置脚本。这些都是基于Ubuntu Linux和Bash编写的。我不知道他们会不会帮你,但他们在我的机器上工作。

如果您的公司在生产环境中运行RedHat Linux,您可能需要调整这些脚本,以便在CentOS或Fedora上运行,这样您的开发环境将与目标环境相当接近。没什么大不了的。

如果你想变得更懒,你可以使用像这样的工具流浪汉简化VM的配置定义。

还有一件事:无论您为配置工具编写了什么脚本和定义文件,请将它们与每个项目一起置于版本控制之下。确保给定项目的版本控制中的内容是一切必要的要处理该项目...代码,测试,文档,脚本......一切。这是比较重要的,我想。

在容器中开发

隔离开发环境的一种方法是在容器中运行它。当您搜索包含容器的信息时,您将阅读大多数工具管弦乐集工具旨在帮助我们管理多个集装箱,通常在生产环境中。对于地方发展的目的,你真的不需要那么多的功能。有一对夫妇为了这个目的实用的容器:


这些都是基于linux的。对您来说,容器化开发环境是否可行取决于您需要什么技术。为了容器化另一个操作系统(如Windows)的开发环境,可能不值得仅仅运行一个成熟的VM。对于其他平台,可能不可能将开发环境容器化。

在云中发展

这是一个比较新的选项,它一组有限的技术是可行的。在建立本地开发环境的好处是,你可以站在一个新的环境,对每一个项目,保证你不会有任何部件或从以前的工作留下的配置设置。这里有几个选项:


期待看到这些环境的改善,期待看到更多的参与者进入这个市场。检查支持哪些技术和语言,看看其中是否有一种适合您的需求。由于变化的速度非常快,所以没有必要列出本文截止日期为止可用的内容。

作为CI构建的一部分,从一般生成测试环境

一旦您有了一个用于旋转VM或配置容器的脚本,就很容易将其添加到CI构建中。的优势是,您的测试将运行在原始环境中,无假阳性的可能性由于剩下的配置从以前版本的应用程序或其他应用程序之前共享相同的静态测试环境,测试数据修改的还是因为以前的测试运行。

许多人有脚本,他们已经攻击了简化他们的生活,但它们可能不适合无人值守的执行。您的脚本(或用于解释声明性配置规范的工具)必须能够在不发出任何提示(例如提示管理员密码)的情况下运行。他们还需要是幂等的(即,在重新启动的情况下,在多次运行它们不会造成任何伤害)。必须在脚本运行时可通过必须提供给脚本的任何运行时值,并且在每个运行之前不需要任何手动“调整”。

“生成环境”的想法可能对某些堆栈感到不可行。广泛提出建议。对于一个Linux环境,每当需要时创建VM很常见。对于其他环境,您可能无法做到确切地那个,但可能有一些步骤可以基于一般概念打败创造环境。

举例来说,一个团队在CICS应用工作在IBM主机上可以定义并运行它作为一个标准的工作开始CICS环境中的任何时间。在80年代初,我们用来做常规。作为上世纪80年代一拖再拖(和整个90年代和21世纪初持续,在某些组织),企业的IT世界变得越来越官僚化,直到此功能拍摄的开发商手中了。

奇怪的是,截至2017年,截至2017年很少的开发团队有选择运行自己的CICS环境进行实验,开发和初始测试。我说“奇怪”,因为我们的工作生活的许多其他方面急剧改善,而那个方面似乎已经在逆行中搬迁。我们没有在我们应用程序的前端工作的问题,但是当我们搬到后端时,我们通过一种时间崩溃。

从一个纯技术角度出发,没有什么可以从这样做停止开发团队。它有资格作为在我看来“产生的环境中,”。您不能运行“云”或“上VM”一CICS系统(至少,不是2017年),但你能够申请“云思维”对管理资源的挑战。亚傅体育app

同样,您也可以将“云思维”应用于环境中的其他资源。亚傅体育app用你的想象力和创造力。毕竟,不是为什么选择这一工作领域?

实时生成生产环境为您的CD管道的一部分

此建议与前一个建议相同,除了它稍后在CI / CD管道中发生。一旦您有某种形式的自动部署到位,您可以扩展该过程以包括自动旋转VM或自动重新加载和配置硬件服务器作为部署过程的一部分。此时,“部署”真的意味着创建和配置目标环境,而不是将代码移动到现有环境中。

这种方法解决了许多超越了简单的配置差异问题。举例来说,如果黑客已经推出任何生产环境,重建那个环境了源,你控制消除了恶意软件。人们发现有一个在重建生产机器和价值的虚拟机频繁,即使没有更改为“部署,”因为这个原因,以及当我们随着时间的推移将更改应用于长时间运行的情况下发生忌“配置偏差”。

许多组织在生产中运行Windows服务器,主要是支持要求操作系统的第三方包。部署到现有Windows Server的问题是许多应用程序需要在目标实例上存在安装程序。一般来说,在任何生产实例上都有安装人员释放的信息安全人员。(FWIW,我同意他们的意见。)

如果您从受控源中的速度创建Windows VM或配置Windows Server,则在配置完成后,您不需要安装程序。您不会重新安装应用程序;如果需要更改,则会重建整个实例。您可以在生产之前准备环境,然后删除用于提供它的任何安装程序。所以,这种方法不仅仅是工作机器问题。

当涉及到zOS这样的后端系统时,您将不需要为生产部署构建自己的CICS区域和lpar。在这种情况下,“云思维”是拥有两个相同的生产环境。然后,部署就变成了在两个环境之间切换流量的问题,而不是迁移代码。这使得在不影响客户的情况下更容易实现生产版本。它也有助于缓解工作机器问题,因为在交付周期后期的测试发生在真正的生产环境中(即使客户还没有指出)。

对此通常的反对意见是支持双环境的成本(即支付给IBM的费用)。这种反对意见通常是由那些没有充分分析所有延迟和返工成本的人提出的。

陷阱三:不愉快的意外,当代码合并

问题:不同的团队和个人以各种方式处理代码退房和办理登机手续。有些退出代码一次并在项目过程中修改它,可能在几周或几个月内。其他人经常提交较小的变化,每天更新当地副本并进行许多次的更改。大多数球队落在了极端之间的某个地方。

通常,代码检出的时间越长,对其进行的更改越多,合并时发生冲突的可能性就越大。你也很可能忘记了你做每一个小修改的原因,其他修改了相同代码块的人也会忘记。合并可能是一件麻烦事。

在这些合并事件期间,所有其他增值工作将停止。每个人都在试图找出如何合并这些变化。脾气爆发。每个人都可以准确地宣称,该系统在他们的机器上运行。

解决方案:避免这类事情的一个简单方法是频繁地提交小的更改,在每个人的更改到位的情况下运行测试套件,并在内存消失之前快速处理小的冲突。这大大减少了压力。

最好的一点是,您不需要任何特殊的工具来完成此操作。这只是一个自律的问题。另一方面,只需要一个人长时间地检出代码,就会把其他人搞得一团糟。要意识到这一点,并善意地帮助你的同事建立良好的习惯。

缺陷4:晚发现集成错误

问题:这个问题与陷阱3类似,但一个抽象级别更高。即使一支团队经常提交小型更改并使用每次提交运行全面的自动测试套件,它们也可能遇到与解决方案的其他组件相结合的重要问题,或者与上下文中的其他应用程序交互。

代码可以在我的机器上工作,以及我的团队的集成测试环境,但一旦我们迈出了下一步,就会松散。

解决方案:这个问题有几个解决方案。第一是静态代码分析。它成为连续集成流水线的标准,包括静态代码分析作为每个构建的一部分。这发生在编译代码之前。静态代码分析工具将源代码视为文本,查找已知导致集成错误(以及其他内容)的模式。

静态代码分析可以检测代码,如循环依赖和高圈复杂度,以及像死代码等基本问题和侵犯编码趋向于增加克鲁夫特在代码库标准的结构性问题。这只是那种克鲁夫特导致合并麻烦,太多。

相关建议是从静态代码分析工具和编译器中获取任何警告级别的错误真实的错误。累积警告级别错误是在运行时最终结束神秘的,意外行为的好方法。

第二种解决方案是集成组件并经常运行自动化的集成测试套件。设置CI管道,以便在所有单元级检查通过后,自动执行集成级检查。让该级别的失败破坏构建,就像处理单元级别检查一样。

通过这两种方法,您可以在交付管道中尽早检测集成误差。你发现问题的前面,修复更容易。

陷阱5:部署是噩梦般的通宵马拉松

问题:大约2017年,它仍然经常会发现那里的人“发行方”时,他们部署代码到生产组织。发行方就像是通宵兄弟会派对,只是没了乐趣。

问题是,第一次应用程序在类似的环境中执行,是在实际生产环境中执行的。当团队试图部署到生产时,许多问题只会变得可见。

当然,没有时间或预算为此。匆忙工作的人可能会以某种方式获得系统并运行,但通常以稍后以生产支持问题的形式出现的回归成本。

并且完全是因为在交付管道的每个阶段,系统“在我的机器上工作”,是否是开发人员的笔记本电脑,与生产不同的共享测试环境,或其他一些不可靠的环境。

解决方案:该解决方案是在整个交付管道中配置每个环境,尽可能接近生产。以下是您可能需要根据当地情况进行修改的一般指导方针。

如果您有一个登台环境,而不是两个生产环境,那么应该将所有内部接口配置为活动的,而将外部接口配置为存根的、模拟的或虚拟化的。即使这是你的想法,它可能会消除发布聚会的需要。但是如果可以的话,最好继续在管道上游进行,以减少在推进代码时意外的延迟。

开发和登台之间的测试环境应该运行与生产版本相同的操作系统和库。它们应该根据要执行的测试范围在适当的边界被隔离。

在管道的开始阶段,如果可能的话,可以在与生产相同的操作系统和通用配置上进行开发。您可能没有生产环境中那么多的内存或处理器。开发环境也不会有任何活动接口;应用程序外部的所有依赖项都是假的。

至少,尽可能将操作系统和发布级别与生产环境匹配起来。例如,如果您将部署到Windows Server 2016,那么使用Windows Server 2016 VM来运行快速CI构建和单元测试套件。Windows Server 2016基于nt10,所以请在Windows 10上进行开发工作,因为它也基于nt10。同样,如果生产环境是Windows Server 2008 R2(基于NT 6.1),那么在Windows 7(也基于NT 6.1)上进行开发。你不可能消除每一个配置差异,但你将要能够避免大多数的不兼容性。

遵循与Linux目标和开发系统的相同拇指规则。例如,如果您将部署到RHEL 7.3(内核版本3.10.x),则可以在可能的情况下运行单元测试如果可能的情况下。否则,请根据您的生产RHEL查看(或构建)基于同一内核版本的CentOS版本(不假设)。在最小的情况下,基于与目标制作实例相同的内核版本的Linux发行版的运行单元测试。在CentOS或基于Fedora的发行版上进行开发,以尽量减少与Rhel的不一致。

如果您使用的是动态基础设施管理方法,其中包括从源代码构建OS实例,那么这个问题就更容易控制了。您可以从相同的来源构建开发、测试和生产环境,以确保整个交付管道的版本一致性。但现实是,截至2017年,很少有组织以这种方式管理基础设施。更有可能的情况是,您将基于发布的ISO配置和供应操作系统实例,然后从私有或公共repo安装包。您必须密切关注版本。

如果您在自己的笔记本电脑或桌面上进行开发工作,您正在使用跨平台语言(Ruby,Python,Java等),您可能会认为您使用的操作系统并不重要。您可能在Windows或OSX上有一个很好的开发堆栈(或其他)您对您感到满意的。即便如此,它是一个好主意旋转一个靠近生产环境的操作系统,只是为了避免意外的惊喜。

对于开发的嵌入式开发,其中开发处理器与目标处理器不同,在低级TDD周期中包含编译步骤,其中包含针对目标平台的编译器选项。这可以暴露在您编译开发平台时不会发生的错误。有时,在不同处理器上执行时,相同的库的相同版本将表现出不同的行为。

嵌入式开发的另一个建议是将您的开发环境限制为具有与目标平台相同的内存限制和其他资源限制。通过这样做,您可以提前捕获某些类型的错误。

对于一些较旧的后端平台,有可能为了方便做开发和单元测试平台外。在输水管道相当早,你会想你的源上传到目标平台和球泡/测试那里的环境。

例如,对于HP direct上的c++应用程序,使用任何编译器和CppUnit这样的单元测试框架,在您喜欢的任何本地环境(假设这对应用程序类型是可行的)上执行TDD是很方便的。

同样,使用Gnucobol在Linux实例上进行COBOL开发和单元测试方便;比使用OEDIT在平台上更快,更容易进行细粒度TDD。

但在这些情况下,目标执行环境与开发环境非常不同。您希望在送货管道早期锻炼代码,以消除工作机器惊喜。

概括

作者的观察是工作机器问题是开发商的压力和时间损失的主要原因之一。笔者进一步指出的主要原因工作机器问题在于跨开发、测试和生产环境的配置差异。

基本建议是尽可能避免配置差异。努力确保所有环境与实际生产环境一样相似。请注意操作系统内核版本、库版本、API版本、编译器版本以及任何自定义实用程序和库的版本。当差异无法避免时,就记录下来,并将其视为风险。将它们封装在测试用例中,以提供任何问题的早期警告。

第二个建议是频繁地自动化如在不同的抽象级别多的测试成为可能,合并代码,经常构建应用程序,经常运行自动测试套件,频繁部署,以及(如果可行)经常建立执行环境。这将帮助你发现问题早,而最近的变化还是新鲜的在你的心中,并且在问题仍然较小。

让我们来修复这个世界,这样的下一代软件开发人员不理解这句话,“作品在我的机器。”

下一个;学生QA:定义完成与Scrum在一个营销团队与德里克Huether

戴夫王匡一直是IT专业自1977年以来,他曾在各种技术和管理职位。他主要担任顾问自1984年以来,保持一只脚在技术阵营,一个在管理阵营。

评论(2)

  1. Raja Nagendra Kumar.
    回复

    这种响应明确表示团队/系统的原始工程技能。没有适当的CI / CD的产品工程不需要考虑产品

    回复
  2. 钢筋混凝土
    回复

    Bravo!本文正好击中钉子:“我的机器上的构建”谬误不仅仅限于开发人员工作站,而是所有静态的“宠物”服务器,包括生产。

    它惊讶于,2018年,在他们的单位测试中了解Setup()和Teardown()概念的相同开发人员不理解将相同的部署环境应用于其部署环境的重要性。因此,他们的服务器不可避免地像雪花一样独特,并且部署到生产成为轮盘赌轮的旋转。

    如果你不能够创建虚拟机或容器“对飞”,然后在最起码,你应该在每次使用后对每个后续周期中清洗你的环境,然后从代码重建它们的配置(例如Ansible)。这包括生产。

    回复

留下你的评论

您的电子邮件地址不会被公开。必需的地方已做标记