- Raw code is here (racing car katas)
- Visit the above url to fork (top right), then clone the code
- The Tennis demo code is here
- ...but you will be working with the racing car katas
- Your task is to use parallel change to create
Alarm.Check(bool setAlarm)
- You have some choices:
- Use your code from the earlier dependency injection exercise
- Add a call to
alarm.Check
in an existing test (eg Foo)- It will pass or fail randomly if you don't have dependency injection yet, but that's not the point of this exercise so can be ignored
- If you have made no changes to tests yet:
- Rename the Foo test to AlarmIsSetWhenPressureLow
- Change Assert.False to Assert.True
- If you run it repeatedly, the test will pass or fail randomly
- Start with the C# dependency-injection-demo branch:
mkdir racing-car2
cd racing-car2
git clone https://github.com/claresudbery/Racing-Car-Katas.git
cd Racing-Car-Katas
git checkout dependency-injection-demo
- Your job is to create a version of
Alarm.Check
with asetAlarm
flag- add a test that expects alarms not to be set when the flag is set to false
- create a duplicate method with a flag
- then gradually change the clients to use the version with the flag
- and finally get rid of the old version
- If you finish the above exercise, replace
Check(bool setAlarm)
with two methods:CheckAndSetAlarm
andCheckWithNoAlarm
- Keep the code compiling and tests passing at each tiny change
- Code from the coding demo can be seen here
- Your task is still the same as in exercise 1
- There are two parts to this exercise (if you have time): First duplicate method with flag, then create two new methods
- Replace
Alarm.Check()
withAlarm.Check(bool setAlarm)
:- Make a new version of
Alarm.Check
that takes a flag:bool setAlarm
- Add a new test:
AlarmNotSet_WhenFlagFalse_ForLowPressure
- can be a copy of existing low pressure test
- Pass false through to Check method (means you'll be calling the new method)
- Change assertion to expect False instead of true
- Run test - will fail initially
- Make test pass
- Update the new version of Alarm.Check to act on the flag
- Change other clients
- In other tests, pass true to method
- Check tests pass
- Remove original version of
Alarm.Check()
- Check tests pass
- Make a new version of
- Note: There is an alternative way of doing the parallel change, which is to give a default value
- Not possible in all languages
- Can be done like this: Make
Alarm.Check
take a flag:setAlarm
:- Add
bool setAlarm = true
- Add a new test:
AlarmNotSet_WhenFlagFalse_ForLowPressure
- can be a copy of existing low pressure test
- Pass false through to
Check
method - Change assertion to expect False instead of true
- Run test - will fail initially
- Make test pass
- Update
Alarm.Check
to act on the new flag
- Update
- Change other clients
- In other tests, pass true to the
Check
method - Check tests pass
- In other tests, pass true to the
- Remove default value in
Check
method- Check tests pass
- Add
- The main kind of parallel change (where you temporarily have 2 duplicate methods) is also used for "Remove flag argument" refactoring:
- Create new method:
public void CheckAndSetAlarm()
- It will just call
Check(true);
- It will just call
- Create new method:
public void CheckWithNoAlarm()
- It will just call
Check(false);
- It will just call
- Run tests - should still pass
- Gradually replace calls in AlarmTest.cs to use the two new methods
- Keep running tests after each change
- Finally make original method private
- Run tests!
- This is parallel change because both versions existed side by side for a while
- In more straightforward examples, you wouldn't even keep a private method
- With a straightforward if statement and two code branches, can just move each branch to new method
- But this example is still helpful because client code is easier to read, and the two public methods effectively document what the flag does in the private method
- Create new method: