![]() |
Articles Feed |
Categories
Archives
- December 2008 (3)
- November 2008 (5)
- October 2008 (4)
- September 2008 (6)
- August 2008 (4)
- July 2008 (5)
- June 2008 (5)
- May 2008 (4)
- April 2008 (2)
- February 2008 (4)
- January 2008 (2)
- December 2007 (2)
- November 2007 (2)
- October 2007 (2)
- September 2007 (1)
- August 2007 (3)
- July 2007 (1)
- June 2007 (4)
- May 2007 (7)
- April 2007 (2)
- February 2007 (3)
- January 2007 (3)
- November 2006 (3)
- October 2006 (3)
- September 2006 (17)
- November 2004 (1)
Rails Migrations and Subversion
by: paul | September 28th, 2006 | 22 comments »
In rails, migrations are generated like so
paul-pagels-computer:~/RailsProjects/project paulpagel$ ruby script/generate migration CreatePacketTimestamp exists db/migrate create db/migrate/013createpacket_timestamp.rb
This creates a numbered migration with an up and a down schema direction. This has been incredibly helpful when dealing with the schema changes. The problem our team has found is doing migrations with subversion.
You run migrations by
paul-pagels-computer:~/RailsProjects/project paulpagel$ rake migrate
Which looks in the schema_info table to find which version of the schema your database is representing, and updates it to the most recent version (the highest number).
The problem comes into play when you have multiple people making migration scripts on their local machine at the same time. If two different people did a migration at the same time and committed them you would end up with two migrations. Which one gets run?
I am not sure how to solve this one yet. I have been loving rails, but this has already has put a dampener on it.
Ruby and Human Compilers
by: paul | September 26th, 2006 | 0 comments »
In Paul Graham’s Book, Hackers and Painters, he talks about patterns and Human Compilers. I started to think about how some traditional Object-Oriented patterns are implemented in different languages. What problems do these patterns solve?Paul Graham’s human compiler is an interesting concept I would like to explore more with relation to ruby, which is what I have been working in lately. The object-oriented design patterns I have been taught are intended for one reason, to increase productivity. These patterns produce well decoupled, easily testable, clean, and reused code that makes it easier for developers to extend and maintain an application. It is the mind of the developer that produces this compiler to be able to read and interpret these patterns to perform workflow optimizations. When I see a pattern in the code, I can easily navigate the implementation and the problem that it is solving. I can hold the entire context in my mind to work on that piece of code. This human compiler is what allows me to move quickly through an unfamiliar piece of code. Moving to dynamic languages, I see the context I need shrinking in the traditional way, holding onto patterns. So I started to wonder, could we build patterns into the language better, or eliminate the need for them? Are the GOF patterns mostly just a method of satisfying our human compiler for statically typed languages?
I have suspicions that moving to ruby from C++/C#/Java will eliminate the need for many of the design patterns we have coveted in those languages. I would like to explore a few of them to prove this thesis. I want to look at the patterns that have helped make testing/design/decoupling better and see how they are different in ruby. Also, how can we transfer the values behind those patterns? The patterns were all based on good decisions, and can we learn anything from them or should we throw away the thought process that made them necessary?
Lets start by taking the most commonly used pattern, Abstract Server. Writing in C#, I need to create interfaces to make sure I don’t violate the Interface –Segregation Principle and depend on concrete classes. This becomes a big deal in a statically typed language because you don’t want to have to depend on a specific type. However, in ruby, you respond to messages of a class, which don’t care what type the return values are. Also, because it is a compiled language, you don’t want to have to recompile the clients of a class just because the implementation changes. In fact, in ruby, the Interface-Segregation violation goes away since there is no need for explicit interfaces to abstract, rather every class becomes an interface for itself.
Have you ever been working on a java/C++/ C# project and noticed an inheritance hierarchy that makes you twinge? Statically typed languages abuse inheritance by definition. Why do you need interfaces? Shouldn’t an abstraction be one of behavior? In ruby, you send messages to objects, which is the same type of firewall, as each object acts as its own interface. However, since an inheritance tree got there, you need to decouple it since it is growing large and not maintainable. Or have you seen interfaces placed in front of a class for the sole value of abstraction. A good example of this I have seen is with Views in the Model/View/Presenter pattern. Something that looked like this:
- public interface ISomeView
- {}
- public class SomeView : ISomeView
- {//some implementation}
This uses the philosophy that the Views need to be decoupled from the Presenters. This is true, but the point of decoupled is missed. Decoupling is a method of using firewalls to hide the implementation of code from its clients (Abstract Server). How does this degenerate do this? It doesn’t. I have seen projects where inheritance is used liberally and there are interfaces for everything. I have also seen projects where inheritance is used conservatively and composition is used for everything, to prevent the formation of highly coupled inheritance trees. Finding the proper balance in static languages is difficult, but it is also a problem that should not exist. In ruby, inheritance is used on a YAGNI basis, as you only use it in the clearest of cases. It makes inheritance a tool to be used rather than monitored for abuses.
In ruby, you only inherit through necessity of behavior rather than clarity for form. Inheritance in most static languages is used as a tool for design patterns to make the code easier to read/work on/maintain for the developers. This is unnecessary in ruby since it is built into the language. Ruby does it instead of your human compiler. Writing beautiful code in java meant making the code clean and decoupled. Inheritance is no longer needed to do that in ruby, as it only serves a utilitarian purpose. Form is just as important in ruby as it is in static languages, it is just expressed without using features meant to serve efficiency purposes.
Self Shunt
by: paul | September 11th, 2006 | 34 comments »
The self-shunt method of testing has been conflicting for me. Self-shunt is a good testing pattern to test observers/views. A colleague of mine has started to convince me that self-shunt has some serious drawbacks. I want to explore the different ways to address the same pattern and how they fit into the test process and the test content. Are certain patterns easier to write and certain ones have a better final form?
Lets look at some code from Michael Feathers self shunt paper (see bottom for link). I extended it to do the mocking examples. The user story we are working with is the name of an item must be displayed on the led when the item is scanned.
Writing all of the tests did not require a concrete window (Display). We didn’t need to create the stub of the file to use; we could just use the interface. All the test patterns let the test be isolated in the test class/interface/production class triad. As a developer, it is easier for me to produce faster without quality loss if my context of thought is limited as much to the scope of the test as possible. Each extra window I switch is more contexts to deal with.
Here are three different tests:
- public class ScannerTest extends TestCase implements Display
- {
- private Item lastItem;
- public void testScan()
- {
- Item item = new Item("corn flakes");
- Scanner scanner = new Scanner(this);
- scanner.scan(item);
- assertEquals(item,lastItem);
- }
- public void displayItem(Item item)
- {
- lastItem = item;
- }
- }
The first test is making user of self-shunt test. Self-shunt was a quick way to start writing a test. The implementation on the interface in the test class will give you a good idea on what the implementation of the concrete class should look like when you get there. Also, the test is simple and the syntax is expressive. However, the scalability is questionable. If you had more than one self-shunted interface in a single test file, it would be hard to start differentiating between which variables are used in which. Also, moving around the file to get a good sense of what a test is doing is misdirectional and distracting. Ideally, I want to see the entire test on one screen, so I can read it. If there were many implemented methods in a test file that were not tests or helpers, there is the potential to be confused.
- public class ScannerTest extends TestCase
- {
- public void testScan()
- {
- Item item = new Item("corn flakes");
- Display mockDisplay = new MockDisplay();
- Scanner scanner = new Scanner(mockDisplay);
- scanner.scan(item);
- assertEquals(item,((MockDisplay)mockDisplay).lastItem);
- }
- }
- public class MockDisplay implements Display
- {
- public Item lastItem;
- public void displayItem(Item item)
- {
- lastItem = item;
- }
- }
Then I wrote the hand mock test. This test got rid of the clutter of implementing interfaces in the test and having local variables. Also, there are no external libraries needed, like a dynamic mocking library. The test is simple and easy to read. The biggest drawback is dealing with the hand mock test file. It is untested code that I have seen a tendency for behavior to slip into, which is disastrous. It can cause a bug in your tests that take too long to track down. Ideally this doesn’t happen, but I have seen it many times.
- public class ScannerTest extends TestCase
- {
- public void testScan()
- {
- MockControl control = MockControl.createControl(Display.class);
- Display mockDisplay = (Display) control.getMock();
- Item item = new Item("");
- mockDisplay.displayItem(item);
- control.replay();
- Scanner scanner = new Scanner(mockDisplay);
- scanner.scan(item);
- control.verify();
- }
- }
Finally the dynamic mock test was written. This test was the simplest to write as a matter of process also the fewest lines of code. I never needed to leave the scope of the test function. It was just setting up my expectations and letting the test run. As Micah Martin pointed out to me, the test execution seems backwards and unreadable with dynamic mocks. The verification statements are at the beginning of the method and the execution is at the end. This is different than all the other tests in the system that follows an intuitive flow cycle of build, operate, and check.
With a little investigation I found Michael Feathers paper on Self Shunt (www.objectmentor.com/resources/articles/SelfShunPtrn.pdf).
Sentential Testing
by: paul | September 7th, 2006 | 4 comments »
In a project I have been working on, we recently decided to allow wrapped assertions to customize our unit tests. Our purpose was to make the unit tests be sentential enough to explain the meaning of the assertion in the execution of the assertion.
We can’t get rid of all developer comments (variable and method names) because, if we did, we would lose the ability to easily read and, consequently, easily maintain the code. In fact, writing easily readable code is a primary goal of good practices, since it is directly correlated with making code easily maintainable. This is important because maintenance is the most expensive part of the development process. However, we must be cautious about writting comments, since they can often have the opposite effect‚ less maintainable code‚ when they are misrepresentations or plain lies. There is a balance that results in easily read and understood tests. Investing in writing tests to tell a story to the developers who may have to look at the tests in the future, makes maintenance and TDD easier and with a better flow.
We chose to achieve this balance by merging the assertions with the comments of the execution of the test, resulting in a pseudo-sentence. The statement is an explanation for the next developer to read. The form we chose is
Verify.That(positiveAssertionString).ProvedBy(subject).verb(predicate);
An example of one of these assertions is
public void test_PressingBrakesShouldDecelerateVehicle()
{
- int originalSpeed = vehicle.currentSpeed;
- vehicle.brake();
- Verify.That(‚"Brakes decelerate vehicle.").ProvedBy(vehicle.currentSpeed).IsLessThan(originalSpeed);<br>
}
When a developer comes across this story, along with PressingEmergencyBrakeLocksTires(), SlamOnBrakesShouldSkid(), and BrakesShouldAntiLockAtIntervals(), the developer is told a story of what the class is doing. Why do we use custom asserts when good test names will solve the problem?
Changing tests should be cheap. As new designs and behavior evolve in the system, tests are changed to conform to the new structures. When implementing a new design to an existing system (such as breaking up an inheritance in favor of composition), I change the tests to fit the new structure on a macro level. However, this often implies that I am changing the behavior (if only slightly) to please the new design. Yet, test names, like comments, are not executable, so you can‚’t trust them to tell you what the tests test. On a system with heavy refactorings, a test might have its details changed five times without the developer thinking to verify the integrity of the names. An answer is to write sentential explanation of the test as the assert statement since the assert statement executes. I will trust execution over comments every time.
There is a project in its early stages called NSpec(.NET), which is a framework for assertions of a more sentential form. The project is based on the idea of Behavior Driven Development (BDD). RSpec, the same project for ruby has a form of BDD assertions which take full advantage of the features of the dynamic language. It allows you to add the assertion to the object from the test.
For example:
def pressingbrakesshoulddeceleratevehicle
vehicle.brake
vehicle.decelerating?.should_be_true
end
This is really cool! It defines the test as behavior of the object, which it is. However, when the code isn’t ruby, there needs to be other means in place to bind the description of the assertion to something which executes.
Fri, 20 Jan 2006 05:37:12, nraynaud, Tests in a changing world
You’re right, we are slowly going to agile world, and for now we have lots of meaningless test taken randomly from existing code (does it makes sense putting a multi megabytes source file in the compiler you test and expecting exactly 2008 errors? without even covering 10% of the compiler). We work on a language, yesterday, I added a restriction to the langugage, it took me 10 minutes to implement and test the change but the rest of the day to change all the others tests.
Moreover, I thank Intellij Idea that renames not only classes but also varialbes named after that class and even comments, this is on the way you takes.
Fri, 20 Jan 2006 13:13:22, David Chelimsky, should_be_decelerating
I’ve just submitted a contribution to rspec that will make this even cooler. If vehicle can respond to any of these messages with a boolean value:
vehicle.decelerating
vehicle.decelerating?
vehicle.is_decelerating
vehicle.is_decelerating?
then you can write this in your test:
def pressingbrakesshoulddeceleratevehicle
vehicle.brake
vehicle.should_be_decelerating
end
Admittedly, this may be confusing to a programmer who is looking for a “should_be_decelerating” method on vehicle, but the messaging is clear it fails (”
Fri, 20 Jan 2006 13:57:32, ,
How about using Higher Order Messaging style and let the user write:
vehicle.should_be.decelerating?
The test framework could mix should_be and similar higher-order messages into the Kernel module.
Fri, 20 Jan 2006 14:40:41, David Chelimsky, should_be That’s kind of how rspec works now. shouldequal, shouldcontain, shouldbe_true, etc are all mixed in to Object, so you can do things like someobject.someattribute.shouldbetrue. Your suggestion of tying it to a “shouldbe” method (rather than parsing the shouldbe_xxx message) might be more clear. I think, though, that “shouldbe.decelerating?” is weird to read (because of the question mark). Programatically, however, it does make the statement look more like the implementation. I’ll think on it some more…
PreFactoring
by: paul | September 7th, 2006 | 23 comments »
Prefactoring is when you see a piece of code which the story you are working on which has a refactorings which would make your story easier. I have seen prefactoring to be a dangerous process. On one hand, you save time when you know that this refactorings will need to be done. You are faced with the choice of writing temporary code (in the sense of duplicate then refactor) or refactoring, then writing quality code. The software designer in me always wants to choose the prefactoring solution, since it gets to make code cleaner, remove duplication, and be more efficient. Then I can stand on the mountain top waving my flag.
There are a few problems right off the bat. First, the uber-developer in all of us will refactor as much as we can, therefore refactor based scope creep is bound to show up. I don’t really know how to stay away from scope creep in this manner.
Prefactoring can lead to a version of design up front which is detrimental if you don’t need it. However, sometimes you know up front this design simplification will cut the story time in half. Do you prefactor? What kinds of smells make it ok or terrible to prefactor?
I have tried backing my way in and using test(s) as a life jacket, so once the test passes, the refactoring is done. However, the problem with this is it leaves me with half done refactorings. The code is constantly moving up in quality, however, it might not look it due to the inconsistencies produced by half done refactorings. I generally think of a complete refactorings as something that made my system better in some manner I would like developers who are extending the behavior of the system to use the refactorings as a model.
Do my refactorings make the system easier to extend? Half-factorings don’t, but they do provide a manageable slope moving positive. I don’t have the time to tackle the big refactorings, but I don’t want to leave them unfinished.
Wed, 22 Mar 2006 09:27:50, Uncle Bob, Half-factorings Paul, Keep the code clean! If the tests pass when the refactoring is half-done, then complete the refactoring. If you can’t complete the refactoring in this iteration, then keep putting effort into it during subsequent iterations. Make sure the team knows, so they can put some effort in too.
There are often times when a new story is easier to implement in a structure different from the one that exists. Refactoring (or “pre-factoring”) the system into that new structure to make that story easy to implement is often a good approach. However, leaving the refactoring in a half-finished state is messy.
Wed, 22 Mar 2006 18:30:36, Micah Martin, Prefactor
”’Prefactor”’ - I like that. If I counted all the time I’ve had to delete my prefactored code…. I believe there’s an Big Up Front Designer in all of us. Face it, BDUF is fun! Frequently I look at a prefactoring that I’ve just completed and realize I’ve been BDUFfing. Most of the time I delete it all because it’s too complex and unnecessary.
Sun, 23 Jul 2006 08:14:08, Sebastian Kubeck, BDUF To be honest, I never got BDUF right. Untill today, I need to start over one to four times untill I get what I want. I was convinced that I’m just lacking the skills to get it right the first time. Fortunately, I found out that people that are much smarter and much more experienced than me don’t get it right the first time either.
I learned in school that Mozart just wrote down his music which was already completely finished in his head. I was toled later that this is just another myth about this guy. Beethoven permanetly adapted his works. His handwritings are hard to read because his corrections. Bach adapted his works depending on the number of musiciants he could afford.
Conclusion: If not even the geniuses mentioned above get it right the first time, how should we “ordinary people” should ever be able to do it?
Over Mocking
by: paul | September 7th, 2006 | 26 comments »
I have noticed using more mocks lately. Instead of using them sparingly for controlling services which are not instrumental to what I am testing, I am essentially using them as a way to isolated what I am testing. This has me noticing a side effect I am not entirely comfortable with. To use the mock, I need to be able to have the mock in the production code, which means I need to inject an abstraction of the mock (dynamic mocks will do that for you).
So, the side effect is long parameter lists, specifically in constructors. Everything takes almost all the objects it uses. Then, to create the production objects are factories. I am using many more factories than I would without mass mocking. I am not sure if this is a good use of dependency decoupling and factory building as design techniques, or if this is a symptom of over design and tightly coupling the mocks to the tests, making it more difficult to change the tests without changing the interface the mock is implementing. Thoughts?
Wed, 24 May 2006 14:03:11, Dave Hoover, Create a default constructor Try poor man’s dependency injection: have a constructor that allows you to inject your dependencies (hidden behind interfaces) for testing, then have a default constructor that instantiates the concrete objects and injects them itself.
Wed, 24 May 2006 15:01:02, David Chelimsky, too many dependencies either way I don’t think mocks or factories are the real problem here. If A depends on the services of B,C,D,E,F,G,H and I, then it’s depending on too many things whether you inject the objects or instantiate them internally.
Wed, 24 May 2006 16:57:06, , Don’t “inject” dependencies. Mock an object’s peers in tests and pass real peers to it’s constructor or as method arguments. Composite objects should create objects they use internally and not expose them at the constructor. A composite object should be simpler than the sum of its parts. Also, avoid passing all dependencies into an object’s constructor: you can probably pass collaborators as method arguments, not constructor arguments.
Wed, 24 May 2006 17:24:56, Dave Hoover, Listen to Chelimsky The smell of a long parameter list leads me to think you may be able to collapse some objects behaind a coarser-grained interface.
Thu, 25 May 2006 11:24:12, Ryan Cooper, DI Containers I find using a DI container like PicoContainer eases the pain by making all (or most of) those factories unnecessary.
I’m still not happy about the long parameter lists in constructors, so I think I will give a few of the suggestions above a try. Thanks all.
Thu, 25 May 2006 16:08:05, Tim Ottinger, The “Airplane” retort “I’ll never be over mocking!”
Fri, 26 May 2006 10:48:42, Asher Sterkin, Over Mocking Personally I mock whatever and whenever I can. Usually a hardship with mocking reveals some interesting deeper design problems. If there are too many arguments for constructor it probably means the class under test has too many dependencies, which means a problem with cohesion. In my experience I seldom need to mock more than 5 interfaces per test case. It’s usually one or two as constructor arguments and two, max three for returned objects. If it’s more I try to re-factor.
Fri, 26 May 2006 16:25:43, Paul Pagel, “In my experience I seldom need to mock more than 5 interfaces per test case.” Do you only mock interfaces?
Sat, 27 May 2006 19:49:22, Rogerio Liesenfeld, I prefer to obtain dependencies with “new” wherever possible In the large (8000+ classes) J2EE web app I am currently working, many business classes obtain instances of other business classes by simply instantiating them with the “new” operator. Besides being the simplest way to obtain dependencies, this allows business service classes to maintain client-specific state, so that private methods don’t need to have any parameters.
Of course, with the mock objects tools previously available, it would have been difficult to unit test such classes. But I wanted to use “new”, and also have final classes, final methods, and static methods where appropriate. So, with that “itch to scratch”, I went ahead and created a new tool that would free me to design the application without constraints, and still have complete unit tests.
If anyone wants to give it a try, the tool is here: jmockit.dev.java.net.
Fri, 9 Jun 2006 10:30:20, Asher Sterkin, Over Mocking “Do you only mock inerfaces?” Not only, but I prefer so. In C++ it really doesn’t matter since there is no good mock library (I use my own which is based on link time substitution; I plan to sourceforge it soon). In Java and C# interfaces do not cost too much, but sometimes you have a class comming from the infrastrucure. You would like to mock it but you do not want to wrap it with an extra interface. For example I recently mocked Java’s TimerTask::cancel in order to validate that in a certain scenario a timer cancellation request is sent properly. I also do test what will my program do if the TimerTask::cancel returns false (too late to cancel).
Fresh Testing
by: paul | September 7th, 2006 | 2 comments »
Sometimes I sit down to write a test on something I haven’t worked on before or don’t know intimately, and I just can’t write the first test. I need a context of the system and a state of existing code. Then I generally do one of two things: look at how things are implemented in the code, or look at other tests that exercise similar behavior. Using either of these as a strict model to write a test is problematic to the flow of TDD.
By using the implementation code as a model, I am limiting one of the great things about TDD from the beginning, the fact the design should evolve as a byproduct of making the test pass. This TDD complacent method tends to ingrain existent design into my mind. These strict models resign to existing design, even if your story/test/problem isn’t exactly the same, just similar enough to convince you of the model.
Copy/pasting a similar test and editing is a developer mistake I commit sometimes when it looks like a freebie is being tossed at me: duplicate then abstract. It is very tempting, yet I have found it painfully regressive. Especially when the tests themselves have begun to rot, as their ability to act as developer docs are deprecated. It causes a lie in logic which is always painful. Either the debugger gets fired up or the test gets scrapped in order to handwrite anyway. Copy/pasting something which is similar is starting from a false expectation most of the time. It is more important to me to have faith in the integrity of my tests.
The most powerful TDD I see is at the beginning of a project, since there is a state of tabula rasa allowing you to move infinitely lateral. Before tests depreciates provides the best model for TDD. Test depreciation is unavoidable, as with design changes, the tests are changed with regularity to accommodate the new structures. The reason for having the tests is to have a safety net to make the code easy to change. It becomes important to keep tests “fresh” when there is already design in place. Otherwise good design appears to degrade due to over/improper use.
Handwriting a test from scratch can seem like an extra step, like reinventing the wheel. Most of the time the extra step is exactly that, an extra step, but in those cases where you are following a false model it is very expensive. It introduces the worst type of design into the system, the kind with little to no smell, but with false premises. Introducing bad design into tests or failing to maintain test code ends up introducing bad design into production code.
COMENTS
Thu, 5 Jan 2006 22:16:48, David Chelimsky, copy/paste Copy/paste can be a real problem, yet it takes an awful lot of discipline to abandon it completely. For example if you’re test driving something new - you write the first test which has some setup in it. You’re not ready to move stuff to a setup method because there’s no duplication to warrant it yet. So for the second test you copy/paste the first test, modify what you will, get it to pass, and then refactor out the duplication. With just a few lines of testing code that’s probably acceptable, but there’s a point where you get yourself in trouble. I guess that’s different for everyone, and perhaps on different days (depending on the coffee/sleep ratio). Maybe committing to a day of absolutely zero copy/paste to see if it really slows me down would be worthwhile.
Thu, 5 Jan 2006 22:53:53, Tim Ottinger, What he said I hate copying from any existing tests, always feeling like I’ve cheated somehow. It is a way to get by (or try to get by) when you don’t really know what you’re doing. When I talk about whether I [[really know][http://tottinge.blogsome.com/2005/12/30/how-can-you-not-know-java/]] something or not, I consider whether I can work from the blank slate. If not, then I don’t really know my topic. Not only is working from tabula rasa liberating, it’s a good indicator that you’ve done enough backgrounding. It’s good on so many levels.
I just wrote the other side of this blog, that [[naive tests don’t help][.ArticleS.TimOttinger.NaiveTestsDontHelp]] so you have to know the software to write tests for new parts. I think that it would be good if we could work on the pro/con of this and give guidance on navigating between sylla and charybdis. If you don’t know enough, you can’t blue-sky the tests. If you are copying the tests, then you only reinforce the implementation in testing (for better or worse). There has got to be a middle way, and some heuristics to help get around: something more useful than “pairing should fix that.”
Fri, 6 Jan 2006 15:50:00, Thomas Eyde, Copy/paste is for professionals – don’t do that at home I think the trick is to write the tests for the truly new requirements, then find reusable code if any, or refactor existing code to be reusable. Not easy, but that’s what I strive for.
I also think there’s nothing wrong to copy/paste and then refactor. It’s without the refactoring things start to get dangerous.
Sat, 7 Jan 2006 12:28:24, Matisse Enzer, Copy and paste as an iterative action Yesterday I was adding tests to some “legacy” code. After I got the library to compile under the test harness I picked one subroutine to test, and create d a test to run that subroutine. Of course I got a run-time exception because the subroutine I was testing made a call to a subroutines defined in some other library. So, I created a stub version of that subroutine in my test harness. ran the test again, another missing external subroutine. I copied and pasted the stub I had created, changed the name, reran the test. Several times. Each time adding a single “fake” subroutine. (Sometimes I had to edit the stubs to return some mock data.)
I also copied-and-pasted my first test. Renamed it, and changed the arguments it passes to the subroutine I’m testing. Did this three times.
Mon, 30 Jan 2006 22:46:53, Paul Pagel, the copy/paste problem There are many ways to introduce code debt into a system. Duplicate code is one of the worse. Copy/Pasting leaves the payment of this debt to the memory of the developer. So if it is copy/paste a few lines at a time, then refactor at the end of small cycles, then I go for it. But if it is going to be coping a file or a series of tests/methods, I won’t.
Smalltalk Bowling
by: micah | September 7th, 2006 | 0 comments »
I’ve been meaning to learn Smalltalk for years now. Recently Dave Astels and I have a had a few discussion on the topic. They all seem to circulate around the theme of Smalltalk being a key OO language of the past, and again in the near future. Now that Ruby has finally captures the attention it deserves, it’s not long before Smalltalk is back in the spotlight.
A few days ago, when he joined me for a train ride, I seized the opportunity and asked him to help me write some Smalltalk. He gave me a copy of Squeak and off we went to write the Bowling game.
Even though we only got through the first two test cases, Dave’s a good teacher and I was able to finish it on my own. The code is below.
My first impression of Smalltalk: “Damn, this requires a lot of clicking”. It requires two clicks just to run a test and another 5 clicks to see what failed. Dave gave me funny looks when I complained about this but I couldn’t believe people programmed this way. Later my dad, remembering a demo by Kent Beck, reassured me that there are keyboard shortcuts for everything. Thank goodness!
In general it’s a sweet language. Experience with Ruby and Objective C exposed me to many of the concepts so there weren’t many surprises. Perhaps the most peculiar thing I ran into was the Smalltalk equivalent to if/else statements. The ”ifTrue: ifFalse:” structure makes perfect sense but it was unexpected. An example can be seen in the ”score” method.
This is my first Smalltalk program and I’m sure I’ve made some newbie blunders. Feel free to rip my code to pieces in your comments. I’d love to hear advise and learn Smalltalk idiosyncrasies.
- TestCase subclass: #BowlingTest
- instanceVariableNames: 'game'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'Bowling'!
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 4/27/2006 18:11'!
- setUp
- game := Game new! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 4/27/2006 18:19'!
- testAllOnes
- 1 to: 20 do: [:i | game roll: 1].
- self should: [game score = 20]! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 4/30/2006 19:52'!
- testAllSpares
- 1 to: 21 do: [ :i | game roll: 5 ].
- self should: [game score = 150]! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 4/27/2006 18:05'!
- testGutterGame
- 1 to: 20 do: [:i | game roll: 0].
- self should: [game score = 0]! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 5/1/2006 12:26'!
- testHeartBreaker
- 1 to: 11 do: [ :i | game roll: 10 ].
- game roll: 9.
- self should: [game score = 299]! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 4/30/2006 19:20'!
- testOneSpare
- game roll: 5.
- game roll: 5.
- game roll: 1.
- 1 to: 17 do: [:i | game roll: 0].
- self should: [game score = 12]! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 4/30/2006 19:44'!
- testOneStrike
- game roll: 10.
- game roll: 1.
- game roll: 2.
- 1 to: 16 do: [:i | game roll: 0].
- self should: [game score = 16]! !
- !BowlingTest methodsFor: 'testing' stamp: 'MDM 5/1/2006 12:26'!
- testPerfectGame
- 1 to: 12 do: [ :i | game roll: 10 ].
- self should: [ game score = 300 ]! !
- Object subclass: #Game
- instanceVariableNames: 'rolls'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'Bowling'!
- !Game methodsFor: 'scoring' stamp: 'MDM 5/3/2006 19:01'!
- init
- rolls := OrderedCollection new! !
- !Game methodsFor: 'scoring' stamp: 'MDM 5/3/2006 19:02'!
- roll: pins
- rolls add: pins.! !
- !Game methodsFor: 'scoring' stamp: 'MDM 5/3/2006 19:03'!
- score
- | roll score |
- roll := 1.
- score := 0.
- 1 to: 10 do: [:i |
- (rolls at: roll) = 10
- ifTrue: [
- score := score + 10 + (rolls at: roll + 1) + (rolls at: roll + 2).
- roll := roll + 1
- ]
- ifFalse: [
- (rolls at: roll) + (rolls at: roll + 1) = 10
- ifTrue: [ score := score + 10 + rolls at: roll + 2]
- ifFalse: [ score := score + (rolls at: roll) + (rolls at: roll + 1)].
- roll := roll + 2
- ].
- ].
- ^ score! !
- "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
- Game class
- instanceVariableNames: ''!
- !Game class methodsFor: 'as yet unclassified' stamp: 'MDM 4/27/2006 18:23'!
- new
- ^ self basicNew init; yourself! !
Tue, 29 Aug 2006 02:03:35, Jamesl, Yay, Smalltalk … Very interested to see someone go ‘back’ to use some Smalltalk.
Other than the ‘click’ frustration that you experienced, what else did you ‘feel’ about the language ?
I’m a smalltalk zealot but get paid to do java, that’s just how it is.
Rgs,James.
Thu, 15 Jun 2006 08:40:37, snoobab, Good to see some smalltalk! Hi
Great to see Smalltalk code! I have been Java zealot for 6 years now and made a decision 2 months ago to learn Smalltalk. And I absolutley love Smalltalk’s simplicity and ideas and am hoping to apply these ideas in my paid software development. I’d love to find a job in South Africa using some Smalltalk.
Must say that you quickly learned alot of Smalltalk on a train ride! BTW you don’t have to override the ‘new’ method. You could simply implement the ‘initialize’ method on the instance side. This is called via the normal object creation. (Which can be found in the ‘new’ method on the instance side of class Behavior)
Fri, 12 May 2006 22:49:35, Dave Astels, Bowling in ruby ${chelimsky} posted one on his blog here
Fri, 12 May 2006 22:48:39, ,
Tue, 9 May 2006 21:01:15, Francesco Rizzi, see what happens ? ..I’m downloading Ruby now. :) I wonder if I’ll find a Ruby version of the bowling kata anywhere…
but this was about Smalltalk originally.. I got to admit that languages where you don’t need { and } around blocks that include more than one line scare me !
Tue, 9 May 2006 18:03:14, Dave Astels, sSpec on the way I’m currently working on a new version of sSpec (which is aligned with the latest rSpec). The first release will be for VW7.4, with a squeak version to follow.
Sun, 7 May 2006 19:33:09, Francesco Rizzi, rSpec ? cool…have you had a chance to look at rSpec (and the whole BDD vs TDD philosophy) ? —-”Yes! Dave assures me that I was the first user of the rSpec in it’s latest form. -${micah}”
Thu, 4 May 2006 00:48:13, Randy Coulman, Minor suggestions Overall, it doesn’t look too bad for a first effort. A couple of comments:
I haven’t used Squeak, so maybe it doesn’t have this method, but I’d be surprised. When you write a loop that doesn’t need to use the index variable, you can do n timesRepeat: [… whatever …] instead of 1 to: n do: [:i | … whatever …].
SUnit also has assert: and deny: methods that expect Booleans in addition to should: and shouldnt: that expect blocks. So instead of self should: [ game score = 300 ], you could put self assert: game score = 300. It’s a matter of taste, really, so either way is fine.
In VisualWorks Smalltalk, there are some add-on tools that make it much easier to run tests and find failures, so not as many clicks are required. I’d be surprised if someone hasn’t done the same for Squeak.
Great tips! Thanks Randy -micah
Paper Bullet
by: micah | September 7th, 2006 | 0 comments »
Work has me visit lots of software teams around the world. This past week I visited a particularly fun team. They worked in a large open work area with desk space for pairing and wall space for BCV (Big Visible Charts). Anyhow, there was one member in particular, I’ll call him Dan, that was notorious for his mischief. Most notably, he’d start paper bullet wars.
Paper bullet is not the term they used but that’s what I’m gonna call it. What you do is tear off a piece of paper and roll it lengthwise. Then fold it fold it in half so you’ve got a wedge shaped paper bullet. Then take a rubber band and stretch it between your thumb and index finger. Slide the wedge onto the center of the rubber band, stretch, aim, and release.
Dan had apparently surprised everyone on the team with a paper bullet in the face or neck at one point or another. They held a friendly grudge against him.
Early in the week I was unaware of the paper bullet wars and I found it peculiar that there were all these bit of paper on the floors and desks. Apparently wars were taking place all week but, being the guest, no one wanted to hit me and so who ever was pairing with me had immunity.
In the final hours of the last day they confessed at how nice they were and how lucky I was that I didn’t get shot all week. Frankly I was disappointed that I didn’t get to play all week so I spat out some fighting words… “You’re lucky you never got me involved!”. It began. I could hear them whistle past my ears as I was writing so unit tests or bounce off the wall behind me as I pass the keyboard to my pair, but I never got hit.
Thankfully, other team member armed me a rubber band and a hand full of paper bullets. At a quiet moment, I figured I’ve give this game a try. Grabbing the rubber band and paper wedge, I loaded and aimed right at Dan’s head. The rubber band was surprisingly flexible. Not knowing how hard to stretch it, I just kept pulling. As I looked down the trajectory, I was sure the projectile would curve. When I released I was shocked and horrified.
The bullet screamed across the room, straight as an arrow, pegging Dan right in the side of the head. It made a loud smacking noise upon impact. The whole team heard it and the room went silent. I was terrified. This was no way to treat your clients, I thought. The poor guy never even hit me so he didn’t deserve it. Apparently I was wrong. Everyone else thought he deserved it. The room broke out in laughter. Team members (not Dan) gave me a thumbs up, telling me “Thanks” or “Good job”.
I apologized to Dan later, trying not to stare at the red welt just below his temple. Dan, the sportsman that he is, congratulated me on my marksmanship. He’s a good guy.
So what’s the moral of the story? None really. But I will note that many of the development environments I visit are much more sterile and “professional” than this team…. and much less productive as well.
Wed, 19 Apr 2006 10:21:32, Greg, hey !? Did you visit my office recently and I didn’t know? We’re also doing this, but since there’s only 3 of us in the office, we sometimes have to use other targets than ourselves (when the red marks are becoming too obvious). We just destroyed an ugly dummy cd of some bad dutch singer here.
Wed, 19 Apr 2006 02:52:29, Mike, My mother used to say it’s only fun until someone’s eye is put out!
Tue, 18 Apr 2006 10:49:47, Dan (yes that one), Injury update The swelling is down…I can see out of that eye now…hope you come back soon :) :) :)
Tue, 18 Apr 2006 06:44:08, Ryan Platte, Nice shot! Don’t be surprised if I hang out by a pillar if you come to another Chirb meeting, yikes!
Beware the Freebie
by: micah | September 7th, 2006 | 0 comments »
The milestones in the life of a story:
- Creation: customer creates the story
- Estimation: the story is estimated by developers
- Selection: the story is selected for an iteration
- Specification: tests are written the story
- Implementation: the story is implemented to make the tests pass
- Acceptance: the customer acknowledges completion of the story after seeing the passing tests and witnessing the new functionality
It is unavoidable. Every story must go through these milestones of life in order. A story cannot be estimated if it has not been created. A story cannot be selected for an iteration if it has not first been estimated. You can attempt to specify a story before it has been selected but you run the risk of being wrong, for the system may change many times before the story is selected. Implementing a story before it has been specified will lead to false implementations. And accepting a story that hasn’t been implemented is just plain silly.
It happens with some frequency, however, that a story gets implemented before it is ever selected, estimated, or perhaps even created. How? A developer may be look at a piece of code and think, “Hey, the customer mentioned he wanted to change this doohickey. I might as well change it now.”. Or a developer may working on one feature and say, “You know, I bet the customer would really like it if I improved this thing-a-magigger”. When this happens, the developer pridefully demonstrates the extra functionality to the customer and says with a smile, “You got a Freebie this iteration!”.
BEWARE THE FREEBIE! A Freebie, by it’s nature, has skipped at least one milestone in it’s life. Most Freebies skip the Selection milestone. This is unfortunate because maybe the customer didn’t really want that story after all. But that’s small potatoes compared to the real danger… Almost all Freebies have skipped the Specification milestone.
Skipping the specification milestone is blasphemous. If a feature has not been specified with tests, how do you know it really works? Worse, how will you know if it still works 2 months from now. Very often Freebies break and nobody knows about it.
I’ve seen it over and over and it’s regrettable every time. A perfectly innocent story is wronged by an overzealous developer. The poor story, out of sync from his peers, strays from the trodden path and becomes a Ghost Story. Becoming a Ghost Story is dreadful fate. They are those stories that were at one time complete, but have since become incomplete. You may never actually see a ghost story but they will surely haunt you. They cause users to have delusions of non-existant functionality and to make exclamations like “Hey! Why doesn’t this stupid app work like it used to?” or “What happened to my favorite feature?”. They keep customers up at night wondering if they actually selected the Ghost Story for an iteration of not. They torment developers forcing them to write code they’ve already written.
Avoid Ghost Stories by avoiding Freebies. Give every story a complete life with all it’s milestones. The next time a developers shows you extra functionality and calls it a Freebie, say “That’s nice. I’ll consider selecting a story for that in a future iteration.”
Mon, 24 Apr 2006 23:17:57, Old Grouch, Another hidded danger By skipping several stages, the freebie runs the risk of breaking something else. An assumption that doesn’t carry throughout the entire system. Usually minor, so it doesn’t show up for months. Then someone else has to rip their hair out. And declare that your parents were never married.
“The more innocuous the change, the greater the ramification.”
Tue, 21 Feb 2006 14:11:34, Gary Dieckman, Looking for Preston and Karen Martin Micah Martin - If your parents are Preston (Tom) and Karen Martin of Proctorville, Ohio, then your dad was best man at my wedding in 1970. I’d like to get in touch. Are you that Micah? gary@exprint.com
Nope, you’ve got the wrong Micah
Tue, 21 Feb 2006 14:11:34, Gary Dieckman, Looking for Preston and Karen Martin Micah Martin - If your parents are Preston (Tom) and Karen Martin of Proctorville, Ohio, then your dad was best man at my wedding in 1970. I’d like to get in touch. Are you that Micah? gary@exprint.com
Thu, 16 Feb 2006 10:09:50, unclebob, Other out of order disfunctions. Indeed! I think you have hit on an interesting way to describe a whole family of dysfunctions. I have certainly seen stories selected before they are estimated. I have seen stories accepted before they are specified. I have seen stories implemented before they are created. Each of these dysfunctions has it’s own particular set of symtoms and ramifications. What are they?
Thu, 16 Feb 2006 08:12:26, chelimsky, skipping selection Well said, Micah. It’s worth noting that 4 of the 6 milestones are customer milestones. As developers, we want to create the best software we create. We talk about it being a team effort (i.e. whole team, customers, developers, et al), but in the end it’s not really our (developers) software. And how can we expect our customer to feel ownership of priorities if we arbitrarily take the their any (sometimes all) of their milestones?
Prelude to the Mock Off
by: micah | September 7th, 2006 | 0 comments »
!title Prelude to the Mock Off You can read David’s side of the story here: Stop Mocking Me
He puts it gently… We’ve actually had some heated arguments about these mocking frameworks and it’a all kinda silly. In the end we’re writting good tests for well designed code. Still, these mocking frameworks rub me the wrong way.
Why do I prefer hand-made mocks?
1 They’re simple to write. Yeah it requires a new class but it only takes a couple seconds and it’s the most brainless code you’ll ever write.
2 They’re simple to use. If I want an instance of a DataEntryView I simple type new MockDataEntryView(). With a mocking framework, it takes 3 or 4 lines before I have a usable object.
3 They’re much more flexible. With mocking frameworks you can set returns values and expected method calls but that’s about it. Hand-made mocks are limited only by your imagination.
4 Mocking frameworks are refactoring-challenged. Especially NMock. Rename a method and dozens of tests will break.
5 Readability. Tests using hand-made mock are easy to read. Tests using mocking frameworks require murky configuration.
6 Mocking frameworks violate testing convention. Build, Operate, Check. Conventionally, all tests follow this flow. With mocking frameworks the flow becomes, Build, Check, Operate, Verify.
7 Failures are deceptive with mocking frameworks. When you get a failure in a test using a mocking framework, the line number usually points to a call to Verify. With Rhino it can point to the last line of a using block. Either way, the failure could have been caused by any number of assertions. It’s up to you to figure out which one. With hand-made mocks, line numbers pinpoint the problem by revealing the exact failing assertion.
What do I hope to get out of the Mockoff? I’ve played with several mocking frameworks before. I hope that by committing to use them for 3 days, I’ll gain insight as to so many people use them. Maybe I’ll find that they improve my productivity and I’ll use them in the future on a regular basis.
What do I expect to happen during the Mockoff? I’m trying very hard to have an open mind going into this. My stubborn self is expecting 3 days of frustration. My optimistic self is expecting to gain appreciation for mocking frameworks. We’ll see what happens.
Mon, 31 Oct 2005 12:22:11, SvenGorts, Unit Testing With Hand Crafted Mocks When I started using hand-made mocks, I expected that I would switch to the use of a mocking framework rather rapidly. Perhaps surprisingly this switch never happend and as of today hand-written mocks are still my preferred choice. The article ”’Unit Testing With Hand Crafted Mocks”’ available at http://www.refactoring.be/articles/mocks/mocks.html summarizes some of my personal experiences.
Mon, 31 Oct 2005 14:14:35, M. Scott Ford, I can’t argue with some of your points. But you may want to take a glance at NMock2. The code that you write is still refactoring challenged. Which is honestly a refactoring tool limitation in my opinion. (I could not resist!) I think that the mocking code with NMock2 is very human readable. Expectations are setup with Expect.Once.On(object).Method(“Method”).With(parameter1, parameter2).Will(Return.Value(result)). To me that is very readable, and it is the reason that I use NMock2 in all my tests (Why am I starting to sound like a salesman?)
The errors in this version have been improved as well. Unexpected calls throw at the point that they occur. And all of the unmet expectations are listed as part of any error thrown by NMock2. You still have to include a verify if you want to find out about unfulfilled expectations, but now, at least, it is just one instead of one per mock object.
I do use hand mocks as well. I just don’t use them as often. I like to mix and match. I pick the tool that will get me to a finished test that clearly demonstrates its intent the fastest. The “dynamic” mocks have their downsides, but I think that the benefits out weigh the cost. Personally, I like to make it clear what code in a test is “mock” code, and what code is supposed to me part of the class that is getting mocked. I think that the mock tools help keep this separation clear.
But I am sure that these are all arguments you have heard before, so I will shut up now. What I really wanted to do was tell you about NMock2, so here [http://vaderpi.scottandlaurie.com/blog/?p=185] is a short article that I wrote comparing NMock and NMock2.
Enjoy the Mockoff! I will enjoy reading the results.
Tue, 1 Nov 2005 04:37:38, Sagy Rozman, Tons of mock classes
They’re simple to write. Yeah it requires a new class but it only takes a couple seconds and it’s the most brainless code you’ll ever write.
I agree, and this is exactly why I don’t use them. I’m trying to write most of my tests as interaction based tests. At first I was going for the hand made mocks approach, but soon I discovered that the test.utils.mocks package was getting quite large. There where lots of mocks and it was getting out of control. When I started to refactor this code I suddenly realized that I was building j/nmock all over again. I then stopped and learned all there is to know about using these libs. Today I use the mock librarys more than hand made mocks.
Tue, 1 Nov 2005 04:43:23, David Chelimsky, re: Unit Testing With Hand Crafted Mocks Sven - I read your article. I like the idea of different types of substitutes. I can imagine that they do a lot to clarify the tests that use them. I’m going to experiment with that as part of my experiment.
Thu, 3 Nov 2005 03:45:47, IsmetKahraman, Sometimes, interacting with an API full of static methods does not allow to mock these classes. In these times, virtualmock really helps. Adding new behavior (here mocking behavior) by means of aspects is a different and a helpful approach. But for the time being, I prefer EasyMock in my TDD efforts. Simple, once accustomed it is a very natural way of dealing with external interfaces.
Sat, 12 Nov 2005 22:00:03, Steve Eichert, Have you tried Rhino Mocks? Rhino Mocks gets rid of the hard coded strings everywhere. I haven’t actually used it as I’m much more of a hand crafted mock guy, however, it does look interesting.
http://www.ayende.com/projects/rhino-mocks.aspx
Wed, 14 Dec 2005 09:22:37, Paul Pagel, I have been using used Rhino mocks lately, which have solved some of the objections to mocks you listed. One thing I have noticed about hand mocks is they end up with logic in them. Often mock classes, as they evolve, will contain logic around different results which is neccessary for the return type or to simulate minimal behavior for the mock to be useful. This logic becomes a lie, as it is not updated with the code, so when the production code gets changed, the tests using the mocks will still pass. The fact there is no executable accountability as a mocking framework would provide makes hand mocks dangerous unless they are bare bones. A mocking framework takes away the temptation, as they can only be bare bones mocks.
Wed, 14 Dec 2005 09:36:09, David Chelimsky, mostly stubs…. There is a distinction that “mockists” make between mocks and stubs. They are both fakes, but a stub is a class that you set up to behave in a known way when the class under test interacts with it - returning a known value in response to a query, for example. A mock records messages it gets from the class under test and reports back against expectations you set in advance. Whether you’re hand-mocking or rhino-mocking or any-framework-mocking - the problem of fakes becoming lies as the real classes change is related more to stubs (predefined behavior of collaborator) than mocks (verification of behavior of class under test).
That said, my biggest issue is the extra classes it produces. I’m in the middle of (gradually) splitting a hierarchy into two separate hierarchies. The existence of hand made mocks for every one of the production classes doubles the effort involved in this separation. Hand made mocks seem to be bound to static hierarchies. Tool generated mocks seem to be bound to the classes they mock and that’s all.
Wed, 11 Jan 2006 14:04:57, David Kreth Allen, So, Micah, what is your impression at this point? Are you more likely to use mock tools now? Any suggestions about when to favor one over the other?
IList, IComparable, ICarumba!
by: micah | September 7th, 2006 | 0 comments »
This IConvention is an interesting one. ”Let’s prefix all interfaces with a capital I.” Who thought of this? Why did they think it was a good idea?
Let’s say I want to implement the Command pattern in C#. I create the following interface…. and to be true the fathers of C# I use the IConvention.
- public interface ICommand
- {
- void Execute();
- }
In my application I can now write Code like this.
- public void ExecuteCommands(IList commands)
- {
- foreach(ICommand command in commands)
- command.Execute();
- }
Clearly, every object in the IList of commands is an Implementation of ICommand. And ICommand is an Interface because It starts with an I. That’s Important to know because If It didn’t have the I, It might be an abstract class or even a concrete class. And If that were the case then….. well…. hmmm…. it doesn’t really matter. I could call the class ICommand or I could call it Command. From the point of view of the client code, maybe Command it’s an interface or maybe it’s not. So if it’s all the same, I might as well submit to the convention and call it ICommand. Right?
Wrong! Prefixing interfaces with I is a mistake and this is why….
Assume that I really do need a Command abstraction. Should it be an interface or an abstract class? I can’t think of any logic to put in the base class and the Dependancy Inversion Principles says interfaces are preferred. So I’ll make it an interface and follow the IConvention naming it ICommand. After a while there are a dozen or so implementations of ICommand in the application. New implementations are popping up all the time. One day I realize that the application needs to know whether an ICommand has executed or not. Since this affects all implementations of ICommand I can add another method to the interface:
- public interface ICommand
- {
- void Execute();
- bool Executed { get; }
- }
However, it’s not long before I realize that all the derived classes implement the Executed property with the exact same code. They also need a boolean field. So to avoid duplicate code, I’ll use Template Method like so:
- public abstract class ICommand
- {
- private bool hasExecuted = false;
- public virtual Execute()
- {
- PerformExecution();
- hasExecuted = true;
- }
- protected abstract PerformExecution();
- public bool Executed
- {
- get { return hasExecuted; }
- }
- }
But wait! ICommand is not longer an interface. I can’t just leave that I sitting there. Clients will think it’s still an interface. So now I need to rename the class to Command without the I. Fortunately, !-ReSharper-! will help me there. But now I’ve got the Command class in a file named ICommand.cs. Renaming the file is a bit more challenging since it has to be changed in source control as well. So I rename the file in the subversion repository, then remove the ICommand.cs file from the Visual Studio project, and finally add the new Command.cs file to the project…. whew. That silly I sure causes a good deal of hurt.
I’ve stumble over this scenario more times than I care to mention. Experience has taught me that prefixing interfaces with an I is a choice that will come back and haunt me. So I don’t do it.
Here’s my dilema. Maybe you can help me. I’ve been translating Unclebob’s Agile Software Development book into C#. In the code examples I have heeded my experience and created interfaces without the I prefix. Reviewers don’t like this. They keep telling me that I need to add the I prefix. I’m torn. I feel in my heart of hearts that using the IConvention does more harm than good. Yet, readers of the book will be familiar with the IConvention and may be confused by examples that don’t use it. What’s the right thing to do?
Tue, 18 Oct 2005 12:04:30, Monica, The beauty of word processors Go without the ‘I’ and tell your readers/reviewers to embrace change.
As a compromise, have your code examples highlight the interface with a format option that clearly communicates it’s the interface you’re referring to..How often do you see the ‘I’ anyway? Only on declarations/assignments correct? IMO what matters is the context that the interface is used in communicates reason and logic for using an abstracted or interfaced element.
Mon, 17 Oct 2005 16:37:14, Runar, IConvention and Hungarian Notation are Evil Micah, sometimes you must compromise, but never on principle. Your gut feeling and your experience are telling you the right thing. Our guide here is a general form of Codd’s Information Principle:
“Data should be stored in relations and in no other way.” More generally: Encode information in semantics, not in names.
To clarify; The indication that something is an interface should be codified as the relation “is an” between “something” and “Interface”. Calling it ISomething only causes you to have to maintain this relation in two places (which, incidentally, violates the OnceAndOnlyOnce principle). And maintenance is more difficult because these semantics cannot be discovered without parsing the type names. Besides, this parser breaks the moment somebody creates a class that violates naming conventions.
Mon, 17 Oct 2005 14:11:45, Phlip, reviewers There’s always a difference between what reviewers say and what a thought leader (or us;) should do about it. ;-)
Sat, 8 Oct 2005 07:53:37, Jed, Hungarian Notation I’ve always felt that Hungarian notation was nothing more than a “helper” for those languages with loose typing (e.g. Visual Basic, C/C++, and so forth) to help us work around the limitations of the language to prevent subtle (and not so subtle) conversion errors. When using a strongly typed language like C#, Hungarian notation serves no useful purpose. The only instance I see Hungarian notation used in C# is as a visual cue that pure abstract classes (interfaces) support multiple inheritance.
I realize this a recursive argument, but I go back to my original assertion that the only reason Hungarian notation is used here is to work around the limitations of multiple inheritance. As a potential point of contention, how many implementation classes that derive from IEnumerable have nearly duplicate code that iterate through a simple array? I tend to agree that multiple inheritance is rarely needed, but the only choice currently available is to duplicate the code with interfaces in those instances that it is needed.
However, I think the more important argument is that the I prefix is so entrenched at this point that breaking away from “tradition” is likely to cause more confusion. I feel your pain, but I think the real argument is that Visual Studio .NET and Subversion do not play nicely together yet. In other words, the more appropriate answer is better integration between Visual Studio .NET and Subversion to support “painless” renaming of files. Whether this is a new version of Ankh that isn’t quite so “broken” or a replacement product that works as well as Tortoise within Visual Studio .NET.
Sun, 25 Sep 2005 09:02:16, Barry, It’s just old IDEs vs. new IDEs Most modern IDEs (Eclipse, VS.NET) will assist you (class browser, syntax checking) and tell you whether or not you’re using an interface or a class. Older IDEs did not. Hence the naming conventions we have now (Hungarian et al.). However given the size of C# libraries and intended audience, it is probably better to stick with convention.
Wed, 21 Sep 2005 10:44:11, Tom Rossen, Syntax vs. convention
Using or not using IConvention is just a convention. When speaking English I (try to :) ) use articles. When writing C# programs I use IConvention.
Let’s not confuse C# with a natural language. Articles are part of the syntax of a natural language. Hungarian notation is a convention, one that moves code further away from natural language and therefore from readability.
BTW, “Hungarian notation” strikes me as an ethnic slur. How about “kitchenSinkNotation”?
Fri, 16 Sep 2005 19:27:12, Alex, AConvention in English. Answering uncleBob regarding nNouns etc. There are some languages out there that do not use articles. Your suggestion
Let’s prefix every noun with an (n), and every nadjective with an n(j), and jevery nadverb with a n(y), and jevery nverb with a (v). could look to them funny without anything else just because of multiple usage of articles a or an which do not add a single bit of extra information to the message.
However it seems to look natural to you.
Using or not using IConvention is just a convention. When speaking English I (try to :) ) use articles. When writing C# programs I use IConvention.
Anything that let people better understand each other is Ok. Sacred Wars don’t.
Fri, 16 Sep 2005 19:22:47, ,
Tue, 13 Sep 2005 22:05:58, Chaz Haws,
The “interface” is a kludge.
It’s not that we “need some multiple inheritance” - what we need is to combine two previously independent sets of behaviors.
Of course you’re right, vendors and standards should definitely go with pure abstractions. Doesn’t mean that’s appropriate for my code. Remember, I’m not questioning the presence of interfaces, I’m questioning the absence of full implementation multiple inheritance.
I’ve got nothing against an “interface”. But I’d like them a lot better if I could migrate them to abstract base classes without breaking multiple inheritance. That’s often critical to reduce duplication.
If I could do that, arguably there would be no perceived need to visually distinguish them with the I. And suddenly we’re back on topic!
Tue, 13 Sep 2005 12:41:12, ,
The “interface” is a kludge.
Whoa! I resemble that remark. An interface is a pure contract/specification. Its value may be more obvious in Java than in C#, because Sun encourages multiple vendors to provide implementations. An abstract class is a pragmatic partial generalization. It’s not that we “need some multiple inheritance” - what we need is to combine two previously independent sets of behaviors.
I know how to build ugly structures with interfaces and composition around the lack of something basic like inheritance, but the problem is I shouldn’t need to.
They don’t need to be ugly. The same desired behaviors and properties can be encapsulated in the same number of classes - they just won’t be base classes.
Mon, 12 Sep 2005 17:48:40, Chaz Haws, RE: Single-inheritance rant Tom, my own take on multiple inheritance is that it is rarely needed but shouldn’t have been removed from either Java or .NET.
The “interface” is a kludge. “We need some multiple inheritance, but that’s hard and you folks can’t be trusted with it, so we’re going to make up a new special kind of abstract class and let you use it with that.”
Well, to be honest that’s worked pretty well. But it’s also true that this whole thread is caused by the artificial distinction between an interface and an abstract base class. When artificial distinctions start getting in the way, it makes me want real multiple inheritance back.
Mon, 12 Sep 2005 17:21:32, Willem Bogaerts, abstractness
If I’m a derived class, I need to know what I can use from my base classes and what I have to define, don’t I? This seems fundamentally different from “outsiders” that don’t care whether method X is implemented by me or an ancestor. I’m NOT an outsider. I’m very much in the family.
No you don’t. If you are a derived class, you ARE a form of the superclass. So you’re everything but an outsider. Like Constable John Doe IS a policeman. And if you do need to know, you still don’t know unless you mark the abstract methods, not the class itself, with an ‘I’. An interface just is a purely abstract class.
I know how to build ugly structures with interfaces and composition around the lack of something basic like inheritance, but the problem is I shouldn’t need to.
As for prefixing, I’m torn between two sides. In languages where multiple implementation inheritance is forbidden, the prefix warns you in case you want to extend two “normal” abstract classes. Even before you write the “extends” keyword. On the other hand, you get a situation where “all abstract classes are equal, but some are more equal than others”. Classes that are not part of the interface-or-class struggle don’t need to know if a type is an interface implementation, and abstract class or an imlementation class.
Mon, 12 Sep 2005 10:36:17, James Grenning, Ditch the I, and th m_, and the DAO Get rid of the “I”. Also you C++ programmers should get rid of the “m” and you DAO fans should get rid of the DAO suffix. All these annotations put up a barrier to being able to “read” the code. When I read ICommand I feel like there is something missing, like I Command you to take out the garbage. When I see the C++ programmers “m” I find myself humming while I read the code mmmmm counter, mmmmm index, mmmmm transmitter, mmmm window. Was the programmer really happy and humming, or were they confused and not sure what variable name to use? Probably the latter. Ohhh. a member variable, that is something special.
DAO? I’d like to be reading in code in the problem domain if possible. DAO is a solution domain suffix. High level design should try to speak to the reader in the problem domain. What reads better Employee.pay() or EmployeeDAO.pay().
I guess I went a little off topic, but i feel better now.
Micah, please leave off the “I” and explain your reasoning. Maybe this will help Microsoft programmers to break themselves away from hungarian notation.
James
Mon, 12 Sep 2005 09:54:52, Tom Rossen, RE: Single-inheritance rant Ignoring for the moment the issues of thread and type safety (generics are now available in Java 5)….
When I … graduated … from C++ to Java, I was pissed about the lack of multiple inheritance. But eventually all the OO propaganda about “composition” started to make sense. I don’t know PHP, but I’ve created collections in Java that were similar to the one you describe.
Essentially you’re building multiple indexes over a single collection, and it should be possible to do this by composition in any reasonable OO language. I suspect that a combination of abstraction (polymorphism and interfaces) and composition could solve just about any problem that presents itself as requiring multiple inheritance.
Mon, 12 Sep 2005 08:50:35, sdc, dsd ff
Fri, 9 Sep 2005 18:31:17, David Chelimsky, super-abstractness Willem Bogaerts wrote “the "abstractness" level of the super class is surely an implementation detail. And implementation (or the lack of it) should not be visible to outsiders!”.
If I’m a derived class, I need to know what I can use from my base classes and what I have to define, don’t I? This seems fundamentally different from “outsiders” that don’t care whether method X is implemented by me or an ancestor. I’m NOT an outsider. I’m very much in the family.
Fri, 9 Sep 2005 14:12:50, Willem Bogaerts, Single-inheritance rant
But now we have strongly typed languages.
If you mean java, we have not. In the XP yahoo group I held a little rant about the claim that multiple inheritance would be difficult. On the contrary.
In my example, I wanted to write a collection class for PHP (it is not built-in). As I wanted to select the members by position or by name, they should inherit the NamedItem interface. After I did that, I noticed that all the subclasses shared the same code for setting, keeping and retrieving the name, so I changed the interface to an abstract class and put the code there. But that prevented me to store Tests, DatabaseQueries, and lots of other useful classes in a collection. Now, what is difficult about a class being able to have two superclasses? On the contrary, try to explain what is wrong with it. Single-inheritance-with-interfaces is a defect in languages that claim to be object-oriented. I think the prefix was introduced because it facilitates the programmer in typing the right keyword (extends or implements). But that keyword should not be necessary, as the “abstractness” level of the super class is surely an implementation detail. And implementation (or the lack of it) should not be visible to outsiders! Back to the collection, the language prohibits the use of a general abstract member class. Now I understand why, in an so-called “strongly typed” language like java, every internal storage has to be done with general “object”s and a lot of casting. I don’t see any strongly typed language here.
In short, this interface thingy is a language bug that you keep fighting day by day.
Wed, 7 Sep 2005 09:17:23, Tom Rossen, Awkwardness… I’m imagining Copernicus’ reviewers saying “Hey - where are all the epicycles?”
Can’t do anything about the FCL - untouchable legacy. But I trust Micah can handle this issue in the introduction. It shouldn’t be any more awkward than explaining how agile techniques differ from traditional approaches.
Tue, 6 Sep 2005 22:35:39, Naim Ru, Recanting…
OK, I can buy the arguments for going against the MS standard, and promote a new standard in C# for naming interfaces (in the hope of someday getting rid of the last remnants of Hungarian notation). Meanwhile we’re still stuck with the IPrefixedInterfaceNames in the .NET FCL; perhaps being inconsistent with this is not such a big deal.
However, remember that Micah posed this issue in the context of writing a book, where he may need to deal with the awkwardness of having two different naming convention for interfaces in print (his own + FCL’s), with no IDE or complier to help out the faithful reader… yeah, that could confuse some people.
Tue, 6 Sep 2005 16:02:18, Liz, ICommand I was translating a ton of java into C# and discovered that I had to add the I. Otherwise property conventions didn’t work correctly.
I did it, I hate it, and now I wonder if I have to change the java to mirror it.
Tue, 6 Sep 2005 14:56:28, Marco A, can’t stop the huns For whatever reason, people get addicted to the Hungarian notation and can’t let it go.
Tue, 6 Sep 2005 09:45:10, Tom Rossen, As IF…. Having fought the battle on multiple projects against pre- or post-pending “IF” in Java, I would urge you to take a stand against “tradition” (~= “antipattern”) here.
An interface has two audiences: users and extenders. If you’re using it, you shouldn’t care whether it’s an interface or a class, unless you try to instantiate it, and the compiler will tell you soon enough. Most of the time you’re not instantiating, just referencing.
If you’re extending it, you need to look at the doc or the source anyway.
Well-written code (small classes, small methods, clear separation of responsibilities) has no need of Hungarian notation. What makes code readable is its approximation of natural language - Hungarian notation degrades that.
Tue, 6 Sep 2005 09:20:20, Casey, Ummmm - hardly an issue If you don’t use I…. then you are creating a different standard to the one almost all MS/C# programmers adhere to. So the first problem is confusion.
The second and bigger one is, the example you give is flawed. If you hose to turn your ICommand interface to a base class, then renaming isn’t going to be the issue (as it can all be done by Resharper or equivalent in a few seconds at most). The problem is that many classes implementing your ICommand interface could now be very broken due to C# not supporting MI - so anything that has a base class already isn’t going to work… and now you have a massive architectural nightmare.
Think first…. Agile doesn’t mean ‘hack it together quick and fix it later’
Sun, 4 Sep 2005 02:32:59, Naim Ru, Interfaith Interfaces?
The .NET framework is filled with IPrefixedInterface names.
Looking at the following examples in printed form, which would be preferable, the following with inconsistent naming and perhaps a comment?
- class Unforgettable : Fire, IList // yucky comment: Fire is an interface
- {
- // ... implementation here
- }
… or this following one?
- class Joshua : ITree, IList
- {
- // ... implementation here
- }
So, on the one hand you have potential confusion due to inconsistent naming conventions and you violate typical C# developer expectations. In printed code, you may have to add comments to help sort things out.
On the other hand, you have a notation (I*) that gives client code knowledge about a type it references which it does not strictly need (that it is an interface), which results in some small – but not insignificant – renaming pain that can happen during refactoring.
This is an interesting dilemma and a very close call. I prefer the consistency, and until I see better reasons to abandon the C# interface naming standard, I will continue to use IPrefixedInterface names in .NET code.
Sat, 3 Sep 2005 10:07:16, keithray, about I-prefixed interfaces See if you can put this story (“how I started with an I-prefixed interface, then changed it to an abstract class, and all the pain the ‘I’ caused”) early in the book, and say that for the remainder of this book, you will not use the I prefix and that you recommend your readers don’t do that either.
Thu, 1 Sep 2005 01:03:01, Chaz Haws, When to use an interface Okay, Micah, one more comment: In my work, the behavior that I’m looking for would almost always allow either an interface or an abstract class. I have so far tended to use the interface notation, due to brevity. But my most likely line of evolution is just as you describe. I make those kinds of changes all the time.
Come to think of it, I probably shouldn’t be using interfaces at all. I almost never need the multiple interface inheritance.
Thanks for making me think about it. I think I’m going to write a lot fewer interfaces.
Thu, 1 Sep 2005 00:44:31, Chaz Haws, Interface notation I don’t care for it myself. But I can see it being useful because it instantly communicates that multiple inheritance is an option for this type (as others have mentioned). If you can’t personally run all the tests that will demonstrate that converting from an interface to an abstract class, then that conversion isn’t really an ideal option for you anyway (as others have mentioned). If you’ve got those tests available, then this is a real issue, and you’ve got a good solution. People will nitpick it, though. Especially people that don’t think about source control all the time, like I do. How many reviewers reported that they were confused, as opposed to guessing that other people would be confused? I’m guessing zero. I hate having to make such choices. I feel your pain. Two parting thoughts: Multiple implementation inheritance would make this (rather artificial) distinction completely moot. I still miss that from C++. And we need more advanced source control to deal with just such refactorings. Name changes as classes evolve and source control needs to deal with that.
Wed, 31 Aug 2005 10:14:13, David Chelimsky, I think that a very interesting part of this discussion is the notion of where (in a design) to use an interface and when (in process) to introduce one.
As for the “when” question, the notion that we should introduce them earlier rather than later denies (defies?) TDD as a design activity. We don’t know that we need an interface until we need one, right? Experience suggests that in many cases this will be very early on - perhaps even during domain model discussions (if that’s your approach), but it also suggests that we won’t catch all the cases up front, at which point we need to be able to easily introduce interfaces later in the process.
As for the notion of the correct way to use interfaces, I find it limiting to suggest that they are only there to describe behavior. Agreed that interfaces serve us well as definitions of behavior, but I think that they also serve us well as definitions of structure. Expressing high level domain concepts like People and Accounts in interfaces allows us to begin to decouple implementations of one from the other, allowing us to choose where to start development based on business value rather than a preconceived notion of architecture. Not to mention dependency injection frameworks that prefer interfaces.
Wed, 31 Aug 2005 05:15:20, Thomas Eyde, Published code and Java vs C# syntax Some additional points: If this is a published library, then a rename will break existing code outside of our control.
Java has “extends” and “implements” which communicates very well on what the class inherits. C# doesn’t have that, instead it uses the convention that if you inherit from more than one thing, the first must be a class and there can only be one class.
I am not sure that is a valid argument. I used to think Hungarian notation was a good thing, too. I guess I have to try out my interfaces without the “I” before I make up my mind.
Wed, 31 Aug 2005 05:27:14, E Charignon, Make your book easy to read. As it was said before, modern tools tend to make this ‘I’ prefix convention useless. Unfortunatly, you don’t find this ease of navigation when reading a book and naming convention helps a lot. I made myself the same reflexions about comments. It might be wellcome to overcomment code examples into books because you are explaining something (you want to say in plain english what the code is doing) and the code there is not going to change once it has been printed. At the contrary, you would not make so many comments in you code since it will make bugs difficult to find and comments maintenance is a nightmare.
Wed, 31 Aug 2005 03:14:17, J Drakes, Use of interfaces I see. you suggest to use the -I- like the -able- in java. Interfaces that are root to “structural” objects rather than “behaviour” objects (pardon the artificial distinction) would drop the I. Behaviour tags would keep the I.
Tue, 30 Aug 2005 23:47:40, Eddie de Bear, Time to learn about correct use of Interfaces. I think you may actually be incorrectly using interfaces if this is the problem you have with them… Interfaces should be used for secondary behaviour, such as IDispose, ISerializable, IBendable, IKickable etc. i.e. where actually deriviving from a base type is not going to work. You can still treat each object as it’s interface type, even though it’s not… Maybe the I should be changed to B for Behaviour!!!
The real question is, do you have a problem with the I prefix, or do you have a problem correctly selecting between an interface and class in early stages of development???
Just my 2cents…
Tue, 30 Aug 2005 21:09:27, Keith Nicholas, Aye Aye Cap’n I think you should keep the I, but explain your reasoning why you don’t like it. However, your justification (so far) sucks. “I don’t like “I”s because my tools make it slighlty painful to change it later” dosnt seem like a really good reason to not have “I“‘s. If that was your reasoning then if resharper was made to automatically do a rename in subversion you’d be happy. Also if this was the case, then you should do some design up front so you get the names of classes right before you start work because its “painful” to change later….hmmm…
5 years of Extreme programming with C# using I’s and I’ve never thought, “bugger, I wish we hadn’t prefixed an “I” onto this”. When we have needed, we have simply taken the I off and made it abstract. no big deal. I did have a bit of hesitation in the beginning with pushing type information into the name but it really hasn’t hurt us. If you do think it does major harm I’d be interested in your reasoning that adds up to a “good deal of hurt” if you had a tool that renamed ICommand to something else in < 1 second….
Tue, 30 Aug 2005 13:33:14, Ivan Vaghi, Hungarian Notation Contrary to popular belief there seem to be some valid uses for Hungarian Notation, and it looks like its actual use is quite different from what it was originally intended for.
Spolsky here explains how to use it to create a ‘conventional’ algebra http://www.joelonsoftware.com/articles/Wrong.html
eg: daysTime1 + daysTime2 is correct daysTime1 + hoursTime2 is not correct daysTime1 + daysFromHours(hoursTime2) is correct
where both days and hours are plain numbers
Of course, you could use typed objects, but sometimes it’s just not worthed. Also note that the prefix indicates the semantic value of the number, rather than just pointing out the type of the number.
Hungarian-like naming can also be useful in dynamic languages for readibility.
eg: def enroll(aperson) #aperson is (usually :-) of type Person def distance(startpoint,endpoint) #it’s getting 2 Point instances
The hungarian-like style I like gives semantics, not just syntax.
Tue, 30 Aug 2005 13:01:44, Ben, IThinkYouMayBeOnToSomething Its funny, I’ve always hated the Hungarian notation. I’m not sure if this convention arose from that hideous pain of a standard, but for one reason or another its a standard that I happened to adopt. Probably for no other reason than seeing it used in other peoples code. What can I say, monkey see, monkey do.
What do you think of the hungarian notation? The developers at my new company love it, and really don’t want to abandon it, despite all my pleas. From what I’ve seen on the web, there are valid arguments on both sides of the coin.
Tue, 30 Aug 2005 11:35:33, Bill de hOra, Your reviewers are guilty of foolish consistency. Java went through this way back when with people appending IF to interface names, before it was dropped as a bad idea. Interfaces in static languages have enough problems without this cruft.
Put it this way. If you don’t drop the convention, I won’t buy the book.
Tue, 30 Aug 2005 10:06:18, , Ni vagree!
Tue, 30 Aug 2005 08:40:08, UncleBob, Hungarian Notation in the 21st Century. There was a time, long long ago in the 80s, when C compilers did not check types and programmers could pass ints to functions that took doubles, that Hungarian Notation (HN) might just possibly have been a sort of OK idea maybe. Maybe.
But now we have strongly typed languages. Now we have IDEs that tell us the type of an identifier simply by hovering over them with the mouse. Now we have Object Oriented languages which soften the notions of “type” and nudges us to hide type rather than expose it.
So, Captain, we are no longer using stone knives and bearskins to get our jobs done. And we don’t need the trappings that, just possibly, maybe, were a sort-of good-idea in the stone age.
I don’t miss the I’s (or the C’s, or the pszqt’s)
Hay! I’ve got a great idea! Let’s prefix every noun with an (n), and every nadjective with an n(j), and jevery nadverb with a n(y), and jevery nverb with a (v). nPeople vwill yquickly vfind nEnglish vto vbe jmuch jmore jreadable.
Tue, 30 Aug 2005 08:19:45, Michael Feathers, Micah wrote “Here’s my dilemma. Maybe you can help me. I’ve been translating Unclebob’s Agile Software Development book into C#. In the code examples I have heeded my experience and created interfaces without the I prefix. Reviewers don’t like this. They keep telling me that I need to add the I prefix. I’m torn. I feel in my heart of hearts that using the IConvention does more harm than good. Yet, readers of the book will be familiar with the IConvention and may be confused by examples that don’t use it. What’s the right thing to do?”
I think you should use the convention after you tell the reader just how stupid it is. I think I railed against it in WELC twice. Couldn’t help myself.
Tue, 30 Aug 2005 08:10:58, Mark Howard, drop the I Drop the I, it’s a bad convention that should have never been there. It smells of hungarian notation
Tue, 30 Aug 2005 06:46:21, Dave Hoover, I Agree with Thomas and Tanton Don’t rename the interface, implement it with an abstract class. Stick with the conventions of the language, readable code is the first step toward adaptable code.
Tue, 30 Aug 2005 04:46:50, Thomas Eyde, IConvention I don’t really see the problem. Why don’t you just do:
abstract class Command : ICommand {}
And you could have both artifacts in the same file, without the “I”: Command.yourfavouritedotnetlanguagesuffix
Tue, 30 Aug 2005 03:14:07, J Drakes, Different audiences This is not the first time I meet this problem. The way I see it, if you are a ‘user’ of the classes, then you shouldn’t care at all about the implementation details of what you call, you should just focus on the readability of the code. You are just using some ‘words’ whose use and semantics are expressed by the test cases. However, the very moment you decide that you want to modify that code, then you get swamped in all kinds of syntax-oriented technicalities and then you have to care about the nature of the ‘words’ that you are using, and those ‘I’ that you use to colour your code can be handy. I don’t have one single answer for you.. it depends. I usually solve it giving my expert users a set of classes that are easy on their eyes, while those classes are based on rougher code with the ‘I’s still sticking out.
Mon, 29 Aug 2005 23:51:02, Tanton Gibbs, Additional Problems I think there are more problems than just renaming files. If ICommand were an interface, then it could participate in Java and C#’s multiple inheritance of interfaces. However, if ICommand were suddenly changed to a class, many classes could be unduly broken. Determining if an entity should be an interface or a class should be something you strive to get right at the beginning. If you choose the interface prematurely, then I would think that you could add a helper class CommonCommandImpl that instantiates the interface and other classes could choose to inherit from if it made sense for them. Therefore, I think the least of your worries is renaming and if you chose to put the I in front of interfaces it would be neither a good nor a bad decision. I think if it is an “idiom” for that language, then you should follow it.
Software Apprenticeship
by: micah | September 7th, 2006 | 0 comments »
David Hoover asked me a few questions about my experiences as a software apprentice. I was happy to answer his questions and pleased to hear that he’s writing a book on the topic.
What is Software Apprenticeship?
Software apprenticeship is path for learning to become a quality software engineer. A software apprentice learns to write code by working with people people who already know how to write code and are good at it.
It’s also an attitude. People who practice the software craft are on a journey of continual learning. There is no piece of paper that deems a craftsman worthy. A craftsman qualifies himself by demonstrating his skills.
I’d argue that any great software developer has been through an apprenticeship stage at one point or another.
How did I hear about Software Apprenticeship?
I saw my father reading a book titled Software Craftsmanship by Pete McBreen. This was shortly after I finished an unsatisfying 5 years in college. I was also knee deep in my apprenticeship, though I didn’t call it that at the time. I read the book and fell in love with the idea that software is a craft. For several years of my life I practiced martial arts and the model for growth in Jujitsu is very similar to that of software craftsmanship. So the concepts were not new to me but seeing software in this light clarified a few things…
No wonder I was so unsettled with my college education… That’s not how you’re supposed to learn software. Of the dozens of classes I took in earning my Computer Science degree, only 3 classes involved writing code. Crazy huh? And even though I could write programs after I graduated, I didn’t know the first thing about writing real software. A lot of good college did me! It was working with the great people at Object Mentor, especially my father, that truly taught me to code.
Not long after I read Pete’s book, Ken Aurer invited me to a Software Apprenticeship summit. There, several pioneers in the software craftsmanship movement got together to share experiences. I learned a great deal but what I took away from that summit was the comfort that there were lots of people who believed in the craftsmanship model. It was only a matter of time before the rest of the industry caught on.
Where am I in my journey?
For those new to the craftsmanship model there are three stages: apprentice, journeyman, and master craftsman. I’m well on my journey as a journeyman. I work on a variety of software projects, I teach, I consult, and I learn more about software every day. And to take this entry full circle, I help other budding software apprentices get started on their journey by leading Object Mentor’s apprenticeship program every summer.
Wed, 22 Jun 2005 21:53:29, David Chelimsky, hands on I had the good fortune to attend a graduation at which Deborah Meier spoke. Ms. Meier is an innovator and educator who founded a grade school at which kids of varying ages/grades work in the same classroom. She described the inspiration for this, talking about how schools USED to be when we (in the US) were a more agrarian society. There were two comments she made that seem relevant in the context of this discussion. One was that you would never choose to take a tennis class in which students sat around talking about tennis and then, one special day, the teacher brought in an actual tennis ball and passed it around so everyone could hold it and see what it felt like.
The other was the fact that in days of school gone by there were many experts and a few novices. The 7 year olds helped the 6 year olds. The 8 year olds helped the 7 and the 6 year olds. Etc, etc. Many experts and few novices - not one expert responsible for 30 novices. This made me think of the blacksmith analogy that permeates the Craftsmanship book.
Wed, 22 Jun 2005 01:53:36, KelleyHarris, ?Finding mentors for mid-career people? Great article Micah. Any suggestions for mid-career people looking to find mentors, full-time, part-time, or remote? Seems like there is room for a service connecting people. There is also room for a service providing object mentoring post OM courses.
There is no piece of paper that deems a craftsman worthy. A craftsman qualifies himself by demonstrating his skills. As people look for new jobs, what would be some good ways of demonstrating skills, at the resume & interview stage?
Any suggestions on open-source projects with great OO TDD code?
Mon, 20 Jun 2005 08:51:34, George Jensen, My Story I guess my story would be different from Micah’s in that, Higher Ed was good for a few seasons, but by no means did I expect to begin learning a craft there. If the above statement were a microcosm for Liberal Arts experience, we might assume it a bankrupt philosophy. This is the impression Micah might give off. After spending a week with Uncle Bob with Java immersion (2002), I can say I was one of those “Masters Level” students who knew nothing of good programming practices. I studied History in undergrad, and Information Science in Post-grad; but I continue to be pulled by the curious efforts Uncle Bob uses to hown the craft of programming, and his old-factory style of learning programming as a “craftmanship”.
I ask daily: With all the altruistic spirits of academia stuffed down our modern minds, why is it so refreshing to hear the obscure rant of Uncle Bob (and others) toting this old-factory campaign about “craftmanship” as a life goal?
Fri, 17 Jun 2005 10:02:01, Uncle Bob, Things have indeed changed. Keith, Things have indeed changed; at least in some sectors. A couple of years ago I brought in an intern who was in a CS masters program. This inidividual simply could not write code, nor had they been taught to write code. I was flabbergasted. I’ve poked around a bit since and have found that, at least at some schools, it is possible to acquire a BSCS, and even an MSCS, without ever having to write a line of code. Incredible!
Thu, 16 Jun 2005 11:22:16, Patrick Morrison, Things were different, but not necessarily better I must’ve gone to college around the same time Keith Ray did, as I can’t think of a CS course I took that didn’t involve at least some programming. But, with one exception (Principles of Software Engineering), every single course required the student to work alone… this is the antithesis of the craftsmanship model, and I’m sure it stunted my growth as a practicioner.
Thu, 16 Jun 2005 09:50:09, keith ray, things have changed When I went to college and got a computer science degree, just about every computer science class required writing code. The only one that didn’t was the one where we designed a CPU. Those who were in computer engineering rather than computer science had a sequel to that course: they had to implement their cpu design.
We programmed in FORTRAN, Pascal, C, 68000 assembler, and COBOL, and the “survey of computer languages” course had us writing short programs in APL, LISP, SNOBOL, and other some other languages.
Jack and Jill
by: micah | September 7th, 2006 | 0 comments »
Once upon a time there live a young girl named Jill and her next door neighbor Jack. Perhaps you’ve heard of them. When Jack and Jill were about 5 years old they both desperately wanted to learn how to ride a bike. Jill’s father, being a practical man, bought Jill a nice child-size bike and took Jill outside to practice riding the bike every chance he got. Jill’s dad would hold Jill up right and move with her while she pedalled. Within a few days Jill was able to ride for moments at a time without her father’s support. After another day, Jill could ride her bike all by herself.
Now Jack’s family was a bit more rigorous. Jack’s father thought it important that Jack have a solid understanding of bike riding and the science behind it before he start riding a bike. So instead of a bike, Jake’s dad bought various books on physics and cycling history. For weeks Jack learned from his father much about kinetic and potential energy. He gained an understanding for gyroscopic forces and much, much more. After about a month, Jack knew everything there was to know about bike riding. It was at this point that Jack’s dad bought a bicycle for Jack. Jack proudly mounted the bike and promptly fell off. He mounted the bike again, peddling slowly and ended up in another painful fall. Meanwhile Jill was effortlessly riding her bike around block, feeling bad for her friend Jack.
Later in life both Jack and Jill graduated high school and wanted nothing more than to become software developers. Jack, following societal protocol, applied to a prestigious university was accepted to the computer science (CS) program. At the onset of his first semester, Jack was mildly disappointed to find that CS program alloted only one class in the first semester that had anything to do with computers. This class was called “Computer Algorithms I” and involved no programming what
