Your Code is Not a Version: How 'Build for Disable' can bring you true continuous integration

马上开始. 它是免费的哦
注册 使用您的电邮地址
Your Code is Not a Version: How 'Build for Disable' can bring you true continuous integration 作者: Mind Map: Your Code is Not a Version: How 'Build for Disable' can bring you true continuous integration

1. Presenter Info

1.1. Nicholas Tuck

1.1.1. Work at AFWA for AFWWEBS

1.2. This preso url: buildfordisable.nicholastuck.com

1.3. Previous Brown Bags

1.3.1. TDD

1.3.2. Unit Testing

1.3.3. Pair Programming

1.4. TheSoftwareGardener.com

1.5. twitter: @nicholastuck

1.6. Find me on G+ (not kidding) seriously...

2. The Goals

2.1. Be productive... every day

2.2. Stop fearing merging and start improving your product confidently

2.3. Thought Experiment

2.3.1. Stop thinking of your code as a version and Start thinking of your code as a living entity

3. The Room for Improvement

3.1. Feature Branch

3.1.1. aka Branch by Version Control

3.1.2. Each feature has it's own branch

3.1.2.1. See Graph (1a)

3.1.3. This process can work but not productive

3.1.3.1. Most features merged at the end

3.1.3.1.1. This week != fun

3.1.3.1.2. Requires the entire team

3.1.3.1.3. Often relies heavily on the most knowledgeable team members

3.1.3.2. Merge first != win

3.1.3.2.1. Sometimes it feels good though

3.1.3.3. Constant testing on branches have limited value

3.1.3.3.1. Last minute integration adds bugs that were already fixed individually, but have been reintroduced due to merging complications and last minute testing

3.1.3.3.2. We have to redo alot tests after integration points and all merges

3.1.3.3.3. See Confidence Graph (1b)

3.1.3.4. Duplicate Work

3.1.3.4.1. See Duplicate Work Graph (1c)

3.1.3.4.2. Ever fix the same thing as someone else?

3.1.3.4.3. Daily pulls do NOT fix this

3.1.3.5. Large Feature Problem

3.1.3.5.1. Major feature missed code cut off

4. Simple Solution

4.1. Commit Constantly and Push Hourly

4.1.1. This is not just DVC - commit hourly. This is actually push to the public repo hourly.

4.1.1.1. See CI Graph (2a)

4.1.2. Push When Exactly?

4.1.2.1. - Worked on a feature for a few hours - Added tests around all the work - Push your code out to everyone else

4.1.2.2. - Fixed a small bug - Only a handful of lines of code - Write the test - Push the code

4.1.2.3. - Working a big feature that will take days, maybe weeks - Write a couple hours worth - Push it to everyone

4.1.3. Why This is Better

4.1.3.1. When you push daily you merge daily

4.1.3.1.1. No more nightmare merges

4.1.3.2. Continuous Testing

4.1.3.2.1. Constant integration means testing at any point is testing the entire state of the sprint

4.1.3.2.2. Confidence is incredibly high at the end of a sprint

4.1.3.3. Eliminates Duplicate Work

4.1.3.3.1. We are literally at the latest changeset, we have all the work that exists

4.1.3.3.2. We can actually start helping eachother

4.1.3.4. Large Features Add Value Constantly

4.1.3.4.1. Large features consist of lots of small improvements

4.1.3.4.2. Every improvement makes it into the baseline as soon as as possible

4.1.3.4.3. See Change/Time Graph (3)

4.1.4. Rules That Have to Change

4.1.4.1. Taboos

4.1.4.1.1. Never commit code that doesn't fully work

4.1.4.1.2. Never commit commented code

4.1.4.2. Rules to Re-enforce

4.1.4.2.1. Don't break the build!!

5. Build for Disable Techniques

5.1. Code Example: OldMath vs NewMath

5.1.1. Original Code

5.1.2. Code can be found on my Bit Bucket

5.2. Simple if check with a static boolean

5.2.1. Code example

5.3. Add a method for the alternative approach and static boolean

5.3.1. Code Example

5.3.1.1. Tests

5.3.2. Writing tests could be challenging as you enable and disable

5.3.2.1. Make this boolean protected and set it for pertinent tests

5.3.2.2. When deleting old math, remove corresponding tests

5.4. Extend the class and override the methods you want to change. Point the app config at the new class, and to disable point to old class

5.4.1. Code example

5.4.2. This keeps tests separated from the other tests

5.4.3. When deleting Old Math copy the old tests into new test class and walk all failing tests

5.4.3.1. Ideally it will be deleting old/changed functionality

5.4.3.2. Maybe you broke something unintended

5.5. Actually USE interfaces!!

5.5.1. Decorator Pattern (sorta)

5.5.1.1. Code example

5.5.1.1.1. Old Math Imp

5.5.1.2. Tests and Class can stay in place if desired, doesn't require being merged later

5.5.1.2.1. Sometimes this is a good design, sometimes not

5.6. Leads to better coding practices in general

5.6.1. Sometimes you find out, this is better architectually and that functionality shouldn't be mixed in where it was

5.6.2. Writing code in separate and distinct groups is easier to test, easier to maintain

5.7. BONUS

5.7.1. Comment It Out

5.7.1.1. Hide Buttons

5.7.1.1.1. // showAwesomeFeatureButton();

5.7.1.2. Disable Web Service

5.7.1.2.1. // @RequestMapping(value = "/export", method = { RequestMethod.POST }) public ...

5.7.1.3. Short Circuit new functionality

5.7.1.3.1. // satellite.maskUglyAreas(THE_NO_KIDDING_THRESHOLD);

6. Why Isn't Everyone Doing This? Introducing 'Build for Disable'

6.1. Few teams are implementing true continuous integration because we believe our code exists in versions

6.1.1. We believe we are working to deliver an idealized version of our code to production

6.1.1.1. Implied (ABC) versions in Graph 1

6.1.1.2. This version of code is on a pedestal

6.1.1.2.1. Only 100% done code is comitted

6.1.1.2.2. Only Code that works without bugs is committed (yah right)

6.1.1.2.3. All features undone are in a different version

6.1.1.2.4. It's like the superhero of all code versions

6.1.1.3. We try to have the public repo represent perfect versions of the code

6.1.1.3.1. This gives us warm fuzzies

6.1.1.4. Why We Do This

6.1.1.4.1. We tend to develop processes around our tools

6.1.1.4.2. Our single mitigation on how not to ship a product with half working features or buggy features

6.2. The Solution

6.2.1. Your Code is NOT a Version!

6.2.1.1. Your code IS a living entity

6.2.1.1.1. It is always

6.2.1.1.2. It's being fed while you push code

6.2.1.1.3. It's being exercised under test

6.2.1.1.4. It's being relieved during refactoring

6.2.1.1.5. It is basically alive

6.2.1.2. Stop looking back at what might be a stable version

6.2.1.3. Spend more time looking ahead and creating the product we want to ship

6.2.1.3.1. (Bad) Car Analogy

6.2.2. Introducing 'Build for Disable' aka Branch by Abstraction (VS Branch by Source Control) (Similar to Feature Toggle)

6.2.2.1. What is it?

6.2.2.1.1. Build significant changes so that they can be trivially disabled

6.2.2.1.2. When producing the product for a release

6.2.2.1.3. We don't fall back

6.2.2.2. An example for comparison

6.2.2.2.1. Show Failed Feature Graph (1e)

6.2.2.2.2. Show Failed Feature Graph (2d)

7. In closing

7.1. Your code as a version

7.1.1. See Graphs (1)

7.1.1.1. Versioned progress

7.1.1.2. Low confidence

7.1.1.3. Feature pulling fiasco

7.2. Your code alive

7.2.1. See Graphs (2)

7.2.1.1. Steady progress

7.2.1.2. Consistent confidence

7.2.1.3. Disabling mechanisms

7.3. Review Goals

8. Questions?

8.1. How do you manage peer reviews with everyone's code mixed together

8.1.1. Fisheye and Mercurial do a pretty good job

8.1.2. Spend 5 minutes to cleanup your peer review for others

8.1.3. Peer reviewing other's code isn't bad but sometimes it's undone

8.2. Does this only work if there exists a good automated test suite on the project?

8.2.1. No, it helps even more

8.2.1.1. This means most of your testing is done manually

8.2.1.2. Merging at the end means repeating all manual efforts and re-troubleshoot very difficult problems while merging

8.2.1.3. Merging along the way means any manual tests are done across that integration

8.2.1.3.1. Gaining more confidence and more manual test coverage throughout the iteration

8.3. When do we remove the extra and disable code?

8.3.1. When it makes sense

8.3.1.1. Once the team accepts the code and is ready to make the feature production

8.3.1.2. Once the risks of the feature are overcome

8.3.1.3. Once everyone feels comfortable with the burn in time

8.3.1.4. Basically when your team is ready

8.4. When do we peer review the code? Before disable code is removed or after?

8.4.1. Both

8.4.1.1. You will want a full review of the code before disable code has been removed so that the team can agree to move forward with the code

8.4.1.2. Then you will need a very quick/easy follow up review of removing the disable code and the extra tests