📄 continuousintegration.html
字号:
<head><title>Continuous Integration</title></head><body><h1><img src="logo.gif"> Continuous Integration</h1>Conventional code management systems use techniques like check-in/check-out to help you be sure you're working on the current version when you edit something. Development teams use <a href="http://c2.com/cgi/wiki?CodeOwnership">CodeOwnership</a> to minimize conflicts among people editing. The longer engineers hold on to modules, the more important it is to minimize conflicts.
<p>What if engineers didn't hold on to modules for more than a moment? What if they made their (correct) change, and <em>presto!</em> everyone's computer instantly had that version of the module?
<p>You wouldn't ever have <a href="IntegrationHell.html">IntegrationHell</a>, because the system would always be integrated. You wouldn't need <a href="http://c2.com/cgi/wiki?CodeOwnership">CodeOwnership</a>, because there wouldn't be any conflicts to worry about.
<p><strong>Note:</strong> You can't release unless the code works. Therefore to have <a href="ContinuousIntegration.html">ContinuousIntegration</a>, you must have <a href="http://c2.com/cgi/wiki?RelentlessTesting">RelentlessTesting</a>. And if your testing process takes days (and some legitimately may), then <a href="ContinuousIntegration.html">ContinuousIntegration</a> may not work for you since much work must go on in parallel with the testing. Even in such a case, however, it depends on the probability that the class will be edited again before testing completes.
<p><hr>
<p><em>How is <a href="ContinuousIntegration.html">ContinuousIntegration</a> related to the idea of building in <a href="http://c2.com/cgi/wiki?HorizontalStripes">HorizontalStripes</a>? I would like to assert that the practices described here are the micro-view of <a href="ContinuousIntegration.html">ContinuousIntegration</a>, while <a href="http://c2.com/cgi/wiki?HorizontalStripes">HorizontalStripes</a> is the macro-view. Or are they totally separate concepts? -- <a href="http://c2.com/cgi/wiki?BillBarnett">BillBarnett</a></em>
<p><hr>
<p><strong>A thread on <a href="news:comp.object">news:comp.object</a> and <a href="news:microsoft.public.visual.sourcesafe">news:microsoft.public.visual.sourcesafe</a> currently attempts to determine the workflow for <a href="ContinuousIntegration.html">ContinuousIntegration</a> using Visual <a href="http://c2.com/cgi/wiki?SourceSafe">SourceSafe</a>. If the thread can find one, I'l summarize it on a page, and link that here. In a more appropriate location. --<a href="http://c2.com/cgi/wiki?PhlIp">PhlIp</a> [8 Jan 2000]</strong>
<p><hr>
<DL><dt> <dd><em>The macro process of object-oriented development is one of "continuous integration." ... At regular intervals, the process of "continuous integration" yields executable releases that grow in functionality at every release. ... It is through these milestones that management can measure progress and quality, and hence anticipate, identify, and then actively attach risks on an ongoing basis.</em>
<p></DL>--<a href="http://c2.com/cgi/wiki?GradyBooch">GradyBooch</a>, <strong>Object-Oriented Analysis and Design with Applications</strong>, 2nd ed.
<hr>
<strong>Please</strong> enter here the things that make you think this won't work. XP takes the position that <a href="ContinuousIntegration.html">ContinuousIntegration</a> is a good enough thing to make it work, and we do. Interrogating us will help us answer how we made it work. --<a href="RonJeffries.html">RonJeffries</a>
<p><strong>Having lots of people working on the same class can only lead to chaos, unreliability, and the warm heat death of the universe.</strong>
<p><em>That turns out not to be the case. You have complete <a href="UnitTests.html">UnitTests</a> to test that class, and all the other classes with which it may collaborate. No code is released unless all the unit tests work.</em>
<p><strong>The guy who edits my class may not be as good as I am.</strong>
<p><em>Partner with him. Both of you will learn something. Besides, what do you mean by "my class"?</em>
<p><strong>What if I'm changing the class and you are, and our changes conflict?</strong>
<p><em>This happens very rarely in practice, especially if you have lots of small classes (which you should). When it does, the person releasing is responsible for resolving conflicts. Our code manager tells us when you are releasing a version which is not based directly on the current release. This means someone slipped in ahead of you. Browse changes, sit with them if need be, resolve and release.</em>
<p><strong>What if you release from your machine and I release from mine and we step on each other's changes?</strong>
<p><em>It hurts when you do that. Don't do that. Consider having a single releasing machine. Go to it, load your changes, test, release. This makes releasing single-threaded, which makes it quite simple to detect conflicts.</em> ( <a href="http://c2.com/cgi/wiki?SingleReleasePoint">SingleReleasePoint</a> )
<p>Single release machines are good. Although we allow developers to version and release code that they have tested, we don't update a config map and create a package until the code has been tested on a single machine, integrated with all of the other changes. That way, if all is not well, we can recover by reloading the previous map. The new map is created on the same single machine. (Matt Stephenson)
<hr>
<p>C3 engineers release their code frequently, generally daily. Everyone loads the config frequently, generally more than once a day. The code you are working on is the official released version, all the time.
<p>This works because we use <a href="http://c2.com/cgi/wiki?RelentlessTesting">RelentlessTesting</a> to ensure that there are no regressions. Our <a href="UnitTests.html">UnitTests</a> tell us right away if we have broken anything. We run a subset of our <a href="FunctionalTests.html">FunctionalTests</a>, called <a href="http://c2.com/cgi/wiki?CoffeeTalk">CoffeeTalk</a>, as well. We push code to production weekly or more often. Our <a href="FunctionalTests.html">FunctionalTests</a> are run before push to make the final check that we're OK.
<p>The result is that we can go very fast. And we avoid <a href="IntegrationHell.html">IntegrationHell</a>. See <a href="ContinuousIntegrationRelentlessTesting.html">ContinuousIntegrationRelentlessTesting</a>. --<a href="RonJeffries.html">RonJeffries</a>
<hr>
<em>Jim, many thanks for your contribution here. You know tons more about BIG projects than I do (or ever hope to). I've tried three times even to formulate questions and responses and not having much luck. More thought needed. I put a couple interleaved requests for clarification below, please check 'em and respond. </em>
<p><em>I think we may need to split the <a href="ContinuousIntegration.html">ContinuousIntegration</a> issues and the <a href="http://c2.com/cgi/wiki?CodeOwnership">CodeOwnership</a> issues apart to tease out the contexts. --Ron</em>
<p>I've worked both on projects where <a href="ContinuousIntegration.html">ContinuousIntegration</a> works and
on ones where it fails.
The success of this technique has something to do with the complexity
of the version space. I also think it may be rooted in an assumption
that the most interesting versions are temporal and fade with time, as
deltas (user-owned temporal changes) do in a delta/MR/MR list/release
hierarchy.
<p><em>Yes ... the fundamental assumption of CI is that there's only one interesting version, the current one.</em>
<p>If you have a simple delivery stream that easily
maps to the source stream, I can see it working fine. But consider
5 different projects working from the same source (where a project
corresponds to a corporate revenue stream working on its own
schedule). The source can be configured
to produce any one of several images. But there are more than 5 images.
Because of staged testing (individual, subsystem, integration, and
acceptance) there are 4 major versions of each of these 5 images. Each
of these versions may contain different changes. And in each of those
major versions, there may be slightly different images for each of three
processor types. It actually gets more complicated because of separately
marketable features (of which there are thousands). There is a possibility
of having hundreds of virtual hands in a piece of code at any given time.
<p><em>When you say hundreds of virtual hands, do you mean "if you don't have ownership" or "even if you do have ownership"?</em>
<p>Such systems are real; I know of many of them. They solve their problems
either with code ownership or with onerous methodological techniques
that are unbelievably cumbersome--the latter quickly discover <a href="http://c2.com/cgi/wiki?CodeOwnership">CodeOwnership</a>.
<p>To convince you that this doesn't easily lend itself to
an architectural solution would take more
space than I care to spend here. The simple answer is that feature
intrinsically cuts across function and structure, so any simple geometric
partitioning is hopeless. Or you can think of <a href="http://c2.com/cgi/wiki?AspectOrientedProgramming">AspectOrientedProgramming</a>
as an analogy (or metaphor, or something) for the problem, where
aspects correspond to features or to deltas that don't fade in time.
<p><em>It's the fact that feature cuts across function that drives us away from <a href="http://c2.com/cgi/wiki?CodeOwnership">CodeOwnership</a>. If we want to go fast, the person doing the feature needs to add all the function, no matter what class he needs to touch. Then, to avoid complex integration problems, we integrate as close to continuously as possible.</em>
<p>The problem with <a href="ContinuousIntegration.html">ContinuousIntegration</a> is manifest in the second paragraph
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -