Name that refactoring: 1 - Version 2 44
Here is an update to the first name that refactoring based on feedback. How about this?
Step 0: Method with embedded dependency
Step 1:Extract method to move dependency to another method
Step 2: Subclass and override method with new code that does not have original dependency
So what do you think? Better or worse?
What about using the star in other image? In general, the star could represent the dependency we’re trying to get rid of.
Name that refactoring: 2 75
Ok, so I’m getting good feedback on the first picture. Now for a series of pictures.
How do you interpret this series?
Step 0
Step 1
Step 2
Step 3
Name that refactoring: 1 67
I’m working on writing up a few handouts I can use in a TDD class (and a few other places). There are a few drawings I keep doing and I’m trying to replicate them so I can refer to something.
Problem is, with many such drawings, the observation of the creation is as important as the end product. I’d like your feedback/recommendations (or links to better pictures). I’m curious about at least two things.- What does this picture suggest to you or what can you draw from it, if anything?
- Do you think this would be better served as a series of pictures showing the build-up?
Thanks for your feedback.
C++ Bowling Kata Result 65
I’m teaching a TDD and Refactoring class this week using C++. Since I had not recently wrote the bowling kata in C++, I figured it was about time to do it again.
Unlike the previous Scala version, this one only addresses the happy-path. I do not consider throwing too many balls or scoring too many pins in any frame. However, having just written this in Scala, I’m sure I could do something similar in C++.
I just switched to CppUTest 2.0 and something I noticed is that if you use <vector> or other std-based classes, you need to make sure to include those first before including <CppUTest/TestHarness.h>. This is because CppUTest overloads new and delete, which causes havoc with the std-based classes. No big deal, I just made sure to include that file as the last header (rather than the first, which is what I used to do).
Here are the various files:RunAllTests.cpp
1 2 3 4 5 |
|
BowlingScoreCardTest.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
|
BowlingScoreCard.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
BowlingScoreCard.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
I sure do miss refactoring tools!-)
Notes from the OkC Dojo 2009-09-30 66
Tonight we had a small group of die-hard practitioners working with Ruby and RSpec. We intended to use the Randori style, but it was a small enough group that we were a bit more informal than that.
We tried the Shunting Yard Algorithm again and it worked out fairly well. The level of experience in Ruby was low to moderate (which is why we wanted to get people a chance to practice it) and the RSpec experience was generally low (again, great reason to give it a try).
- Forth
- Operator precedence
- Operator associativity
- L-Values and R-Values
- Directed Acyclic Graphis
- In-fix, pre-fix, post-fix binary tree traversal
- Abstract Syntax Trees (AST)
- The list goes on, I’m a big-time extrovert, so I told Chad to occasionally tell me to shut the heck up
- 1 + 3 becomes 1 3 +
- a = b = 17 becomes a b 17 = =
- 2 + 3 * 5 becomes 2 3 5 * +
- 2 * 3 + 5 becomes 2 3 * 5 +
One typical approach to this problem is to develop an AST from the in-fix representation and then recursively traversing the AST using a recursive post-fix traversal.
What I like about he Shunting Yard Algorithm is it takes a traditionally recursive algorithm (DAG traversal, where a binary tree is a degenerate DAG) and writes it iteratively using it’s own stack (local or instance variable) storage versus using the program stack to store activation records (OK stack frames). Essentially, the local stack is used for pending work.
This is one of those things I think is a useful skill to learn: writing traditionally recursive algorithms using a stack-based approach. This allows you to step through something (think iteration) versus having to do things whole-hog (recursively, with a block (lambda) passed in). In fact, I bought a used algorithm book 20 years ago because it had a second on this subject. And looking over my left shoulder, I just saw that book. Nice.
To illustrate, here’s the AST for the first example:
Since the group had not done a lot with recursive algorithms (at least not recently), we discussed a short hand way to remember the various traversal algorithms using three letters: L, R, P
- L -> Go Left
- R -> Go Right
- P -> Print (or process)
- in-fix, in -> in between -> L P R
- pre-fix, pre, before -> P L R
- post-fix, post, after -> L R P
- in-fix: Go left, you hit the 1, it’s a leaf note so print it, go up to the +, print it, go to the right, you end up with 1 + 3
- post-fix: Go left you hit the 1, it’s a leaf node, print it, go back to the +, since this is post-fix, don’t print yet, go to the right, you get the 3, it’s a leaf node, print it, then finally print the +, giving: 1 3 +
- pre-fix: start at + and print it, then go left, it’s a leaf note, print it, go right, it’s a leaf node, print it, so you get: + 1 3 – which looks like a function call (think operator+(1, 3))
It’s not quite this simple – we actually looked at larger examples – but this gets the essence across. And to move from a tree to a DAG, simply iterate over all children, printing before or after the complete iteration; in-fix doesn’t make as much sense in a general DAG. We also discussed tracking the visited nodes if you’ve got a graph versus an acyclic graph.
After we got a multi-operator expression with same-precedence operators working, e.g., 1 + 3 – 2, which results in: 1 3 + 2 -, we moved on to handling different operator precedence.
Around this time, there was some skepticism that post-fix could represent the same expression as in-fix. This is normal, if you have not seen these kinds of representations. And let’s be frank, how often do most of us deal with these kinds of things? Not often.
Also, there was another question: WHY?
In a nutshell, with a post-fix notation, you do not need parentheses. As soon as an operator is encountered, you can immediately process it rather than waiting until the next token to complete the operator (no look-ahead required). This also led to HP developing a calculator in 1967 (or ‘68) that was < 50 pounds and around USD $5,000 that could add, subtract, multiply and divide, which was huge at the time (with a stack size of 3 – later models went to a stack size of 4, giving us the x, y, z and t registers).
During this rat-hole, we discussed associativity. For example, a = b = c is really (a = (b = c))
That’s because the assignment operator is right-associative. This lead into r-values and l-values.
Anyway, we’re going to meet again next week. Because we (read this as me) were not disciplined in following the Randori style, these side discussions lead to taking a long to fix a problem. We should have “hit the reset button” sooner, so next time around we’re going to add a bit more structure to see what happens:- The driver finishes by writing a new failing test.
- The driver commits the code with the newest failing test (we’ll be using git)
- Change drivers and give him/her some time-box (5 – 10 minutes)
- If, at the end of the current time-box, the current driver has all tests passing, go back to the first bullet in this list.
- If at the end, the same test that was failing is still failing, (fist time only) give them a bit more time.
- However, if any other tests are failing, then we revert back to the last check in and switch drivers.
Here’s an approximation of these rules using yuml.me:
(start)->(Create New Failing Test)->(Commit Work)->(Change Drivers) (Change Drivers)->(Driver Working) (Driver Working)-><d1>[tick]->(Driver Working) <d1>[alarm]->(Check Results)->([All Tests Passing])->(Create New Failing Test) (Check Results)->([Driver Broke Stuff])->(git -reset hard)->(Change Drivers) (Check Results)->([First Time Only and Still Only Newest Test Failing])->(Give Driver A Touch More Time)->(Check Results)
Note that this is not a strict activity diagram, the feature is still in beta, and creating this diagram as I did made the results a bit more readable. Even so, I like this tool so I wanted to throw another example in there (and try out this diagram type I have not used before – at least not with this tool, I’ve created too many activity diagrams). If you’d like to see an accurate activity diagram, post a comment and I’ll draw one in Visio and post it.
Anyway, we’re going to try to move to a weekly informal practice session with either bi-weekly or monthly “formal” meetings. We’ll keep switching out the language and the tools. I’m even tempted to do design sessions – NO CODING?! What?! Why not. Some people still work that way, so it’s good to be able to work in different modes.
If you’re in Oklahoma City, hope to see you. If not, and I’m in your town, I’d be interested in dropping into your dojos!
Pair with one of us at Agile 2009 20
Dean, Uncle Bob, Michale Feathers and I will be spending time in our Agile 2009 booth working on problems and pairing with volunteers.
If you’d like to join us for some pairing, please stop by.
We’ll give you an autographed “code monkey” for your efforts.
Remote Ping-Pong Challenge: Your turn, who's next? (Java) 32
So I want to try a form of TDD using Ping-Pong. Problem is, you are not where I can pair with you directly. So I figured we’d try a slower-form. I’ll post the beginning of a problem. First person to post the next response “wins” – that’s where the next person should pick up from. We’ll continue until the problem is “finished.”
Interested? First the ground rules, then the problem and the starting code. This is Java. However, if someone responds in another language, that’s cool. I might try and follow up, but you’re welcome to do so yourself. I can imagine having multiple threads going on at the same time. (If you’d like your own language thread, ask and I’ll post another blog entry for that particular language.)
Ground Rules
- Follow the three rules of TDD + Refactoring.
- Fix the one failing test.
- Add one to three more tests before posting.
- Make sure you leave one and only one failing test for the next person to fix. (Meaning you can add two passing tests but leave a third test failing, or you can just add one failing test).
- You can/should refactor the test code and the production code
- If you feel a test is wrong, you may change it, but be prepared to justify it.
- I’ll serve as the customer, so I get to define what is “correct” – however, I can be argued with and I can lose arguments (see some of my other blog postings for evidence).
- Feel free to respond with comments/suggestions rather than additional tests.
- Feel free to apply refactorings like extract method, rename, split loop, ... Keep the code clean!
The Problem
Translate infix notation to postfix notation. Consider reviewing The Shunting Yard Algorithm. But that’s a guideline.The Start
Here is the test and production code. Note, when you respond, surround your code with one of the following pairs of HTML tags:- <typo:code>, and </typo:code>
- <pre>, and </pre>
InfixToPostfixConverterTest
package com.om.example;
import static org.junit.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Collection;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class InfixToPostfixConverterTest {
private final String infix;
private final String expectedPostfix;
@Parameters
public static Collection<String[]> data() {
ArrayList<String[]> values = new ArrayList<String[]>();
addTestCase(values, null, "");
addTestCase(values, "", "");
addTestCase(values, "45", "45");
addTestCase(values, "+", "+");
addTestCase(values, "3 + 8", "3 8 +");
return values;
}
private static void addTestCase(ArrayList<String[]> values, String infix,
String expectedPostfix) {
values.add(new String[] { infix, expectedPostfix });
}
public InfixToPostfixConverterTest(String infix, String expectedPostfix) {
this.infix = infix;
this.expectedPostfix = expectedPostfix;
}
@Test
public void checkTranslation() {
InfixToPostfixConverter converter = new InfixToPostfixConverter();
String result = converter.translate(infix);
assertEquals(expectedPostfix, result);
}
}
InfixToPostfixConverter
package com.om.example;
public class InfixToPostfixConverter {
public String translate(String string) {
if(null == string)
return "";
return string;
}
}
Infinitest for Java, have you tried it? 10
Background
About 2 years ago, I was working with Ben Rady and he demonstrated something he was working on at the time: Infinitest. As often I am, I was a little interested but mostly skeptical – don’t know if that came across or not.Since then he and others (e.g., Rod Coffin have made amazing strides and created plugins for both Eclipse and IntelliJ.
Taking it for a test run
Earlier this month, I finally decided to give it a test drive. When I made that announcement, Ben made the following (bold?) statement:For me, using Infinitest is as different from TDD as TDD is from not testing
So is that true? Is using a continuous test execution tool as different from not using one as using TDD is from not testing? I’m not sure I’m there yet. However, I will say my brain is having some difficulty getting used to the cool feedback.
Here are two recent experiences I had using it.
Classpath Issues
Back at the end of 2006 I wrote a class on using JPA and EJB 3. I’ve not really done much to update that material in some years but recently I had an email from someone trying to work through the first tutorial with little success. Over the past few years there’s been some bit-rot. The embeddable container is not really up to date, EJB 3.1 includes an embeddable container as part of its spec, Hibernate has been updated, etc. So I spent a few hours tracking down updated jar files and building my classpath. I had already installed Infinitest and I noticed as added I something to my classpath, Infinitest would kick off and show a stack trace (my code was doing that in a @Before method). So I sped up what I was doing:- I directly edited the .classpath file in Eclipse
- Saved what I was doing
- Waited about a second
- Noticed the new stack trace
- Found the next jar file I needed to add
- Repeat until tests passed.
Might sound like a bit of overkill, but in the end I built a classpath from scratch and I ended up adding 13 jar files. So it saved some time.
Note, I wasn’t looking for this. I had only installed Infinitest the day before so this was unexpected and welcome! Oh, and before my @Before method was handling the exception properly, Infinitest showed that the code had a problem (it was in the @After with a null pointer exception), which it indicated as an error like a syntax error or a validation error. Nice!
Using Mockito
I’ve recently been using Mockito. You can review a previous blog entry for that example. Today we’re holding the first coding dojo at the recently opened OkC CoCo. Last night I started working on the next problem I want to use for the next dojo. It involves practicing using a mockist approach. I set up my classpath, started writing tests and immediately I noticed what looked like a syntax error on the verification step of my first unit test. I was confused thinking I had an actual syntax error since I’m not quite to the point of touch-typing Mockito based tests (I did update Eclipse so I could more easily find the static imports).Next, I updated my test to use the @Mock annotation. I removed the hand-written initialization and immediately I noticed a “syntax” error – null pointer exception. I was immediately (OK 1 second later) showed the impact of removing a single line of code. I added the missing line to auto-initialize the @Mock annotated fields but I did it incorrectly, so the error remained. I finally got the line correct and the “syntax error” went away.
Observations
Wow. That’s what I have to say so far. I’m not entirely sure the before and after of using Infinitest is the same size as moving from not testing to using TDD. Maybe it’s the same as moving from being Test Infected to practicing TDD. I was Test Infected several years before I practiced TDD.I was also about as skeptical that moving to TDD from being Test Infected was useful. I was wrong. History tends to repeat itself, so I’m guessing, based on my initial resistance, that this is the future.
Embrace it.
Challenge: How would you start this problem? 21
On Thursday, we’re holding our first Coding Dojo at the recently opened OkC CoCo. This isn’t the first Coding Dojo to happen in Oklahoma City. Some time back, Dave Nicolette held a Randori with a Fishbowl at the OkC Java User’s Group, and that’s the format I’ll be using for this problem. It was a blast then and I’m hoping it’ll be the same this time around.
This first DoJo is with C#, though I hope we manage to use several languages over time. I’d like to sneak in Smalltalk as soon as we have enough of a critical mass so we don’t lose people. I also plan to slowly introduce BDD (maybe not so slowly, who knows – depends on the group).
The recent refactoring exercises (here and here), they come from this problem. We’ll be starting from scratch, so you can probably imagine that those refactoring examples are not going to come up right away (actually probably not at all given the time).
So your challenge this time is not one of refactoring but rather one of an initial value problem. Given the problem statement, how would you go about starting it? I’m assuming TDD, do you make that same assumption? If so, what’s your first test? Your first few tests? What features do you try to tackle first? What questions do you ask yourself about the problem?
I’ve used this problem several times and it’s a great problem to practice many things including:- Test Driven Development
- refactoring (lower case r deliberate – can you guess why?)
- Refactoring to Design Patterns
- Most of the SOLID principles
Anyway, how would you go about starting this problem? Or better yet, give it a try and post your first few tests (in the order you create them).
I’ll be interested in seeing how people start and I’ll compare it to what I’ve done (hint, I use this as a class-driven thing, so I’m pretty flexible on how to start it).
p.s. As a result of studying the manual for my HP 32SII, I have a much better understanding of just how its stack works. I have a EE and CS background, so the stack implementation makes sense, but I left some of its details out of the problem.
TDDing an Interface - a Twitter influenced discussion 30
Background
I’ve collected a few quick notes regarding TDD and interfaces (as in Java/C# or C++ classes with all pure virtual methods). You dynamic-language-using-types (near irony intentional) can read and laugh to yourselves! You don’t need stinking interfaces, right?Note, these are based on a few questions from someone I follow on twitter. I considered leaving out the original poster, but since it’s on twitter, I guess that’s not really going to stay hidden. And, quite frankly, his questions are pretty good and quite common.
I’m interested in seeing what other people have to say about this.
When TDDing, I see info on using interfaces, but how do interfaces get created through TDD? How do you unit test your way to an interface?
Interfaces and TDD
There are several reasons an interface comes up while practicing TDD, here are two:- You have some existing code that has a concrete dependency on something and you want to remove that relationship.
- You are working on new production code, taking a mockist approach and you want to create an object, inject dependencies represented by test-doubles that implement interfaces that do not yet exist.
@GBGames goes on to write (remember, this was in Twitter, so I left the abbreviations and such as is):
Game uses HardwareLayer. HL used libSDL but don’t need SDL for unit tests so I wanted IHL for a mockHL. But how to get IHL? Most info I find assumes interface exists or class exists to extract interface. I feel like I’m trying to do 2 things at once.
This additional information suggests something like the following:
@GBGames suggests using an IHardwareLayer to fully get rid of libSDL, which is a fine approach. Another approach is testing the HardwareLayer directly (with unit tests on the HardwareLayer) and passing in an adapter to libSDL (basically an ILibSdl):
What are we Testing?
If the goal is to test responsibility/functionality that belongs in the Game, then creating the IHardwareLayer is the right thing to do. The game only cares about the hardware layer and not the libSDL. If the goal is to test responsibility/functionality that belongs to the Hardware Layer, then that’s where we should start. However, this decision is academic. Why? @GBGames’s original question was, in a nutshell:When using TDD to test a class that depends on an interface that does not yet exist, how do you go about doing that?He observed, correctly, that it seems like you are doing two things at the same time, and you are:
- What methods exist in the interface
- How will the class under test use that interface.
- Create interfaces
- Add methods to those interfaces needed to add functionality
- Set expectations on the use of those interfaces
- The Hardware layer, apparently, does not yet exist.
- By extension, the interface does not yet exist.
- When writing the real hardware layer class, it will ultimately have to implement all of the methods in the interface created while TDDing the game class
- Writing the actual hardware layer class will require TDDing it, and passing in an ILibSDL class. This is not strictly necessary, but if you want to test the HardwareLayer without using the real lib SDL, that’s your best option.
Now to get more concrete
So let’s assume that in fact we are starting from scratch on a game and we want to develop it without requiring a real hardware layer. Is it reasonable to assume the use of a hardware layer before we’ve even started writing the game? I say yes. What do you say? So I’d need to come up with some tests (test categories) to get started (I’m just making this up, I don’t have any idea what GBGames is actually working on right now):- Creating a game properly initializes the hardware layer
- Creating a game properly acquires some kind of game configuration information, which is used to configure the hardware layer (e.g., preferred resolution, color depth, anti-aliasing, ...) (Do you see that even these two test categories actually suggest more than just two classes if you consider the single responsibility principle.)
This is enough to start to express my intent. Almost time to start with something.
One final set of questions before I get really started:- One assertion per test?
- TDD or BDD (At the very lest, looks like we’re staring outside in)
- ...
Test 1: Initializing
How about when I create a game, I want to make sure that it sends some basic initialization to the HardwareLayer:package com.om.example.gameandhw;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.Test;
public class GameTest {
@Test
public void itShouldInitializeHardwareLayerDringGameConstruction() {
IHardwareLayer layer = mock(IHardwareLayer.class);
new Game(layer);
verify(layer, times(1)).setResolution(1024, 768);
verify(layer, times(1)).setColorDepth(8);
}
}
- On the first line, I had to create and interface IHardwareLayer, no methods.
- On the first line, I also had to stop to statically import the mock method.
- On the second line I had to stop and create the Game class.
- On the second line I had to stop and add a constructor with a parameter (the injected IHardwareLayer, for which I use the Mockito library to create a test-double, which I am using as a Spy)
- On the third line I had to stop to add the method setResolution to the IHardwareLayer interface.
- On the third line I had to stop to add the static import of the verify method.
- On the fourth line I had to stop to add the setColorDepth method to the IHardwareLayer interface.
(Trust me, it too much longer to type that list than to do the work. The actual work was well under 30 seconds to do all of that.)
After this test compiled, but did not pass, I had to write the method for Game. Here are the other two java files I created as a result of this single test (getting the test to pass the first time was included in that 30 seconds above):package com.om.example.gameandhw;
public interface IHardwareLayer {
void setResolution(int widthInBits, int heightInBits);
void setColorDepth(int bitsPerChannel);
}
package com.om.example.gameandhw;
public class Game {
public Game(IHardwareLayer layer) {
layer.setResolution(1024, 768);
layer.setColorDepth(8);
}
}
Now I have no idea if this is even beginning to make any sense for the original problem. This is where having a pair partner with expertise on the game requirements (and maybe some idea about this libSDL) would greatly help.
Notice, however, that as I try to write the Game class, I am adding methods to the IHardwareLayer class AND figuring out how the game will interact with those methods.
Hope this helps GBGames. I also hope to see some discussion in the comments section.
Brett