构建持续交付_如何使交付成为您的重点将如何帮助您构建高质量的应用程序

构建持续交付

by Simon Schwartz

西蒙·施瓦茨(Simon Schwartz)

如何使交付成为您的重点将如何帮助您构建高质量的应用程序 (How making delivery your focus will help you build quality applications)

I was recently asked by our company’s executive team why our team was able to develop improvements to our product so quickly. This blog outlines some key guidelines, from a technical point of view, that our team followed to x iterate our product at speed safely. I tried my darndest to stay high level in this post while still providing technical details. The techniques we talk about aren’t things that we invented.

公司执行团队最近问我为什么我们的团队能够如此Swift地开发出对我们产品的改进。 该博客从技术角度概述了一些关键准则,我们的团队遵循这些准则来安全快速地迭代我们的产品。 我尽我最大的努力使这篇文章保持高水平,同时仍然提供技术细节。 我们谈论的技术不是我们发明的东西。

My fellow tech comrades on the team and I saw it as our role to reduce the friction to delivering value to our users. We also aimed to maintain a high quality of the applications we were responsible for. We did a large part of this by removing, simplifying, and automating the processes around delivering updates to our production codebase.

我的团队中的技术同志,我将其视为减少为用户提供价值的摩擦的角色。 我们还旨在保持我们负责的应用程序的高质量。 我们通过删除,简化和自动化将更新交付到生产代码库的过程来完成了大部分工作。

Keep in mind there are some projects that may have inherent complexity. Some of the techniques our team used may not fit your project. From my experience, working with legacy software can make it hard or impossible to simplify certain processes truly.

请记住,有些项目可能具有固有的复杂性。 我们的团队使用的某些技术可能不适合您的项目。 根据我的经验,使用旧版软件可能很难或不可能真正简化某些流程。

使交付成为重点 (Make delivery the focus)

Our team prioritized delivering frequent improvements to the production codebase above everything else. Well almost — we put things like mental health, letting people take a day off if they were sick, and being nice ahead of delivery.

我们的团队优先考虑对生产代码库进行频繁的改进,而不是其他所有方面。 好吧,几乎-我们采取了心理健康之类的措施,让人们在生病的时候可以放假一天,并在分娩前保持良好状态。

Code in production is the goal. We made sure that all ideas, designs and feature requests had a clear path for how we were going to get it to production. One technique we used to re-enforce this was only to show working code in showcases. We banned powerpoints and design mockups. We also found this made our showcases more engaging and interesting.

生产中的代码是目标。 我们确保所有想法,设计和功能要求都有一条明确的路线,说明我们如何将其投入生产。 我们用来加强此功能的一种技术只是在展示柜中显示工作代码。 我们禁止使用Powerpoint和设计模型。 我们还发现这使我们的展示柜更具吸引力和趣味性。

Meetings are optional. We found that this encouraged people who called meetings to articulate the purpose and value of the meeting clearly. It was up to team members to decide if they should attend a meeting. We wanted to prevent developers from being unnecessarily interrupted. It can take upwards of 30 minutes for someone to return to a productive state after being interrupted.

会议是可选的。 我们发现,这鼓励召集会议的人清楚地阐明会议的目的和价值。 由团队成员决定是否应参加会议。 我们希望防止开发人员受到不必要的干扰。 某人被打扰后可能要花费30分钟以上的时间才能恢复到生产状态。

Spend time solving user problems, not technology problems. We wanted to avoid spending countless hours discussing what technology to use or building our own technology. We used AWS Lambda so we didn’t have to think about servers and scaling. We used Create React App so we didn’t have to worry about build configuration for our front end app. We made early tech decisions and stuck to them.

花时间解决用户问题,而不是技术问题。 我们希望避免花费无数时间讨论要使用的技术或构建自己的技术。 我们使用了AWS Lambda,因此我们不必考虑服务器和扩展。 我们使用了Create React App,因此我们不必担心前端应用程序的构建配置。 我们做出了早期的技术决策并坚持了下来。

我们试图避免。 (? What we tried to avoid.)

  • We avoided spending weeks building our own tooling or frameworks when we could re-use them from elsewhere.

    当我们可以从其他地方重用它们时,我们避免花费数周时间来构建自己的工具或框架。
  • We avoided adding unnecessarily complex processes or ceremonies to the team. This included convoluted kanban boards or agile processes that weren’t benefiting us.

    我们避免向团队添加不必要的复杂流程或仪式。 其中包括混乱的看板或敏捷流程,这些都没有使我们受益。
  • We avoided spending weeks designing, building and supporting features that had no proof they would be useful to our users. Our design team did a great job of designing features based on user feedback and analytics.

    我们避免花费数周的时间来设计,构建和支持功能,而这些功能并没有证明它们对我们的用户有用。 我们的设计团队在基于用户反馈和分析的功能设计方面做得非常出色。

使部署成为非事件 (Make deployments a non-event)

Having a rapid release cycle meant we could get new features out to our users as soon as they were ready. We also recovered from bugs and outages much quicker. A major challenge of high-frequency deployments is moving at pace without introducing bugs. Automating this process is critical as it vastly reduces the time and effort it takes to deploy updates.

快速的发布周期意味着我们可以在用户准备就绪后立即向他们推出新功能。 我们还可以更快地从错误和中断中恢复。 高频部署的主要挑战是在不引入错误的情况下按步伐移动。 自动化此过程至关重要,因为它可以大大减少部署更新所需的时间和精力。

Automate the deployment. Rapid delivery requires the deployment process to be as frictionless as possible. Luckily nowadays we have many tools that can automate the entire deployment process. I recommend tools such as CircleCI and TravisCI. Our setup was when the new code was added to the release branch, the code was automatically deployed by our deployment tool.

自动化部署。 快速交付要求部署过程尽可能无摩擦。 幸运的是,如今,我们有许多工具可以自动化整个部署过程。 我建议使用CircleCI和TravisCI之类的工具。 我们的设置是在将新代码添加到release分支后,该代码由我们的部署工具自动部署。

Write (and automate) tests. When deploying code changes automatically, it is critical to understand the impacts the changes will have and to stop deployments that introduce bugs or regressions. This means we needed to write tests that confirm the code is functioning as expected.

编写(和自动化)测试 。 当自动部署代码更改时,至关重要的是了解更改将产生的影响并停止部署会引入错误或回归的部署。 这意味着我们需要编写测试以确认代码是否按预期运行。

Whenever we integrate new code to a release branch, the CI tool automatically runs our test suite. Any failures in the test suite will cancel the deployment process. Developers would also run this test suite locally to confirm everything worked before pushing changes. Automated testing is also much quicker, less cumbersome and less prone to human error than manual testing.

每当我们将新代码集成到发布分支时,CI工具都会自动运行我们的测试套件。 测试套件中的任何失败都将取消部署过程。 开发人员还将在本地运行该测试套件,以在推动更改之前确认一切正常。 与手动测试相比,自动测试还更快,更麻烦并且更不容易出现人为错误。

Delivering at speed doesn’t work if all new code needs to be manually tested by a human for an hour. As a team, we agreed that we would write tests for all the code we wrote. For cases where it wasn’t practical to write tests, we would need to give a reason. Any time we fixed a bug, we would also write a test that covered the bug. We made sure that we had tests for common user interactions and journeys (integration tests). As well as tests for the individual functions that made up our applications(unit tests).

如果所有新代码都需要人工人工测试一个小时,则无法快速交付。 作为一个团队,我们同意为所有编写的代码编写测试。 对于编写测试不切实际的情况,我们需要给出一个理由。 每当我们修复错误时,我们还将编写覆盖该错误的测试。 我们确保已针对常见的用户交互和旅程进行了测试(集成测试)。 以及组成我们应用程序的各个功能的测试(单元测试)。

Small frequent updates. Updating our codebase in small increments increased the rate we delivered improvements to our users. Small updates are easier to integrate into the codebase. Our code review process became more rigorous. It was easier and quicker for developers to review small pull requests. It is much easier to identify issues and impacts of new code because the surface area of the code was so small.

少量频繁更新。 以较小的增量更新代码库可以提高我们为用户提供的改进速度。 较小的更新更易于集成到代码库中。 我们的代码审查过程变得更加严格。 对于开发人员而言,审查小型拉取请求更容易,更快捷。 由于代码的表面积很小,因此识别新代码的问题和影响要容易得多。

One technique we found useful was moving the design quality assurance(QA) audit process to the pull request level. This made the QA process more focused and quicker as opposed to when it carried out every few days on a large set of multiple changes. As a team, we made an agreement that we would keep PRs small.

我们发现一种有用的技术是将设计质量保证(QA)审核过程移至拉动请求级别。 与每隔几天对大量更改进行一次质量检查相比,这使质量检查过程更加集中,更快。 作为一个团队,我们达成了一项协议,我们将使PR保持较小。

We also agreed that we would review PRs within half a day. If we weren’t able to review within that time frame, we needed to let the author know.

我们还同意,我们将在半天之内审查PR。 如果我们无法在该时间范围内进行审核,则需要告知作者。

我们试图避免。 (? What we tried to avoid.)

  • We avoided manually doing tasks that we could otherwise automate.

    我们避免了手动执行本来可以自动化的任务。
  • We avoided risks associated with deploying a large amount of code all at once. It’s not uncommon to deploy code that has bugs that are not picked up or bugs that only surface when the code runs at scale. The larger the surface area of our deployments, the larger the impact these issues will have.

    我们避免了一次全部部署大量代码带来的风险。 部署具有未被发现的错误或仅在代码大规模运行时才浮出水面的错误的情况并不少见。 我们的部署的表面积越大,这些问题将产生的影响越大。

使更改代码简单安全 (Make changing code simple and safe)

“To me, there is only one definition of well designed code. Well designed code is code that is easy to change” — Dave Thomas
“对我来说,只有一个定义良好的代码定义。 设计良好的代码就是易于更改的代码” – Dave Thomas

Having the ability to deploy code changes on demand is pointless if changing the code is hard and time-consuming. Writing code that is easy to understand and update helps us iterate at speed. As a technical team, we kept each other accountable through our code review process to ensure we were writing code as clearly and simply as possible.

如果更改代码既困难又耗时,则能够按需部署代码更改就毫无意义。 编写易于理解和更新的代码有助于我们快速迭代。 作为技术团队,我们在代码审查过程中互相追究责任,以确保我们尽可能清楚,简单地编写代码。

Write modular and reusable code. Functions are the building blocks of our applications. These functions should be small, decoupled and have a single purpose. This makes it easier for developers to follow and understand the logic of the application. It’s easier to repurpose existing functions to reduce the amount of code written. Changing functions is much safer because the surface area of function is so small. The effects of the change are easier to understand. As a team, we would carefully review each others pull requests and give feedback to help each other write the best code we could.

编写模块化和可重用的代码。 功能是我们应用程序的基础。 这些功能应小巧,分离,并具有单一目的。 这使开发人员更容易遵循和理解应用程序的逻辑。 重新利用现有功能以减少编写的代码量更加容易。 更改功能要安全得多,因为功能的表面积很小。 更改的影响更容易理解。 作为一个团队,我们将仔细检查彼此的拉取请求并提供反馈,以帮助彼此编写尽可能好的代码。

Write code for humans. There are two primary users of the code we write: computers who run the code and humans who read and change the code. Most developers are pretty good at writing code for computers. If your code runs or complies without bugs — it means you did a good job writing code for the computer. Some developers forget about writing code for humans. If the code is hard to understand it will take longer for developers to understand and update the code. We focused on making it clear the purpose, outputs, and inputs of each function.

为人类编写代码。 我们编写代码的两个主要用户:运行代码的计算机和阅读和更改代码的人员。 大多数开发人员都擅长为计算机编写代码。 如果您的代码运行或遵照执行,没有错误-这意味着您在编写计算机代码方面做得很好。 一些开发人员忘记了为人类编写代码。 如果代码难以理解,开发人员将需要更长的时间来理解和更新代码。 我们专注于明确每个功能的目的,输出和输入。

The inputs and outputs of functions were made clear with the type system. We used the inbuilt type system when using Go, and Flow when using JavaScript.

类型系统使功能的输入和输出变得清晰。 使用Go时使用内置类型系统,使用JavaScript时使用Flow。

We chose descriptive names for our variables. This made it clearer what data the variable held or what function is performed.

我们为变量选择了描述性名称。 这样可以使变量保存哪些数据或执行什么功能变得更加清晰。

// Both these functions do the same thing
function a(arr) {  return arr.filter(it => it.age < 30)}
function getUsersUnder30(userList) {  return userList.filter(user => user.age < 30)}

Write testable code. Whenever we change the code we need to be sure our changes have not regressed the previous functionality of the code. This is one of the great benefits of having tests. It adds a level of safety to making code changes. We made our lives easier by writing code in a way that made it simple to write tests for. A technique for writing code that is easy to test, is to use pure functions.

编写可测试的代码。 每当我们更改代码时,都需要确保所做的更改未使代码的先前功能退步。 这是进行测试的巨大好处之一。 它为更改代码增加了一定的安全性。 通过以简化编写测试的方式编写代码,使生活变得更轻松。 编写易于测试的代码的技术是使用纯函数

A pure function is a function that given the same inputs, will always return the same outputs. These functions are super simple to test. If you are interested in learning more about pure functions Eric Elliot has a fantastic article describing pure functions.

纯函数是给定相同输入的函数,将始终返回相同的输出。 这些功能非常易于测试。 如果您有兴趣了解有关纯函数的更多信息,那么Eric Elliot有一篇很棒的文章描述了纯函数 。

Unfortunately, you cannot write a function as a pure function if it has side effects. A side effect is something that operates outside of the scope of its function. This could be operations such as writing a file or sending an API request. Side effects can be tricky to test at the unit level, so these were separated from our pure functions.

不幸的是,如果函数具有副作用 ,则不能将其编写为纯函数。 副作用是超出其功能范围的事情。 这可能是诸如写入文件或发送API请求之类的操作。 在单位级别测试副作用可能很棘手,因此将这些副作用与我们的纯函数分开了。

我们试图避免。 (? What we tried to avoid.)

  • We avoided wasting time manually testing scenarios that we could automate.

    我们避免了浪费时间手动测试可以自动化的方案。
  • We avoided compromising code quality for speed. Compromising code quality for speed is redundant. Not only are you more likely to introduce bugs, but you are also creating a codebase that will eventually be very hard to change and debug. This will significantly slow down your ability to deliver new features and bug fixes.

    我们避免为了速度而牺牲代码质量。 为了速度而牺牲代码质量是多余的。 您不仅更有可能引入错误,而且还创建了最终将很难更改和调试的代码库。 这将大大减慢您交付新功能和错误修复的能力。

Thanks for reading!

谢谢阅读!

翻译自: https://www.freecodecamp.org/news/making-delivery-the-focus-techniques-for-delivering-quality-applications-222b79d301d9/

构建持续交付

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/393177.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微信退款通知,退款回调数据解密.SHA256签名AEAD_AES_256_GCM解密

$xmlResult file_get_contents("php://input");//获取微信的数据$result $this->xmlToArray($xmlResult);//将xml转成数组 // 将加密的数据解密,方法在下面$reqInfo $this->refund_decrypt($result[req_info]); /** 退款通知解密* Author WangZhaoBo* param…

BeanShell自动装箱拆箱

“装箱”和“拆箱”是用来描述自动包装一个原始类型到一个包装类以及在必要时解开包装回到原始类型的术语。装箱是 Java 的特性&#xff08;SDK 1.5&#xff09;之一&#xff0c;且 BeanShell 已支持多年。 BeanShell 支持原始类型的装箱和拆箱。比如&#xff1a; int i5; Inte…

leetcode816. 模糊坐标

我们有一些二维坐标&#xff0c;如 “(1, 3)” 或 “(2, 0.5)”&#xff0c;然后我们移除所有逗号&#xff0c;小数点和空格&#xff0c;得到一个字符串S。返回所有可能的原始字符串到一个列表中。 原始的坐标表示法不会存在多余的零&#xff0c;所以不会出现类似于"00&q…

IO流入门-第十二章-ObjectInputStream_ObjectOutputStream

DataInputStream和DataOutputStream基本用法和方法示例&#xff0c;序列化和反序列化 import java.io.Serializable; //该接口是一个“可序列化”的 &#xff0c;没有任何方法&#xff0c;是一个标识接口&#xff0c;还有Cloneable /*标识接口的作用&#xff1a;标识作用…

matlab pca重构,Matlab – PCA分析和重建多维数据

这是一个快速的演练.首先我们创建一个隐藏变量的矩阵.它有100个观察,有两个特点.>> Y randn(100,2);现在创建一个加载矩阵.这将把隐藏的变量映射到观察到的变量上.说你观察到的变量有四个特征.那么你的加载矩阵需要是24>> W [1 1; 1 -1; 2 1; 2 -1];这告诉你,观察…

文档对象模型dom_什么是文档对象模型,以及为什么应该知道如何使用它。

文档对象模型domby Leonardo Maldonado莱昂纳多马尔多纳多(Leonardo Maldonado) 什么是文档对象模型&#xff0c;以及为什么应该知道如何使用它。 (What’s the Document Object Model, and why you should know how to use it.) So, you’ve studied HTML, you’ve created y…

安装Docker step by step

1. 系统要求 centos7以上 使用cat /etc/redhat-release查看系统版本&#xff0c;我的Centos 7.6 centos-extra 仓库 enable&#xff0c;默认是打开的 2.安装docker docer安装分为联网安装和离线安装两种安装 方式&#xff0c; 第一种 在有外网环境下安装docker,一般使用yum安…

linux用户空间和内核exit的语义--linux没有线程

如果你在程序中调用了exit&#xff0c;那么很显然你的程序会退出&#xff0c;可是至于为何会退出那就是库的事情了&#xff0c;我为什么说只是库的事情而不关linux内核的事情呢&#xff1f;那是因为linux内核根本不管用户空间的行为策略。库的策略是什么&#xff1f;很简单的退…

leetcode1328. 破坏回文串

给你一个回文字符串 palindrome &#xff0c;请你将其中 一个 字符用任意小写英文字母替换&#xff0c;使得结果字符串的字典序最小&#xff0c;且 不是 回文串。 请你返回结果字符串。如果无法做到&#xff0c;则返回一个空串。 示例 1&#xff1a; 输入&#xff1a;palindro…

php补充 扩展,PHP安装扩展补充说明

上一篇文章中用到了&#xff0c;php的sodium扩展&#xff0c;那么如何安装PHP扩展呢&#xff1f;基于我之前踩过的一些坑&#xff0c;大致整理了几种安装php扩展的方法。已安装sodium为例1、先做点准备工作&#xff0c;安装sodium依赖rpm -ivh http://mirrors.whsir.com/centos…

Java调用存储过程出现Bug,sql语法错误

因为SQL Server运行没有正常,检查了传入参数的值,发现问题,然后传入默认参数,解决了问题.转载于:https://www.cnblogs.com/JimmySeraph/p/11043490.html

leetcode1438. 绝对差不超过限制的最长连续子数组

给你一个整数数组 nums &#xff0c;和一个表示限制的整数 limit&#xff0c;请你返回最长连续子数组的长度&#xff0c;该子数组中的任意两个元素之间的绝对差必须小于或者等于 limit 。 如果不存在满足条件的子数组&#xff0c;则返回 0 。 示例 1&#xff1a; 输入&#…

gitlab 2.7版本升级到2.8

第一步 关闭服务 /etc/init.d/gitlab stop第二部 更新代码cd /home/gitlab/gitlab# Get latest codesudo -u gitlab git pull origin stable# Install libssudo -u gitlab bundle install --without development test# update dbsudo -u gitlab bundle exec rake db:migrate RA…

arkit技术介绍_面向移动AR的触觉技术:如何以“触摸”感增强ARKit应用

arkit技术介绍by Neil Mathew通过尼尔马修(Neil Mathew) 面向移动AR的触觉技术&#xff1a;如何以“触摸”感增强ARKit应用 (Haptics for mobile AR: how to enhance ARKit apps with a sense of “touch”) I’m really excited about the future of haptics for AR and VR. …

Unity3D的坑系列:动态加载dll

Unity3D的坑系列&#xff1a;动态加载dll 我现在参与的项目是做MMO手游&#xff0c;目标平台是Android和iOS&#xff0c;iOS平台不能动态加载dll&#xff08;什么原因找乔布斯去&#xff09;&#xff0c;可以直接忽略&#xff0c;而在Android平台是可以动态加载dll的&#xff0…

微信小程序 php配置,微信小程序的配置

我们使用app.json文件来对微信小程序进行全局配置&#xff0c;决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。以下是一个包含了所有配置选项的简单配置app.json{"pages": ["pages/index/index","pages/logs/index"],"wi…

leetcode332. 重新安排行程(dfs)

给定一个机票的字符串二维数组 [from, to]&#xff0c;子数组中的两个成员分别表示飞机出发和降落的机场地点&#xff0c;对该行程进行重新规划排序。所有这些机票都属于一个从 JFK&#xff08;肯尼迪国际机场&#xff09;出发的先生&#xff0c;所以该行程必须从 JFK 开始。 …

PWA - service worker - Workbox(未完)

Get Started&#xff08;开始&#xff09; 只有get请求才能cache缓存吗&#xff1f;Create and Register a Service Worker File&#xff08;创建和注册 Service Worker&#xff09; Before we can use Workbox, we need to create a service worker file and register it to o…

draft.js_如何使用快捷方式在Draft.js中创建有序列表和无序列表

draft.jsby Andrey Semin通过安德烈塞米(Andrey Semin) 如何使用快捷方式在Draft.js中创建有序列表和无序列表 (How to create ordered and unordered lists in Draft.js with a shortcut) We at Propeller have encountered many differences between Draft.js and popular t…

当javaScript从入门到提高前需要注意的细节:变量部分

到了HTML5的时代&#xff0c;对javaScript的要求不是降低了&#xff0c;而是更提高了。javaScript语言的入门非常简单&#xff0c;如果你有java、C#等C风格的结构化语言的基础&#xff0c;那javaScript你最多半天就可以写点什么了。但是javaScript是一种动态语言&#xff0c;这…