Object Mentor Blog http://blog.objectmentor.com en-us 40 Working on C++ Book Again <p>Picked up working on a book on C++. It&#8217;s freely available (as I work on it) and a <span class="caps">PDF</span> is available <a href="http://schuchert.wikispaces.com/cpptraining.CppAndOodTheLeastYouNeedToKnow">here</a>.</p> Wed, 03 Aug 2011 18:56:00 -0500 urn:uuid:5e8ace45-ffaa-449f-9813-73061ed1e77c Brett Schuchert http://blog.objectmentor.com/articles/2011/08/03/working-on-c-book-again Schuchert's Scattered Synapses cpp TDD ood Bamboo reminds me of a time when... <p>I needed to do some yard work. It’s nearly always windy in Oklahoma where I live, so when I got up Friday morning I noticed a distinct lack of wind and thought it would be a good idea to get started on the yard work. I was tired of getting dust, dirt and other unmentionable things in my eyes and ears and nose.</p> <p>Things started as normal, but since I got started so early I took the time to clean up the west side of the house. Then I managed to rake and clean up a bit more. I pulled some weeds. Much of the work I did was not visible most of the time but it bothered me just a little. Then I got to the part of the job that was visible. I took a little extra time raking, sweeping, mowing, etc. I was “done” earlier than I had expected and then I made a crucial decision, it was time to take care of the bamboo.</p> <p>3 years ago I planted an 8 foot by 2 foot plot of bamboo. When I did that I dug down 2 feet into the ground. Not knowing how to dig like a professional, it took me a long time &#8211; total planting time was 13 hours. 32 cubic feed of dirt and clay takes a lot of work to remove. I needed to dig so deep to put a protective lining around the bamboo. There are two kinds of bamboo you might plant. One kind stays in clumps and doesn’t invade everything. That’s not the kind I planted. I plated the kind that takes over. Thus, I needed to dig 2 feet into the ground and surround the bed with a thick plastic lining. I did all the prep work but then I decided I would let it move into my yard but not into the neighbor’s yard. So I left the front of the bed open.</p> <p>Fast forward 3 years and notice that the bamboo moved more quickly than I imagined. I’ve been meaning to get to this outside job, but I’ve managed to put it off. I decided to dig a 2-foot deep trench in the front of the bed and add in the missing plastic lining. It took me about 6 hours. Here it is two days later and my hands and forearms are still quite sore. Much of the digging at the top was easy, but as I got deeper, the digging got more difficult. Then I hit clay. That was even worse. I really didn’t have the right tool for the job. I needed a trench digger, but I had a regular shovel, a gardening shovel and a standard spade. These were ok at the top but not as I worked deeper into the ground.</p> <p>Finally, needing a break, I went to buy more lawn supplies including: pete moss, top soil, steaks, fencing, grass seed, lime, oh, and a 4 inch trench digger.</p> <p>I was about 20 inches into the ground. The last inch had cost me plenty. The 2 inch bruise on the palm of my right hand (yes, I wore gloves) is one example. That last inch took me maybe an hour. 4 more inches would take me longer than another 4 hours. The trench digger, however, made it more like 15 minutes.</p> <p>When I started digging I knew I needed to start wider at the top because the trench would naturally get narrower as I worked my way into the ground. This might not be the case if either a: I knew what I was doing, or b: I had the right tools for the job. So I started much wider than “necessary” to give me a little slack later.</p> <p>That decision was key. Even though I eventually bought the right tool for the job, a 4 inch trench digger, if the trench was too narrow to use it, then I still would have been out of luck. So this decision made it possible for me to use the right tool later.</p> <p>I managed to finish the trench, line the bed, replace the soil and then get about 100 square feet of yard reseeded.</p> <p>Other than sore muscles, bruises and the satisfaction of getting something off my well-aged to-do list, what other take aways do I have from this experience?</p> <ul> <li>Adoption of best practices</li> <li>Leave a little slack</li> <li>Right tool for the job</li> </ul> <h2>Adoption of Best Practices</h2> <p>(There’s a great story of a manager of a Coca-cola plant who’s numbers were far better than his peers. When asked what his “secret” was, he said simply that rather than take a best practice and modify it to meet what the plant did, he instead modified the plant to match the best practice. His secret was not trying to be too clever.</p> <p>I knew that I should have lined the bed three years ago. I knew that bamboo can spread. There was a well-established best practice on planting bamboo. It was easy to follow. I had everything I needed to follow the practice. I had a 2 foot deep hole just begging to be fully lined. I thought I was more clever (not build here syndrome anybody?) and decided to just line the back of the bed. So 3 years later I managed to spend 6 hours doing something that would have been an additional 5 minutes. If I had just followed the best practice recommended by people who were experts, I would have avoided most of the work I did and all of the bruises, scratches, etc. But I was far too smart to follow the recommendation of someone with real experience.</p> <p>The best practice when adoption best practices is to adopt the best practice. If you decide to modify a best practice to your local conditions before having direct experience with the practice, the very problems that lead you to consider adopting the practice may be the same thing that will mange to remove all the teeth out of the best practice.</p> <p>Does this mean you don’t adapt the practice? No. It just means you need to fully understand the practice and more importantly what are its intentions before you start to modify it. When you have direct experience with it, that, coupled with the knowledge of your current challenges, might give you a better chance of coming up with something that works even better. Or, you might just keep with the practice as is.</p> <p>I had another recent experience with this regarding Uncle Bob’s <span class="caps">TPP</span> (http://cleancoder.posterous.com/the-transformation-priority-premise). From my reading of his example, he also practiced <span class="caps">TDD</span> as if you mean it (http://gojko.net/2009/08/02/tdd-as-if-you-meant-it-revisited/). I talked to him about this and sure enough he confirmed it. I was working on a “known” problem, a kata. I resisted doing what he had done because it wasn’t what I had done in the past. I even recognized this and mentioned it to him. I decided to just see what happens. Well I ate crow that evening because when I did it, the kata moved quite smoothly for me. In fact, better than it had in the past. It didn’t require as much planning ahead.</p> <p>What can you do about this? If you can figure out how you tend to resist change, and then notice when you are doing so, you might be able to just work through it. In my case I could tell I was resisting change rather than rejecting the idea &#8211; if I slow down a bit and just pay attention I can make that determination, something I learned from practicing Yoga. As for how you can start to learn this, here’s one exercise you could try (http://schuchert.wikispaces.com/AlternatingHandGripExercise). Another idea is to try Yoga. Or, try pausing whenever you find yourself resisting something and ask yourself the question: am I resisting the idea or change. If you’re not sure, then give it a try (and assume you’re resisting the change).</p> <h2>Leave a Little Slack</h2> <p>I stared digging by marking a line where I wanted to put the new edge. I then dug a shallow trench about a foot wide. The extra width was to give me enough room to work. While it might seem like more work at first, in fact it gave me enough rom to move around, attack the dirt at different angles and I used the “extra” dirt to fill a hole dug by my dogs in the bamboo (I hope it recovers).</p> <p>As I got deeper, I used different kinds of shovels, and the trench became narrower because of the angle I was using to dig, which was related to the tools I used. When I finally hit clay, the larger shovels were too hard to work with both because of the angle but also because of the density of the clay and the amount I was trying to move. I started using a hand-shovel for gardening.</p> <p>When I bought the right tool it was possible to use because there was enough room for it. Unlike the other shovels that are 10 inches wide or wider, this one was 4 inches wide. It worked perfectly. I was able to take out about 1 &#8211; 2 inches laterally and 3 &#8211; 4 inches deep at a time. While it might seem like slow going, it was blazing fast compared to my previous attempts.</p> <h2>Right Tools</h2> <p>Growing up on a farm in Iowa, my dad often reminded me of the idea of using the right tool for a job. You might be able to use another tool, but if you use the right tool for the job, it will just go smoother.</p> <p>My wife bough a few pruning tools last fall. One in particular was much nicer than I might have bought. In the past I would just use the shovel to try and break the roots. This, as you might imagine, is hard work. It will eventually work, but as the roots get bigger, the work grows at least by the square of the diameter (the difficulty felt NP hard (grin) but that’s because I don’t do this work on a regular basis). When I started the trench this time, I used that tool instead of the shovel. To be sure, it required a touch more work. I had to find it in the garage (it was where I though it would be), I had to carry it to the back yard. When I finished the job I had to put it away.</p> <p>However, it was exactly the right thing to cut the roots that I came across. Trying to use a shovel to cut those roots in the past versus using a proper pruning tool is a great way to have a kinesthetic experience on the use of the right tool for the job.</p> <p>As I used the pruning tool, I was reminded of this “right tool for the job.” When I took a break to buy more stuff to do more work on the yard, I looked for and found the trench digger. It was a bit expensive. I’ll probably use it for this one job and never again. Even so, within 2 minutes of using it, I did not regret the money spent versus the time saved. This initial impression was confirmed when I moved so much more quickly than I had been moving in more difficult situations. If I never use that tool again it was still the right thing for me to do. If I ever need to dig a trench again, I’m ready for it.</p> <p>The danger is that you buy a tool for the problem you think you have but while it solves the apparent problem, the actual problem is something else. Case in point, scripting tools for ui-based checking.</p> <p>I am not against using scripting tools, far from it. However, the secret of checking the UI is to design the code so that most of the logic is unit checkable (http://schuchert.wikispaces.com/tdd.Refactoring.UiExample). The scripting tool seems to be solving the problem of manual checking but that’s a surface problem. A well-design system makes it possible to easily look at it in ways that let you know if it works as expected. We’re used to thinking about headless checking, but what about body-less checking?</p> <h2>Conclusion</h2> <p>Everything is related to everything else, right? Old habits die hard. Insert your favorite cliche here. In a sense, that’s all I’m really saying.</p> <p>I wonder if working with software allows me to figure these things out more quickly &#8211; or at least with less physical pain &#8211; or if in fact doing so makes me take longer? I became test infected in 1997. Before that I wrote code to test my code, but I did not keep it around as a living artifact. On the surface it appears to take more time and effort, but in practice doing so pays dividends.</p> <p>Moving to practicing <span class="caps">TDD</span> came later. When I started trying out <span class="caps">TDD</span>, I though it was a bit silly. When I originally read an article about Inversion of Control (http://martinfowler.com/articles/injection.html), I though “meh.” When I was originally shown Mozilla 0.8, I though “hyper cards over gopher net, meh.” In fact, I can almost predict the viability of a technological idea as the inverse of my initial impression to it.</p> <p>The cost of being wrong isn’t too bad if, as I often do, change my mind with evidence. In the case of physical labor &#8211; planing bamboo &#8211; the real physical pain of doing it poorly has a much more real feeling consequence and maybe works better for me as a way to reinforce things I already know.</p> <p>When you work do you leave a little slack? Do practices like <span class="caps">TDD</span> give you a little slack? When you follow those practices, do you try to get a “pure” experience before adapting or do you adapt from the beginning? Are you using effective tools to solve your actual problems or do you notice tools that solve an apparent problem but simply introduce worse problems than the one they were originally meant to solve?</p> Tue, 24 May 2011 10:53:00 -0500 urn:uuid:3b4bd450-c568-4119-8d22-a4df3d374039 Brett Schuchert http://blog.objectmentor.com/articles/2011/05/24/bamboo-reminds-me-of-a-time-when Schuchert's Scattered Synapses best practices adopting tools TDD A Gradle Example <p>Gradle is a build tool. Even though it is younger than Maven, I really like it and it shows decent maturity. Here&#8217;s one example of getting started using it: <a href="http://schuchert.wikispaces.com/gradle.GettingStarted">http://schuchert.wikispaces.com/gradle.GettingStarted</a></p> Tue, 24 May 2011 10:31:00 -0500 urn:uuid:cd93dee4-aa1b-4a3c-8b68-e9cda39a6c26 Brett Schuchert http://blog.objectmentor.com/articles/2011/05/24/a-gradle-example Schuchert's Scattered Synapses build gradle New century, old mistakes <p>In the early 90’s, I taught classes in Object-Oriented Analysis and Design, as well as just Object Oriented Design and Programming in C++ and Smalltalk (Java didn’t exist yet). I got burnt out teaching both kinds of classes for different reasons.</p> <p>The language classes were tough – more C++ than Smalltalk, because there was so much detail and I wanted to cover too much – notice the classic error that the instructor’s opinion is relevant to learning. Both classes were hard, though, because getting the ideas of Object Orientation across in addition to learning a language and an environment (in the case of Smalltalk) was a lot. That, coupled with a lack of discipline in not using some kind of unit testing framework was tough. (This last observation is based on my current observations of teaching similar language classes versus what I used to do last century.)</p> <p>I have fewer problems with that these days: First, I don’t try to cover it all. I just try to cover some of language highlights. More importantly, using a unit test framework makes it easy to experiment.</p> <p>On the <span class="caps">OOAD</span> front, the problem I used to have was trying to “help” the students by pointing out mistakes ahead of time, so they wouldn’t suffer the same mistakes I’ve made. That was fundamentally wrong on my part, well intended, but just flat-out wrong.</p> <p>People need to see mistakes and even make mistakes to move forward. I’ve personally learned probably most of what I know based on either making mistakes or observing other mistakes – ones I would have committed myself if my customers had not already done so themselves &#8211; thank you for that.</p> <p>I’ve recently discovered myself making this same mistake again. In this case it has to do with enforcing code coverage to get people to write tests. I used to think this was a bad idea, and maybe it is, but even bad ideas can have utility &#8211; context, context, context.</p> <p>How can this possibly be a bad idea? Well when this happens, developers tend to write tests with few checks that are heavily implementation-oriented. If the production code is written first, which is more common, it often has high path (cyclomatic) complexity. What ends up happening is developers write complex production code for many “just in case” scenarios, the code has many paths, they are told to get 80% coverage and so they write tests to verify that all the paths of their code have been executed.</p> <p>Of course, how many of those paths are essential versus incidental isn’t typically considered. Since the tests are written to drive coverage, and the underlying code is probably overly complex, the tests tend to be heavily implementation-oriented rather than intention oriented (or scenario-based). The tests are hard to write, harder to read and even worse to maintain.</p> <p>So up to a few months ago, my advice was to not enforce coverage. But a great theory is often destroyed by data. I’ve had 2 customers recently enforce code coverage on new development. Both of them experienced something like what I expect would happen. They implemented coverage standards, implementation-oriented tests got written and developers were having problems with writing unit tests. However, something else more important happened. Even though the tests were hard to maintain, many of the developers started to get test infected. That is, they started to be convinced that writing unit tests was valuable and now they needed to know how to do that more effectively; rather than this being the destination, it was a step in an ongoing journey. (Another example of a mistake I make, confusing a process for one of its events.)</p> <p>To me, someone who is writing tests, thinks they are useful and is now ready to learn how to write them more effectively is easier to work with than someone who has not written tests, don’t think they add value and certainly are not their responsibility.</p> <p>So it appears this “bad practice” has merit as an intermediate step in a longer learning arc.; one possible path through the murky testing waters. Did I make these kinds of mistakes? I’ve never been in a situation where I was told to have some % coverage, so not exactly. However, have I written implementation-oriented tests? Yes. Have I written tests with few or no checks? Yes. I still do sometimes, but much less so than in the past. Just now I do so consciously rather than out of a lack of options.</p> <p>As I see it, I committed several mistakes I’ve made in the past. First, trying to “help” people by giving advice which would allow them to avoid mistakes I’ve made in the past. Maybe those mistakes are a necessary rite of passage for some people. Another mistake I made was thinking of the learning experience as an event rather than a process. Finally, while I might be tangentially involved, ultimately someone else’s learning is their learning, not mine. They need to do what they need to do. I need to be available if necessary, but otherwise keep my agenda out of it!</p> <p>Take in the context of a class, learning really doesn’t stop after a <span class="caps">TDD</span> class, or coaching. Some might argue that learning doesn’t start <span class="caps">UNTIL</span> the <span class="caps">TDD</span> class is over – I could make that argument myself. In any case, I was looking at my involvement as “the learning event”. As I write this, I realize just how insane that really is. I wasn’t aware of my mental model until recently; now that I am hopefully I can fundamentally change how I approach this situation going forward.</p> <p>What are some other “don’t do’s” you’re aware of that make sense in the context of a process, but not as an end or goal?</p> Wed, 19 Jan 2011 15:13:00 -0600 urn:uuid:cfe434ea-24c9-4d80-a708-2952ddace567 Brett Schuchert http://blog.objectmentor.com/articles/2011/01/19/new-century-old-mistakes Schuchert's Scattered Synapses TDD training learning education event process Tdd for the iPhone: Continued <p>After a week in Israel and the UK, I got back to this series. I&#8217;ve switched to using XCode 4, but as it is not officially released, the videos I recorded using it were a bad idea to upload.</p> <p>Back to XCode 3: <a href="http://www.vimeo.com/album/1472322">http://www.vimeo.com/album/1472322</a></p> Mon, 22 Nov 2010 00:45:00 -0600 urn:uuid:4aab9cfc-47ab-484a-a981-990347659e29 Brett Schuchert http://blog.objectmentor.com/articles/2010/11/22/tdd-for-the-iphone-continued Schuchert's Scattered Synapses TDD iphone xcode refactoring iPhone and Tdd: The Video Series Begins <p><a href="http://www.vimeo.com/album/1472322">http://www.vimeo.com/album/1472322</a></p> <p>Title says it all. Well, I&#8217;ll add that this was take #20 (or so). It&#8217;s rough getting back in to video recording mode. I will do more in this series.</p> <p>And I barely know Objective-C, so as the series progresses, I&#8217;ll expect some help on better practices.</p> Thu, 11 Nov 2010 02:03:00 -0600 urn:uuid:db408603-c72d-4977-a3ed-46803ef9c829 Brett Schuchert http://blog.objectmentor.com/articles/2010/11/11/iphone-and-tdd-the-video-series-begins Schuchert's Scattered Synapses TDD objectivec xcode getting started video Info Please: Tdd and Pair Programming <p>I often get asked to provide background materials on <span class="caps">TDD</span> and Pair Programming.</p> <p>Here are a few I often cite, but can you point me to some more? Are there any that you particularly like/dislike?</p> <p>I would like both for and against. I prefer research or experience rather than rants, though if the rant is funny&#8230;</p> <p>Thanks!</p> <p><del>&#8212;</del><p/> (This is taken from a recent email I sent.)</p> <h2>Start Here</h2> <ul><li><a href="http://en.wikipedia.org/wiki/Pair_programming">http://en.wikipedia.org/wiki/Pair_programming</a></ul></li> <p>Good overview and sites studies.</p> <h2>Then here</h2> <ul><li><a href="http://accu.org/index.php/journals/1395">http://accu.org/index.php/journals/1395</a></ul></li> Here&#8217;s a good Snippet from that site: <blockquote> <span class="caps">A 1975</span> study of &#8220;two-person programming teams&#8221; reported a 127% gain in productivity and an error rate that was three orders of magnitude less than normal for the organization under study. [Crosstalk] </blockquote> <h2>Pairing in Education</h2> <ul><li><a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.89.6834&#38;rep=rep1&#38;type=pdf">http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.89.6834&#38;rep=rep1&#38;type=pdf</a></li></ul> <h2>Other Articles</h2> <ul><li><a href="http://www.stsc.hill.af.mil/crosstalk/2003/03/jensen.html">http://www.stsc.hill.af.mil/crosstalk/2003/03/jensen.html</a></ul></li> Tue, 09 Nov 2010 08:58:00 -0600 urn:uuid:bcc270bf-5c58-4c7e-af9d-074346d38282 Brett Schuchert http://blog.objectmentor.com/articles/2010/11/09/info-please-tdd-and-pair-programming Schuchert's Scattered Synapses request for information TDD pairing pair programming iPhone Development with Unit Testing <p>I&#8217;m finally getting back to iPhone development. The environment is taking some getting used to and it took me some time to get to a reasonable working environment.</p> <p>I&#8217;m starting to document that. I plan to have both written and video tutorials. For now, I&#8217;ve got some rough notes put together. Have a look and feedback is appreciated: <a href="http://schuchert.wikispaces.com/iPhone.SettingUpTheEnvionment">http://schuchert.wikispaces.com/iPhone.SettingUpTheEnvionment</a></p> Tue, 09 Nov 2010 03:08:00 -0600 urn:uuid:23073f38-8101-423a-a2b5-be8dc73b9fe0 Brett Schuchert http://blog.objectmentor.com/articles/2010/11/09/iphone-development-with-unit-testing Schuchert's Scattered Synapses TDD objectivec xcode getting started CPP And OOD: The Least You Need To Know <p>I&#8217;ve put what I&#8217;ve been writing up, available for free. Not sure if I&#8217;ll ever try to get it published dead-tree form.</p> <p><a href="http://schuchert.wikispaces.com/cpptraining.CppAndOodTheLeastYouNeedToKnow">http://schuchert.wikispaces.com/cpptraining.CppAndOodTheLeastYouNeedToKnow</a></p> <p>Feedback appreciated.</p> <p>Have a great weekend.</p> Fri, 08 Oct 2010 16:34:00 -0500 urn:uuid:269b7430-05c9-47b5-b652-57187d67dd59 Brett Schuchert http://blog.objectmentor.com/articles/2010/10/08/cpp-and-ood-the-least-you-need-to-know Schuchert's Scattered Synapses cpp c ood Quick Intro To BDD Style Table Syntax <p>Here it is a over a year after I wrote several FitNesse tutorials. Several months back Bob added some new ways to write scenarios using a placeholder syntax and an alternative way to render script tables. What you end up with is something just a little less table-like.</p> <p>This is a very quick and dirty writeup I&#8217;ve been meaning to put together for nearly half a year. So while it&#8217;s not pretty, it works, shows the basics and may make you aware of something you didn&#8217;t know was there &#8211; unless you&#8217;ve been reading the release notes.</p> <p><a href="http://tinyurl.com/2wfyxyb">Alternative Script Table Syntax</a></p> <p>Comments and requests welcome.</p> <p>Brett</p> Tue, 21 Sep 2010 23:54:00 -0500 urn:uuid:01018108-8559-40bc-a148-792a6ad26482 Brett Schuchert http://blog.objectmentor.com/articles/2010/09/21/quick-intro-to-bdd-style-table-syntax Schuchert's Scattered Synapses script Tables alternative syntax FitNesse bdd slim Selection of tools for otherwise free content, Your Opinion <h1>The Question</h1> Should I be concerned that free content I release on my wiki, or the videos I release, use paid-for tools?<p/> <p>I expect people will also answer a secondary question: which tool I should use for Ruby. I&#8217;m interested in that as well, however my primary question is the general one of whether I should stick to free tools for the free content I release.</p> <h1>The Background</h1> I&#8217;m planning on recording a few <span class="caps">BDD</span> videos for Ruby and I&#8217;ve hit a bit of a roadblock. <ul> <li>Eclipse Helios doesn&#8217;t cut it for running RSpec out of the box</li> <li>I understand that The Aptana plugin might support RSpec, however in the past when I&#8217;ve used that plugin, it felt like kudzu</li> <li>IntelliJ 9.0.3 doesn&#8217;t seem to work out of the box either</li> <li>RubyMine works out of the box, but it&#8217;s not free</li> <li>RubyMine Early Access Program is free, but neither stable (less of a concern) nor long-lasting (I assume the license to use it expires)</li> <li>I&#8217;m not familiar with another cross-platform option for tools other that vi/emacs(I&#8217;m a vi user)</li> </ul> Here&#8217;s the thing, everything on my wiki is released under <a href="http://www.creativecommons.org/licenses/by-sa/2.5">Creative Commons Attribution Share-Alike 2.5 License</a>. The <a href="http://vimeo.com/user3159463/videos">videos I&#8217;ve released</a> are also freely available. So it seems strange to me to release something free that uses tools someone has to pay for to use for non-commercial use.<p/> <p>At least for the stuff I typically release that is. If it were just some video I expected people to watch and not replicate, then I&#8217;d be less concerned about the toolset. However, I hope people will use what I&#8217;ve released by attempting to replicate it. I don&#8217;t want people to have to buy tools to replicate free material. The one exception I can think of is using ReSharper for .Net-baed languages. Since people are already paying big $$ for the <span class="caps">IDE</span> in that case (mono developers probably excluded), adding ReSharper doesn&#8217;t seem like a big deal.<p/></p> <p>Since I&#8217;d like people to have the option of &#8220;repeating the experiment&#8221;, the tool selection adds another dimension of importance to me. Should it be? If I were working on a product, I&#8217;d consider tool cost a wash. If something will make me more productive and I&#8217;m going to be working on it for more than a few weeks, that justifies a tool purchase. I&#8217;ve personally spent $$ to make myself more efficient when I could not get my company/customer to pay for a particular tool. But this seems different. It seems like a barrier to entry.<p/></p> <h1>Question Repeated</h1> So what&#8217;s your opinion? If I&#8217;m releasing something for free, should I strive to find a decent toolset that&#8217;s free?<p/> <p>And I&#8217;m also interested in the implied question: What toolset should I use? Can you recommend a toolset that will work on <span class="caps">OS X</span>, Linux, and Windows XP/7? I&#8217;ve got the command line already and vim. If you can recommend free tools to make that better, I&#8217;d like to hear it. If you can recommend something that works for either Eclipse or the community edition of IntelliJ, that&#8217;s fine as well. Should I give Aptana another try? Does is RadRails plugin not take over Eclipse?</p> Sun, 12 Sep 2010 10:04:00 -0500 urn:uuid:eb3005fc-7ebe-4267-963c-ec7e12d72ca5 Brett Schuchert http://blog.objectmentor.com/articles/2010/09/12/selection-of-tools-for-otherwise-free-content-your-opinion Schuchert's Scattered Synapses The 4-contact points of software development The three laws of <span class="caps">TDD</span> are: <ul> <li>Write no production code without a failing test</li> <li>Write just enough of a test to fail</li> <li>Write just enough production code to get the test to pass</li> </ul> <p>This list doesn&#8217;t include refactoring, which is typically an assumed activity. In fact, some people refer to these rules as &#8220;red, green, refactor&#8221;. An even older version of this, from the Smalltalk community, is Red, Green, Blue. (Why Blue for refactor? I think someone was thinking <span class="caps">RBG</span> for a color space, luckily they didn&#8217;t try to use <span class="caps">CMYK</span> or <span class="caps">LAB</span>!)</p> <p>In this simple model, there two kinds of code: test &#38; production. There are two kinds of activity: writing &#38; refactoring. Interestingly, at one level it is all code. The thing that distinguishes both sets is intent.</p> <p>The intent of a test is to demonstrate or maybe specify behavior. The intent of production code is to implement (hopefully) business-relevant functionality.</p> <p>The intent of writing code is creation. The intent of refactoring code is to change (hopefully improve) its structure without changing its behavior (this is oversimplified but essentially correct).</p> If you mix those combinations you have the<i> <b>4-limbs of development</b></i>: <ul> <li>Writing a test</li> <li>Writing production code</li> <li>Refactoring a test</li> <li>Refactoring production code</li> </ul> <p>An important behavior to practice is doing only one of these at a time. That is, when you are writing tests, don&#8217;t also write production code. Sure, you might use tools to stub out missing methods and classes, but the heart of what you are doing is writing a test. Finish that train of thought before focusing on writing production code.</p> <p>On the other hand, if you are refactoring production code, do just that. Don&#8217;t change tests at the same time, try to only do one refactoring at a time, etc.</p> <p><span class="caps">WHY</span>?</p> <p>First an analogy that almost always misses since most developers don&#8217;t additionally rock climb.</p> <p>When rock climbing, a good general bit of advice is to only move one contact point at a time. For this discussion, consider your two hands and two feet as your four contact points. Sure, you can use your face or knee, but neither are much fun. So just considering two hands and two feet, that suggests that if, for example, you move your right hand, then leave your left hand and both feet in place.</p> <p>This gives you stability, a chance to easily recover by simply moving the most recent appendage back in place and, when the inevitable happens, another appendage slips, you have a better chance of not eating rock face. If you move more than one thing at a time, you are in more danger because you&#8217;ve taken a risky action and reduced the number of points of contact, or stability.</p> <p>Will you sometimes move multiple appendages? Sure. But not as a habit. Sometimes you need to take risks. The rock face may not always offer up movement patterns that make applying this recommendation possible. Since you know the environment will occasionally work against you, you need to maintain some slack for the inevitable.</p> <p>Practicing Test Driven Development is similar. If you change production code and tests at the same time, what happens if a test fails? What is wrong? The production code, the test, both, neither? An even more subtle problem is that tests pass but the test is fragile or heavily implementation-dependent. While not necessarily an immediate threat, it represents design debt that will eventually cause problems. (This also happens frequently when tests are written after the production code as it&#8217;s seductively easy to write tests that exercise code, expressing the production&#8217;s code implementation but fundamentally hiding the intent.)</p> <p>Notice, if you had only refactored code, then you know the problem is in one place. When you change both, the problem space actually goes from 1 to 3 (4 if you allow for neither). Furthermore, if you are changing both production and test code at the same time and you get to a point where you&#8217;ve entered a bottomless pit, you&#8217;ll end up throwing away more work if you choose to restore from the repository.</p> <p>Are there going to be times when you change both? Sure. Sometimes you may not see a clear path that gives you the option to do only one thing at a given time. Sometimes the tests and code will work against you. Often, you&#8217;ll be working in a legacy code base where there are no tests. Given that the environment will occasionally (or frequently) work against you, you need to maintain some slack.</p> <p>Essentially, be focused on a single goal at any given time: write a test. then get it to pass. clean up production code &#38; keep the tests first unchanging and then passing.</p> <p>I find that this is a hard thing both to learn and to apply. I frequently jump ahead of myself. Unfortunately I&#8217;m &#8220;lucky&#8221; enough when I do jump ahead that when I fail, I thoroughly fall flat on my face.</p> <p>This approach is contextual (aren&#8217;t they all?). Every time you start working on code, you&#8217;ll be faced with these four possibilities. Each time you are, you need to figure out what is the most important thing in the moment, and do that one thing. Once you&#8217;ve taken care of the most important thing, you may have just promoted the second most important thing to first place. Even so, reassess. What is the most important thing now? Do that.</p> <p>Good luck trying to apply this idea to your development work. I&#8217;m interesting in hearing about it.</p> Thu, 19 Aug 2010 22:59:00 -0500 urn:uuid:a43fda5f-eaf6-4d2d-bb76-34f395bebda2 Brett Schuchert http://blog.objectmentor.com/articles/2010/08/19/the-4-contact-points-of-software-development Schuchert's Scattered Synapses TDD refactoring 4 contact points Is it worth killing trees over another C&amp;#43;&amp;#43; Book? <p>I&#8217;ve taught a few C&#43;&#43; courses recently to people primarily moving from C to C&#43;&#43;. I know C&#43;&#43; has been around for years and it&#8217;s not in vogue like it was 15 years ago. I stopped using it full time in 1997. Even so, there&#8217;s been quite a bit of work on the library and language standard. And there are still a lot of places developing new systems with C&#43;&#43;. I know some people are still be learning C&#43;&#43; in school.</p> <p>In my most recent classes, I&#8217;ve been teaching students who have recently taken a class on <span class="caps">OO A</span> &#38; D based on the work of Craig Larman. The C&#43;&#43; class attempts to follow that class by dovetailing into what it covers. Because of this, I did not use ObjectMentors&#8217; standard C&#43;&#43; and <span class="caps">OOD</span> class. Good as it is, it has different starting assumptions. I instead wrote a class, using two problems as the entire basis of all the material I cover. I know, &#8220;not build here syndrom.&#8221; It pained me to do this, I did my research and I considered retro-fitting the OM course. The discrepancy was too large to consider reuse. And refactoring the existing class to accomodate changes, which I also considered, wasn&#8217;t practical. Looking back I made the right decision.</p> So this course has a few key design elements: <ul> <li>Problem focused</li> <li>Test oriented (sometimes test-first, other times test-driven, occasionally refactor-oriented)</li> </ul> <p>The problem-focus limits the topic coverage. If something about the language doesn&#8217;t come up somewhat naturally (not contrived) in the two projects I use, I don&#8217;t cover the material. For example, I don&#8217;t mention placement new, I only cover Multiple Inheritance if asked about it. I also try to focus on classes in the standard library. For example, std::array, std::vector, std::map, std::shared_ptr.</p> <p>Additionally, there&#8217;s an early focus on testing. That&#8217;s another thing that&#8217;s different from how I taught C&#43;&#43; say before 1995 &#8211; I really didn&#8217;t teach it from 1995 &#8211; 2007, so no comments on what I might have done differently in that span of years.</p> <p>To give you an idea of how early the focus is on test, I only show cout if asked. The first main() calls CommandLineTestRunner::RunAllTests and everything after that runs within a unit test. the last time I taught the class, I demonstrated tests executing with cslim, but still, a test focus.</p> <p>I have them use unit tests as a way to experiment with the language. In one example, I have them write tests that force a method to become virtual that was not virtual before. In another case, I do the same thing with a virtual destructor. I have them test from raw pointers into shared_ptr and then update their code accordingly.</p> Because of the test focus, I make certain recommendations that impact overall class design. That means learning C&#43;&#43; with designs supporting testability early on. In C&#43;&#43; this means (among other things): <ul> <li>Dependency Injection (OK, this is not just C&#43;&#43;)</li> <li>Virtual functions and by corollary a virtual destructor</li> <li>Storing pointers because 1. calling methods through an auto object are not virtually dispatched, and 2. you cannot put references in the standard collections</li> <li>Use std::shared_ptr to avoid memory leaks, which are detected by the unit testing tool I have them use.</li> </ul> <p>I take the class to a certain level, but I make it clear I&#8217;m just scratching the surface. I believe it&#8217;s not really possible to learn C&#43;&#43; in a 1-week class. You can get the beginnings of proficiency and be in a good position to continue learning &#8211; that&#8217;s an assumption I state up front after the students have had their first exercise &#8211; about 5 minutes into the start of the class. I try to only go into detail as the students ask questions, but at times I just want to really open up the beast and get into what&#8217;s really happening.</p> <p>To address this, I&#8217;ve started novelizing the class I&#8217;ve been teaching. I&#8217;m following the same outline as the class, but I dive under the surface and at times get to quite a bit of detail that I would not typically get into in a 4.5 day class.</p> I know this material will augment the class. This will give my students three sources of information: <ul> <li>The class itself, which is exercise-driven</li> <li>Online videos</li> <li>A novelization of the class, going into much more detail</li> </ul> <p>The thing I&#8217;m wondering is, would the book be worth making more generally available? I&#8217;m writing it so that it can stand on its own. There&#8217;s a certain advantage to knowing my students have taken the previous <span class="caps">OO A</span> &#38; D class I mentioned because it uses a problem that I&#8217;ve used on and off since 1992. This allows me to give examples from a problem they have looked at in the past and then at the current problem. I&#8217;ve not yet made references to that problem in the book I&#8217;m writing. I could, I just have not done so yet &#8211; it&#8217;s more natural in the second problem and I&#8217;m still working on the first problem (and therefor the first half of the book). I&#8217;m certain I can make those references without the previous class experience. (It&#8217;s the Monopoly problem.)</p> In any case, I need to do some research. If I do start the publishing process, a key step involves competitive research. Can you recommend any books published for the first time this century (really in the past 7 years) that have any of these characteristics: <ul> <li>Cover a minimal set of C&#43;&#43;, enough for decent OO solutions</li> <li>Have any kind of emphasis on test &#8211; at least half the book?</li> <li>Cover the language strictly through a problem-based approach rather than from a language perspective?</li> <li>Involve deliberately making mistakes and observing those mistakes to learn how the language works?</li> </ul> <p>Additionally, can you recommend any great C&#38;#43&#38;#43 books? I can list many of the ones I&#8217;ve read and enjoyed, but the last time I bought a book for myself on the topic, Amazon did not exist as an online company.</p> <p>Independent of whether I deal with trying to get this thing published as a printed book, I&#8217;m going to finish it because I think it will be useful to my students. I suspect I&#8217;ll be teaching this class in the future, so I will find it useful in the future as well. If I don&#8217;t attempt publishing it through a major publisher, I&#8217;ll put it on my wiki at the very least. Though it&#8217;s going to be quite a bit more effort than my typical wiki articles.</p> <p>But the question I keep coming back to, is this: Is there really a need for this book dead tree version, or it is primarily useful as supplemental material for a class I teach?</p> <p>I&#8217;d like to hear your opinions.</p> Tue, 17 Aug 2010 00:17:00 -0500 urn:uuid:66306ecb-5578-4490-9b17-69cd5da4547f Brett Schuchert http://blog.objectmentor.com/articles/2010/08/17/is-it-worth-killing-trees-over-another-c-43-43-book Schuchert's Scattered Synapses c 43 ood automated test Game Of Life with @lunivore <p>At the <a href="http://coderetreat.com/how-it-works.html">#coderetreat</a> in Orlando I spent an hour programming with <a href="http://twitter.com/lunivore">@lunivore</a> (Liz Keogh). We worked in Clojure on Conway&#8217;s game of life. It was quite an experience!</p> <p>Liz was not very familiar with Clojure, so I felt I had the advantage. Wrong! By the end of the hour she had taken charge and was programming rings around me. It was a lot of fun; if a bit humbling.</p> <p>Liz came into the session knowing the structure of the algorithm she wanted to implement. She just didn&#8217;t know how to implement it in Clojure. When the starting gun was fired, she showed me a picture of a glider (a standard form in life) and said she wanted this to be the acceptance test.</p> <p>During the session we wrote only a very few unit tests, each very focussed on one particular part of the problem. The size of the steps was considerably larger than I am used to in Java or Ruby; yet it didn&#8217;t seem to matter. Writing functions in clojure is easy, and apparently far less error prone.</p> <p>We finished 10 minutes before the end of the session, and had some time to refactor.</p> <p>I&#8217;ve posted the code below. I&#8217;ve cleaned it up a bit (being unable to leave it alone); but the algorithm remains the same; as are the tests.</p> <script src="http://gist.github.com/526188.js"> </script> Sun, 15 Aug 2010 20:40:21 -0500 urn:uuid:7f23560e-7e6a-44c0-861c-f3bb7e794934 Uncle Bob http://blog.objectmentor.com/articles/2010/08/15/game-of-life-with-lunivore Nearly 22 years ago <p>Moved the article and the file. Reduced resolution from 300 dpi to 75 dpi (using a quartz filter on <span class="caps">OS X</span> from <a href="http://discussions.apple.com/profile.jspa?userID=57524">Jerome Colas</a></p> <p>Here&#8217;s the story with the updated location: <a href="http://schuchert.wikispaces.com/IntorductionToMicrocomputersAndDataProcessing">The Moved Blog</a></p> Wed, 11 Aug 2010 22:23:00 -0500 urn:uuid:6ce78f16-6696-4c53-a7d9-6151d4b81bd9 Brett Schuchert http://blog.objectmentor.com/articles/2010/08/11/nearly-22-years-ago Schuchert's Scattered Synapses old computer book FIRST the 80 s Getting Started With cslim in Visual Studio 2010 Using the Command Line Tools <p>Some of you asked for it. Here&#8217;s something to get you started: <blockquote><a href="http://schuchert.wikispaces.com/cpptraining.UsingCSlimWithVisualStudio2010">http://schuchert.wikispaces.com/cpptraining.UsingCSlimWithVisualStudio2010</a></blockquote></p> <p>These instructions are a work in progress and alpha. However, they do get the basics working.</p> <p>If you are so inclined, have a look at the NMakefile (you&#8217;ll come across it in the instructions) and give me a better way to build it.</p> <p>I spent probably 8 hours getting a working environment (much yak shaving including a faulty mac book pro <span class="caps">DVD</span> drive). I then spent another 8 &#8211; 10 hours getting this working. I worked through it about 5 times to minimize the amount of changes I needed to make to the original library source.</p> <p>I ended up using some link and pre-processor seams to get most of this built. However, most of my time was spent trying to figure out the command line tools and their options.</p> <p>If you can give me some guidance on improving this, I&#8217;d like to hear it. However, this is now a low-burning thread, so some assembly required!</p> <p>Enjoy,</p> Sun, 08 Aug 2010 22:08:00 -0500 urn:uuid:b9ed3dc1-bb3c-4c54-beb5-9f6785ea21c6 Brett Schuchert http://blog.objectmentor.com/articles/2010/08/08/getting-started-with-cslim-in-visual-studio-2010-using-the-command-line-tools Schuchert's Scattered Synapses c cpp cslim visual studio 2010 Rough Notes on using FitNesse with C++ <p>I&#8217;ve been working with FitNesse.slim, using the cslim implementation to execute C++ code. I have some rough notes online. These should be enough to get started, though you&#8217;ll need to be using G++ 4.4 or later.</p> <p>In any case, have a look. Give me some feedback if you&#8217;d like. I&#8217;ll be working on these over the next month or so: <a href="http://schuchert.wikispaces.com/cpptraining.ExecutingBinaryOperators">http://schuchert.wikispaces.com/cpptraining.ExecutingBinaryOperators</a></p> Fri, 30 Jul 2010 22:09:00 -0500 urn:uuid:155f5034-8a3b-48d9-aa7c-d68584e51670 Brett Schuchert http://blog.objectmentor.com/articles/2010/07/30/rough-notes-on-using-fitnesse-with-c Schuchert's Scattered Synapses c FitNesse cslim Preprocessor seams and assignment of responsibility In my <a href="http://tinyurl.com/2fljzng">previous blog</a> I mentioned adding a single method to the cslim library: <blockquote> <b>cslim/include/CSlim/SlimListSerializer.h:</b> <div class="typocode"><pre><code class="typocode_default ">void SlimList_Release(char *serializedResults);</code></pre></div> <b>cslim/src/CSlim/SlimListSerializer.c:</b> <div class="typocode"><pre><code class="typocode_default ">void SlimList_Release(char *serializedResults) { if(serializedResults) free(serializedResults); }</code></pre></div> </blockquote> Now I&#8217;m going to explain how I came across this need, what it took to figure it out and then why I picked this solution. <h2>Background</h2> In FitNesse, Query Table Results are a list of list of list: <ul> <li>The outer-most list represents &#8220;rows&#8221;. It collects all objects found. It has zero or more entries.</li> <li>The inner-most list represents a single field. It is a key value pair. It is a list of size 2. The first entry is the name of the field (column to FitNesse). The second field is the value. Both are strings.</li> <li>The middle list represents a single object. It is a collection of fields. It has zero or more entires.</li> </ul> <p>I understand the need for this representation and it takes a little bit to get it built correctly. So much so, I built a <a href="http://github.com/schuchert/queryresultbuilder">simple tool to do it in java</a>.</p> <p>C&#43;&#43; is no different. In fact, the authors of cslim though the same thing and they created a C Abstract Data Type to help out (and an add-on method to create the correct final form):</p> <ul> <li>SlimList</li> <li>SlimList_Serializer</li> </ul> <p>They use C because it can be used by both C and C&#43;&#43;. I&#8217;m using C&#43;&#43; and I wanted to make building query results even easier, so I built a QueryResultAccumulator. The most recent source is in the <a href="http://tinyurl.com/2fljzng">previous blog</a> and I&#8217;ll be putting it on github after I&#8217;ve had some more time to work on it.</p> <p>Here&#8217;s the progression to my QueryResultAccumulator class:</p> <ul> <li>Wrote a Query-Table based fixture and followed the example provided with cslim (thank you for that!)</li> <li>Moved the code from functions into methods on a class</li> <li>Extracted a class, called SlimListWrapper, which made the fixture code easier to follow.</li> <li>Went to get takeout and realized that I had named the class incorrectly and that it was really accumulating query results (thus the name). The SlimList was a mechanism, not an intent.</li> <li>Refactored the class into QueryResultAccumulator (I left the original alone, created a new class, copied code from one to the other and changed it around a bit.</li> </ul> <p>Now it might sound like I didn&#8217;t have any tests. In fact, I did. I had my original Acceptance Test in FitNesse. I kept running that, so in a sense I was practicing <span class="caps">ATDD</span>.</p> <p>I was not happy with that, because I was not sure that I had properly handled memory allocation correctly. In fact, I had not. The final result is dynamically allocated and I was not releasing that. So I &#8220;fixed&#8221; it. (It needs to be released <b>after</b> the return from slim back to FitNesse, so the typical pattern is to lazily delete it, or release it in a &#8220;destroy&#8221; method called after the execution of a single table.)</p> <h2>I have a memory leak?!</h2> I am simplifying this story a bit. So I&#8217;m skipping some intermediate results. Ultimately I wrote the following test to check that you could use a single query result accumulator for multiple results correctly: <div class="typocode"><pre><code class="typocode_default ">TEST(QueryResultAccumulator, CanProduceFinalResultsMultipleTimes) { QueryResultAccumulator accumulator; accumulator.produceFinalResults(); accumulator.produceFinalResults(); }</code></pre></div> <p>This caused a memory leak of 60 bytes. It was at this point I was up too late and banging my head against a wall. About 3 hours later I figured that out and went to bed. I fixed the problem and sent a patch to authors of cslim in maybe 45 minutes. So I should have gotten more sleep.</p> <h2>Where is that damn thing</h2> In any case, I visually checked the code. I debugged it. I did everything I could initially think of, and I was convinced that my code was correct. (As we&#8217;ll see it both was and was not due to a preprocessor seam in cslim.) I got to the point where I even tried different versions of gcc. (I found a parsing error in g&#43;&#43; 4.5 when handling templates, so in desperation and late at night I wasted 5 minutes switching my compiler.) I had the following code in my class: <div class="typocode"><pre><code class="typocode_default "> if(result) free(result);</code></pre></div> <p>This was the correct thing, but it was in the wrong location. Again, this was related to a preprocessor seam in cslim.</p> <h2> Eureka!</h2> I looked at the cslim code and confirmed it was doing basic C stuff, nothing surprising. It was at that point that I remembered something important: <blockquote> cslim depends on CppUTest and uses a different malloc/free </blockquote> <p>Ah ha! That&#8217;s it. So I tired to recompile my C&#43;&#43; code to use the same thing. However, I was not able to do that. CppUTest&#8217;s memory tracking implementation does not work with many of the C&#43;&#43; standard classes like &lt;string&gt; and &lt;vector&gt;. So I could not compile my code using the same approach.</p> <p>I&#8217;m glad this happened becuase it made me realize that it was the wrong place anyway. Here&#8217;s the logic:</p> <ul> <li>CSlim has a preprocessor seam, comile with or without -Dfree=cpputest_free, -Dmalloc=cpputest_malloc</li> <li>I&#8217;m using a class in cslim to do the allocation, where the policy of allocation is stored</li> <li>I should <b>not</b> release the memory but instead allow the cslim library to release the memory becaue it has the allocation policy, and therefore the release policy.</li> </ul> About 2 minutes later, I had added a single function to the library: <blockquote> <b>cslim/include/CSlim/SlimListSerializer.h:</b> <div class="typocode"><pre><code class="typocode_default ">void SlimList_Release(char *serializedResults);</code></pre></div> <b>cslim/src/CSlim/SlimListSerializer.c:</b> <div class="typocode"><pre><code class="typocode_default ">void SlimList_Release(char *serializedResults) { if(serializedResults) free(serializedResults); }</code></pre></div> </blockquote> <p>I updated my QueryResultAccumulator to use SlimList_Release and my false positive disappeared.</p> <p>It also turns out that this improved symmetry in the library. To allocate and release entries in an SlimList you use the following functions:</p> <ul> <li>SlimList* SlimList_Create() </li> <li>void SlimList_Destroy(SlimList*);</li> </ul> <p>Now to serlalize a list and release the memory later you use:</p> <ul> <li>SlimList_Serialize</li> <li>SlimList_Release</li> </ul> <p>As I write this, I think there&#8217;s a better name. I&#8217;ll let the authors give it a better name (like SlimList_Release_Serialization_Results). But in any case, if you use a function in the cslim library that allocates something, you use another method in the cslim library to release it.</p> <p>Since the libray has a preprocessor seam, that symmetry removes a false-positive memory leak.</p> <h2>What took so long?</h2> I had an interesting time with this. Originally I had not released that memory in the class but rather in the unit test. I was working too late and not thinking clearly. I realized that my class needed to manage that. <p>When I called free in the unit test, it was calling the correct version of free, cpputest_free, becasue it was a unit test using CppUTest. When I moved the code into the class, which has no knowledge of CppUTest (nor can it), the flow of the code was correct, but the compilation (preprocessor symbols) were different and it caused a false positive.</p> <p>Since I changed the code, I assumed it was a problem with how I changed the code. To me more clear, I though it was a code-flow problem, not a preprocessor seam problem. So I spent a lot of time verifyig my code. Once I determined it was correct, I then moved into debugger mode.</p> <p>It was not long after that when I finally figured out what was going on.</p> <h2>Conslusions</h2> As with many things in life, this is intuitive once you understand it!-) <p>That cslim depends on CppUTest might be questionable. However, if I treat cslim as a (mostly) black box, and I don&#8217;t know its allocation policy, I should not assume a deallocation policy.</p> <p>By putting the responsiblity in the correct library level, it fixed the problem and added symmetry to the overall solution.</p> <p>I also really enjoyed this (after it was done). I&#8217;ve come across memory leaks using CppUTest in the past. Often they were my fault. Sometimes they were not. This was interesting because it both was and was not my fault. I originally had written the code incorrectly. When I put he correct steps in my code, I still had wrong code because I put the responsibility in the wrong place. It really was only correct after I moved the actual implementation into the library and then called it from my code that I had finally written it correctly.</p> Thu, 22 Jul 2010 10:32:00 -0500 urn:uuid:dfbd2b43-7d99-443b-8325-bfa1b93ed842 Brett Schuchert http://blog.objectmentor.com/articles/2010/07/22/preprocessor-seams-and-assignment-of-responsibility Schuchert's Scattered Synapses c FitNesse cslim assignment of responsibility malloc free preprocessor seam Some C++ Fixtures for FitNesse.slim <p>I continue working on these. I was stuck in the airport for 5 hours. Between that and the actual flight, I managed to create three different test examples against a C++ RpnCalculator. Each example uses a different kind of fixture. I had a request from @lrojas to publish some results on the blog. So this is that, however these are in progress and rough.</p> <p>I&#8217;m still trying different forms to figure out what I like the best.</p> <p>By the way, that lastValue stuff in the fixtures has to do with the fact that all of the hook methods return a char* but I&#8217;m responsible for cleaning up after myself.</p> <h2>A Decision Table</h2> <div class="typocode"><pre><code class="typocode_default ">!|ExecuteBinaryOperator | |lhs|rhs|operator|expected?| |3 |4 |- |-1 | |5 |6 |* |30 |</code></pre></div> <h2>And Its Fixture Code</h2> <div class="typocode"><pre><code class="typocode_default ">#include &lt;stdlib.h&gt; #include &lt;stdio.h&gt; #include &lt;string&gt; #include &quot;RpnCalculator.h&quot; #include &quot;OperationFactory.h&quot; #include &quot;Fixtures.h&quot; #include &quot;SlimUtils.h&quot; struct ExecuteBinaryOperator { ExecuteBinaryOperator() { lastValue[0] = 0; } int execute() { RpnCalculator calculator(factory); calculator.enterNumber(lhs); calculator.enterNumber(rhs); calculator.executeOperator(op); return calculator.getX(); } static ExecuteBinaryOperator* From(void *fixtureStorage) { return reinterpret_cast&lt;ExecuteBinaryOperator*&gt;(fixtureStorage); } OperationFactory factory; int lhs; int rhs; std::string op; char lastValue[32]; }; extern &quot;C&quot; { void* ExecuteBinaryOperator_Create(StatementExecutor* errorHandler, SlimList* args) { return new ExecuteBinaryOperator; } void ExecuteBinaryOperator_Destroy(void* self) { delete ExecuteBinaryOperator::From(self); } static char* setLhs(void* fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); self-&gt;lhs = getFirstInt(args); return self-&gt;lastValue; } static char* setRhs(void* fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); self-&gt;rhs = getFirstInt(args); return self-&gt;lastValue; } static char* setOperator(void *fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); self-&gt;op = getFirstString(args); return self-&gt;lastValue; } static char* expected(void* fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); int result = self-&gt;execute(); snprintf(self-&gt;lastValue, sizeof(self-&gt;lastValue), &quot;%d&quot;, result); return self-&gt;lastValue; } SLIM_CREATE_FIXTURE(ExecuteBinaryOperator) SLIM_FUNCTION(setLhs) SLIM_FUNCTION(setRhs) SLIM_FUNCTION(setOperator) SLIM_FUNCTION(expected) SLIM_END }</code></pre></div> There&#8217;s a bit of duplication. I&#8217;ve been experimenting with pointers to member functions and template functions to make it better. I really should be using lambdas, but I&#8217;m not there yet. I have them available in some form since I&#8217;m using gcc 4.5. I simply compile with the option -sdd=c++0x. Even so, I&#8217;m not quite ready to do that. <h2>A Script Table</h2> <div class="typocode"><pre><code class="typocode_default ">!|script |ProgramTheCalculator | |startProgramCalled|primeFactorsOfSum | |addOperation |sum | |addOperation |primeFactors | |saveProgram | |enter |4 | |enter |13 | |enter |7 | |execute |primeFactorsOfSum | |check |stackHas|3|then|2|then|2|then|2|is|true|</code></pre></div> <h2>And Its Fixture Code</h2> <div class="typocode"><pre><code class="typocode_default ">#include &lt;stdlib.h&gt; #include &lt;stdio.h&gt; #include &lt;string&gt; #include &quot;RpnCalculator.h&quot; #include &quot;OperationFactory.h&quot; #include &quot;SlimUtils.h&quot; #include &quot;SlimList.h&quot; #include &quot;Fixtures.h&quot; struct ProgramTheCalculator { ProgramTheCalculator() : calculator(factory) { } static ProgramTheCalculator* From(void *fixtureStorage) { return reinterpret_cast&lt;ProgramTheCalculator*&gt;(fixtureStorage); } OperationFactory factory; RpnCalculator calculator; }; extern &quot;C&quot; { void* ProgramTheCalculator_Create(StatementExecutor* errorHandler, SlimList* args) { return new ProgramTheCalculator; } void ProgramTheCalculator_Destroy(void *fixture) { delete ProgramTheCalculator::From(fixture); } static char* startProgramCalled(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self-&gt;calculator.createProgramNamed(getFirstString(args)); return remove_const(&quot;&quot;); } static char* addOperation(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self-&gt;calculator.addOperation(getFirstString(args)); return remove_const(&quot;&quot;); } static char* saveProgram(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self-&gt;calculator.saveProgram(); return remove_const(&quot;&quot;); } static char* enter(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self-&gt;calculator.enterNumber(getFirstInt(args)); return remove_const(&quot;&quot;); } static char* execute(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self-&gt;calculator.executeOperator(getFirstString(args)); return remove_const(&quot;&quot;); } static char* stackHasThenThenThenIs(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); for(int i = 0; i &lt; 4; ++i) { if(self-&gt;calculator.getX() != getIntAt(args, i)) return remove_const(&quot;false&quot;); self-&gt;calculator.executeOperator(&quot;drop&quot;); } return remove_const(&quot;true&quot;); } SLIM_CREATE_FIXTURE(ProgramTheCalculator) SLIM_FUNCTION(startProgramCalled) SLIM_FUNCTION(addOperation) SLIM_FUNCTION(saveProgram) SLIM_FUNCTION(enter) SLIM_FUNCTION(execute) SLIM_FUNCTION(stackHasThenThenThenIs) SLIM_END }</code></pre></div> This one is a bit more regular. I am using the updated auto keyword in this code. The fixture is just holding the calculator and its OperationFactory (not my preferred name, but that&#8217;s what students wanted to call things like +, -, etc, operations not operators). <h2>The Dreaded Query Table</h2> It&#8217;s a bit of a pain to produce query results. So much so, I wrote a simple library in Java to make it easier. I can create a well-formed query result from a single object or a list of objects and even do basic transforms (in names and in paths to data). I started using the jakarta bean utils, but my use was so simple (2 methods), I ripped out that library and just hand-wrote the methods I needed. It was not a case of &#8220;not invented here syndrom.&#8221; I started by using the library, and I had tests. I didn&#8217;t like the size of the library relative to how much I was using it, so I just got rid of it. <p>Well here I am working C++ and I felt compelled to make it easier work with query results in C++.</p> First the FitNesse table, then the fixture and finally the support class. I have tests for it as well, I&#8217;m not going to show those, however. <div class="typocode"><pre><code class="typocode_default ">!|Query: SingleCharacterNameOperators| |op | |+ | |* | |/ | |! | |- |</code></pre></div> <h2>And Its Fixture Code</h2> <div class="typocode"><pre><code class="typocode_default ">#include &lt;stdlib.h&gt; #include &lt;stdio.h&gt; #include &lt;vector&gt; #include &lt;string&gt; #include &lt;memory&gt; #include &quot;RpnCalculator.h&quot; #include &quot;OperationFactory.h&quot; #include &quot;Fixtures.h&quot; #include &quot;SlimUtils.h&quot; #include &quot;QueryResultAccumulator.h&quot; struct SingleCharacterNameOperators { OperationFactory factory; RpnCalculator calculator; SingleCharacterNameOperators() : calculator(factory), result(0) { } ~SingleCharacterNameOperators() { delete result; } static SingleCharacterNameOperators* From(void *fixtureStorage) { return reinterpret_cast&lt;SingleCharacterNameOperators*&gt; (fixtureStorage); } void resetResult(char *newResult) { delete result; result = newResult; } void conditionallyAddOperatorNamed(const std::string &amp;name) { if (name.size() == 1) { accumulator.addFieldNamedWithValue(&quot;op&quot;, name); accumulator.finishCurrentObject(); } } void buildResult() { v_string names = calculator.allOperatorNames(); buildResult(names); } void buildResult(v_string &amp;names) { for (v_string::iterator iter = names.begin(); iter != names.end(); ++iter) conditionallyAddOperatorNamed(*iter); resetResult(accumulator.produceFinalResults()); } QueryResultAccumulator accumulator; char *result; }; extern &quot;C&quot; { void* SingleCharacterNameOperators_Create(StatementExecutor* errorHandler, SlimList* args) { return new SingleCharacterNameOperators; } void SingleCharacterNameOperators_Destroy(void *fixture) { delete SingleCharacterNameOperators::From(fixture); } static char* query(void *fixture, SlimList *args) { auto *self = SingleCharacterNameOperators::From(fixture); self-&gt;buildResult(); return self-&gt;result; } SLIM_CREATE_FIXTURE(SingleCharacterNameOperators) SLIM_FUNCTION(query)SLIM_END SLIM_END</code></pre></div> <h2>And the Helper Class</h2> <b>QueryResultAccumulator.h</b> <div class="typocode"><pre><code class="typocode_default ">#pragma once #ifndef QUERYRESULTACCUMULATOR_H_ #define QUERYRESULTACCUMULATOR_H_ class SlimList; #include &lt;vector&gt; #include &lt;string&gt; class QueryResultAccumulator { public: typedef std::vector&lt;SlimList*&gt; v_SlimList; typedef v_SlimList::iterator iterator; QueryResultAccumulator(); virtual ~QueryResultAccumulator(); void finishCurrentObject(); void addFieldNamedWithValue(const std::string &amp;name, const std::string &amp;value); char *produceFinalResults(); private: SlimList* allocate(); void releaseAll(); void setInitialConditions(); private: v_SlimList created; SlimList *list; SlimList *currentObject; int lastFieldCount; int currentFieldCount; char *result; private: QueryResultAccumulator(const QueryResultAccumulator&amp;); QueryResultAccumulator&amp; operator=(const QueryResultAccumulator&amp;); }; #endif </code></pre></div> <p>I know there are too many fields. The counts help with validating correct usage. I also wrote it so one instance could be re-used and I tried to make sure it was in a &#8220;ready to receive fields&#8221; state when necessary. In any case, this error checking helped find a defect I introduced while refactoring.</p> <b>QueryResultAccumulator.cpp</b> <div class="typocode"><pre><code class="typocode_default ">#include &quot;QueryResultAccumulator.h&quot; #include &quot;DifferentFieldCountsInObjects.h&quot; #include &quot;InvalidStateException.h&quot; extern &quot;C&quot; { #include &quot;SlimList.h&quot; #include &quot;SlimListSerializer.h&quot; } QueryResultAccumulator::QueryResultAccumulator() : result(0) { setInitialConditions(); } QueryResultAccumulator::~QueryResultAccumulator() { releaseAll(); SlimList_Release(result); } void QueryResultAccumulator::setInitialConditions() { releaseAll(); list = allocate(); currentObject = allocate(); lastFieldCount = -1; currentFieldCount = -1; } SlimList* QueryResultAccumulator::allocate() { SlimList *list = SlimList_Create(); created.push_back(list); return list; } void QueryResultAccumulator::releaseAll() { for (iterator i = created.begin(); i != created.end(); ++i) SlimList_Destroy(*i); created.clear(); } void QueryResultAccumulator::finishCurrentObject() { if(lastFieldCount &gt;= 0 &amp;&amp; lastFieldCount != currentFieldCount) throw DifferentFieldCountsInObjects(lastFieldCount, currentFieldCount); SlimList_AddList(list, currentObject); currentObject = allocate(); lastFieldCount = currentFieldCount; currentFieldCount = -1; } void QueryResultAccumulator::addFieldNamedWithValue(const std::string &amp;name, const std::string &amp;value) { SlimList *fieldList = allocate(); SlimList_AddString(fieldList, name.c_str()); SlimList_AddString(fieldList, value.c_str()); SlimList_AddList(currentObject, fieldList); ++currentFieldCount; } char* QueryResultAccumulator::produceFinalResults() { if(currentFieldCount != -1) throw InvalidStateException(&quot;Current object not written&quot;); SlimList_Release(result); result = SlimList_Serialize(list); setInitialConditions(); return result; }</code></pre></div> Note, this code uses a method I added to the cslim library: <b>SlimListSerializer.h &#8211; in include/CSlim</b> <div class="typocode"><pre><code class="typocode_default ">void SlimList_Release(char *serializedResults);</code></pre></div> <b>SlimListSerializer.c &#8211; in src/CSlim</b> <div class="typocode"><pre><code class="typocode_default ">void SlimList_Release(char *serializedResults) { if(serializedResults) free(serializedResults); }</code></pre></div> <p>I needed to add these methods due to a false-positive memory leak indicated when using CppUTest to test this code. That&#8217;s another blog.</p> Thu, 22 Jul 2010 00:32:00 -0500 urn:uuid:63a89994-cb84-4422-b3c8-5ac5e7f53331 Brett Schuchert http://blog.objectmentor.com/articles/2010/07/22/some-c-fixtures-for-fitnesse-slim Schuchert's Scattered Synapses c FitNesse cslim FitNesse, C++ and cslim, step-by-step instructions <p>Title says it all: <a href="http://schuchert.wikispaces.com/cpptraining.GettingStartedWithFitNesseInCpp">http://schuchert.wikispaces.com/cpptraining.GettingStartedWithFitNesseInCpp</a></p> <p>First draft. If you have problems, please let me know.</p> Mon, 19 Jul 2010 23:26:00 -0500 urn:uuid:d1463d08-3298-4a46-bb72-4208f313a52a Brett Schuchert http://blog.objectmentor.com/articles/2010/07/19/fitnesse-c-and-cslim-step-by-step-instructions Schuchert's Scattered Synapses c FitNesse cslim A Few C plus plus TDD videos <p>Using CppUTest, gcc 4.4 and the Eclipse <span class="caps">CDT</span>.</p> <p>Rough, as usual.</p> <p><a href="http://www.vimeo.com/album/254486">The Video Album</a></p> <p>Might redo first one with increased font size. Considering redoing whole series at 800&#215;600.</p> Mon, 12 Jul 2010 06:30:00 -0500 urn:uuid:a05f9c5f-4b90-46ab-9eaf-72750d3ae303 Brett Schuchert http://blog.objectmentor.com/articles/2010/07/12/a-few-c-plus-plus-tdd-videos Schuchert's Scattered Synapses TDD c plus std tr1 accumulate for_each bind _1 refactoring array vector random Software Calculus - The Missing Abstraction. <p>The problem of infinity plagued mathematicians for millennia. Consider Xeno&#8217;s paradox; the one with Achilles and the tortoise. While it was intuitively clear that Achilles would pass the Tortoise quickly, the algebra and logic of the day seemed to suggest that the Tortoise would win every race given a head start. <em>Every time</em> Achilles got to where the tortoise was, the tortoise would have moved on. The ancients had no way to see that an infinite sum could be finite.</p> <p>Then came Leibnitz and everything changed. Suddenly infinity was tractable. Suddenly you could sum infinite series and write the equations that showed Achilles passing the tortoise. Suddenly a whole range of calculations that had either been impossible or intractable became trivial.</p> <p>Calculus was a watershed invention for mathematics. It opened up vistas that we have yet to fully plumb. It made possible things like Newtonian mechanics, Maxwell&#8217;s equations, special and general relativity and quantum mechanics. It supports the entire framework of our modern world. We need a watershed like that for software.</p> <p>If you listen to my keynote: <a href="http://en.oreilly.com/rails2010/public/schedule/detail/14134">Twenty-Five Zeros</a> you&#8217;ll hear me go on and on about how even though software has changed a lot in form over the last fifty years, it has changed little in substance. Software is still the organization of sequence, selection, and iteration.</p> <p>For fifty years we have been inventing new languages, notations, and formulations to manage Sequence, Selection, and Iteration (SSI). Structured Programming is simply a way to organize <span class="caps">SSI</span>. Objects are another way to organize <span class="caps">SSI</span>. Functional is still another. Indeed, almost all of our software technologies are just different ways of organizing Sequence, Selection, and Iteration.</p> <p>This is similar to Algebra in the days before calculus. We knew how to solve linear and polynomial equations. We knew how to complete squares and find roots. But in the end it was all just different ways to organize adding. That may sound simplistic, but it&#8217;s not. Subtracting is just adding in reverse. Multiplying is just adding repeatedly. Division is just multiplication in reverse. In short, Algebra is an organizational strategy for adding.</p> <p>Algebra went through many different languages and notations too, just like software has. Think about Roman and Greek numerals. Think how long it took to invent the concept of zero, or the positional exponential notation we use today.</p> <p>And then one day Newton saw an apple fall, and he changed the way we <em>thought</em> about mathematics. Suddenly it wasn&#8217;t about adding anymore. Suddenly it was about infinities and differentials. Mathematical reasoning was raised to a new order of abstraction.</p> <p>Where is that apple for software (pun intended). Where is the Newton or Leibnitz that will transform everything about the way we <em>think</em> about software. Where is that long-sought new level of abstraction?</p> <p>For awhile we thought it would be <span class="caps">MDA</span>. Bzzzzt, wrong. We thought it would be logic programming like prolog<sup><a href="#fn1">1</a></sup>. Bzzzt. We thought it would be database scripts and 4GLs. Bzzzt. None of those did it. None of those can do it. They are still just various ways of organizing sequence, selection, and iteration.</p> <p>Some people have set their sights on quantum computing. While I&#8217;ll grant you that computations with bits that can be both states simultaneously is <em>interesting</em>, in the end I think this is just another hardware trick to increase throughput as opposed to a whole new way to think about software.</p> <p>This software transformation, whatever it is, is coming. It must come; because we simply cannot keep piling complexity upon complexity. We need some new organizing principle that revamps the very foundations of the way we think about software and opens up vistas that will take us into the 22nd century.</p> <p id="fn1"><sup>1</sup> Prolog comes closest to being something more than a simple reorganization of sequence, selection, and iteration. At first look logic programming seems very different. In the end, however, an algorithm expressed in prolog can be translated into any of the other languages, demonstrating the eventual equivalence.</p> Mon, 05 Jul 2010 20:26:15 -0500 urn:uuid:4780351e-b2f2-4152-b4ef-0691cab0ff92 Uncle Bob http://blog.objectmentor.com/articles/2010/07/05/software-calculus-the-missing-abstraction Uncle Bob's Blatherings C++ Algorithms, Boost and function currying <p>I&#8217;ve been experimenting with C++ using the Eclipse <span class="caps">CDT</span> and gcc 4.4. Since I&#8217;m a fan of boost, I&#8217;ve been using that as well. I finally got into I realistic use of boost::bind.</p> I converted this: <div class="typocode"><pre><code class="typocode_default ">int Dice::total() const { int total = 0; for(const_iterator current = dice.begin(); current != dice.end(); ++current) total += (*current)-&gt;faceValue(); return total; }</code></pre></div> Into this: <div class="typocode"><pre><code class="typocode_default ">int Dice::total() const { return std::accumulate( dice.begin(), dice.end(), 0, bind(std::plus&lt;int&gt;(), _1, bind(&amp;Die::faceValue, _2)) ); }</code></pre></div> <p>To see how to go from the first version to the final version with lots of steps in between: <a href="http://schuchert.wikispaces.com/cpptraining.SummingAVector">http://schuchert.wikispaces.com/cpptraining.SummingAVector</a>.</p> <p>This is a first draft. I&#8217;ll be cleaning it up over the next few days. If you see typos, or if anything is not clear from the code, please let me know where. Also, if my interpretation of what boost is doing under the covers (there&#8217;s not much of that) is wrong, please correct me.</p> <p>Thanks!</p> Sat, 12 Jun 2010 23:41:00 -0500 urn:uuid:549aae6e-42fc-4ae7-ad78-126667918e8d Brett Schuchert http://blog.objectmentor.com/articles/2010/06/12/c-algorithms-boost-and-function-currying Schuchert's Scattered Synapses c cpp boost function currying std for_each vector shared_ptr accumulate TDD in Clojure <p>OO is a tell-don&#8217;t-ask paradigm. Yes, I know people don&#8217;t always use it that way, but one of Kay&#8217;s original concepts was that objects were like cells in a living creature. The cells in a living creature do not ask any questions. They simply tell each other what to do. Neurons are tellers, not askers. Hormones are tellers not askers. In biological systems, (and in Kay&#8217;s original concept for OO) communication was half-duplex.</p> <p>Clojure is a functional language. Functional languages are ask-dont-tell. Indeed, the whole notion of &#8220;tell&#8221; is to change the state of the system. In a functional program there is no state to change. So &#8220;telling&#8221; makes little sense.</p> <p>When we use <span class="caps">TDD</span> to develop a tell-don&#8217;t-ask system, we start at the high level and write tests using mocks to make sure we are issuing the correct &#8220;tells&#8221;. We proceed from the top of the system to the bottom of the system. The last tests we write are for the utilities at the very bottom.</p> <p>In an ask-don&#8217;t-tell system, data starts at the bottom and flows upwards. The operation of each function depends on the data fed to it by the lower level functions. There is no mocking framework. So we write tests that start at the bottom, and we work our way up the the top.</p> <p>Therein lies the rub.</p> <p>In a tell-don&#8217;t-ask system, the tells at the high level are relatively complex. They branch out into lower subsystems getting simpler, but more numerous as they descend. Testing these tells using mocks is not particularly difficult because we don&#8217;t need to depend on the lower level functions being there. The mocks make them irrelevant.</p> <p>In an ask-don&#8217;t-tell system the asks at the low level are simple, but as the data moves upwards it gets grouped and composed into lists, maps, sets, and other complex data structures. At the top the data is in it&#8217;s most complex form. Writing tests against that complex data is difficult at best. And there is currently no way to mock out the lower levels<sup><a href="#fn1">1</a></sup> so all tests written at the high level depend on all the functions below.</p> <p>The perception of writing tests from the bottom to the top can be horrific at first. Consider, for example, the <a href="http://github.com/unclebob/clojureOrbit">Orbit program</a> I just wrote. This program simulates N-body gravitation. Imagine that I am writing tests at the top level. I have three bodies at position Pa, Pb, and Pc. They have masses Ma, Mb, and Mc. They have velocity vectors of Va, Vb, Vc. The test I want to write needs to make sure that new positions Pa&#8217;, Pb&#8217;, Pc&#8217;, and new Velocity vectors Va&#8217;, Vb&#8217;, and Vc&#8217; are computed correctly. How do I do that?</p> Should I write a test that looks like this? <pre> test-update { Pa = (1,1) Ma = 2 Va = (0,0) Pb = (1,2) Mb = 3 Vb = (0,0) Pc = (4,5) Mc = 4 Vc = (0,0) update-all Pa should == (1.096, 4.128) Va should == (0.096, 3.128) Pb should == (1.1571348402636772, 0.1571348402636774) Vb should == (0.15713484026367727, -1.8428651597363226) Pc should == (3.834148869802242, 4.818148869802242) Vc should == (-0.16585113019775796, -0.18185113019775795) } </pre> A test like this is awful. It&#8217;s loaded with magic numbers, and secret information. It tells me nothing about <em>how</em> the update-all function is working. It only tells me that it generated certain numbers. Are those numbers correct? How would I know? <p>But wait! I&#8217;m working in a <em>functional language</em>. That means that every function I call with certain inputs will <em>always</em> return the same value; no matter how many times I call it. Functions don&#8217;t change state! And that means that I can write my tests quite differently.</p> <p>How does update-all work? Simple, given a list of objects it performs the following operations (written statefully):</p> <pre> update-all(objects) { for each object in objects { accumulate-forces(object, objects) } for each object in objects { accelerate(object) reposition(object) } } </pre> <p>This is written in stateful form to make is easier for our non-functional friends to follow. First we accumulate the force of gravity between all the objects. This amounts to evaluating Newton&#8217;s F=Gm1m1/r^2 formula for each pair of objects, and adding up the force vectors.</p> <p>Then, for each object we accelerate that object by applying the force vector to it&#8217;s mass, and adding the resultant delta-v vector to it&#8217;s velocity vector.</p> <p>Then, for each object we reposition that object by applying the velocity vector to it&#8217;s current position.</p> <p>Here&#8217;s the clojure code for update-all</p> <pre> (defn update-all [os] (reposition-all (accelerate-all (calculate-forces-on-all os)))) </pre> <p>In this code you can clearly see the bottom-to-top flow of the application. First we calculate forces, then we accelerate, and finally we reposition.</p> <p>Now, what do these -all functions look like? Here they are:</p> <pre> (defn calculate-forces-on-all [os] (map #(accumulate-forces % os) os)) (defn accelerate-all [os] (map accelerate os)) (defn reposition-all [os] (map reposition os)) </pre> <p>If you don&#8217;t read clojure, don&#8217;t worry. the map function simply creates a new list from an old list by applying a function to each element of the old list. So in the case of reposition-all it simply calls reposition on the list of objects (os) producing a new list of objects that have been repositioned.</p> <p>From this we can determine that the function of update-all is to call the three functions (accumulate-forces, accelerate, and reposition) on each element of the input list, producing a new list.</p> <p>Notice how similar that is to a statement we might make about a high level method in an OO program. (It&#8217;s got to call these three functions on each element of the list). In an OO language we would mock out the three functions and just make sure they&#8217;d been called for each element. The calculations would be bypassed as irrelevant.</p> <p>Oddly, we can make the same statement in clojure. Here&#8217;s the test for update-all</p> <pre> (testing "update-all" (let [ o1 (make-object ...) o2 (make-object ...) o3 (make-object ...) os [o1 o2 o3] us (update-all os) ] (is (= (nth us 0) (reposition (accelerate (accumulate-forces os o1) (is (= (nth us 1) (reposition (accelerate (accumulate-forces os o2) (is (= (nth us 2) (reposition (accelerate (accumulate-forces os o3) ) ) </pre> <p>If you don&#8217;t read clojure don&#8217;t worry. All this is saying is that we test the update-all function by calling the appropriate functions for each input object, and then see if the elements in the output list match them.</p> <p>In an OO program we&#8217;d find this dangerous because of side-effects. We couldn&#8217;t be sure that the functions could safely be called without changing the state of some object in the system. But in a functional language it doesn&#8217;t matter how many times you call a function. So long as you pass in the same data, you will get the same result.</p> <p>So this test simply checks that the appropriate three functions are getting called on each element of the list. This is exactly the same thing an OO programmer would do with a mock object!</p> <h3>Is <span class="caps">TDD</span> necessary in Clojure?</h3> <p>If you follow the code in the Orbit example, you&#8217;ll note that I wrote tests for all the computations, but did not write tests for the Swing-Gui. This is typical of the way that I work. I try to test all business rules, but I &#8220;fiddle&#8221; with the <span class="caps">GUI</span> until I like it.</p> <p>If you look carefully you&#8217;ll find that amidst the <span class="caps">GUI</span> functions there are some &#8220;presentation&#8221; functions that <em>could</em> have been tested, but that I neglected to write with <span class="caps">TDD</span>[2]. These functions were the worst to get working. I continuously encountered NPEs and Illegal Cast exceptions while trying to get them to work.</p> <p>My conclusion is that Clojure without <span class="caps">TDD</span> is just as much a nightmare as Java or Ruby without <span class="caps">TDD</span>.</p> <h3>Summary</h3> <p>In OO we tend to <span class="caps">TDD</span> our way from the top to the bottom by using Mocks. In Clojure we tend to <span class="caps">TDD</span> our way from the bottom to the top. In either case we can compose our tests in terms of the functions they should call on the lower level objects. In the case of OO we use mocks to tell us if the functions have been called properly. This protects us from side-effects and allows us to decouple our tests from the whole system. In clojure we can rely on the fact that the language is functional, and that no matter how many times you call a function it will return the same value.</p> <p id="fn1"><sup>1</sup> Brian Marick is working on something that looks a lot like a mocking framework for clojure. If his ideas pan out, we may be able to <span class="caps">TDD</span> from the top to the bottom in Clojure.</p> <p id="fn2"><sup>2</sup> This is an unconscious game we all play with ourselves. When we have a segment of code that we consider to be immune to <span class="caps">TDD</span> (like <span class="caps">GUI</span>) then we unconsciously move lots of otherwise testable code into that segment. Yes, I heard my green band complain every time I did it; but I ignored it because I was in the <span class="caps">GUI</span>. Whoops.</p> Thu, 03 Jun 2010 12:33:00 -0500 urn:uuid:496c0f47-16d5-480d-9530-125b7ee235d8 Uncle Bob http://blog.objectmentor.com/articles/2010/06/03/tdd-in-clojure Uncle Bob's Blatherings Orbit in Clojure <p>I spent the last two days (in between the usual BS) writing a simple orbital simulator in Clojure using Java interop with Swing. This was a very pleasant experience, and I like the way the code turned out &#8211; even the swing code!</p> <p>You can see the source code <a href="http://github.com/unclebob/clojureOrbit">here</a></p> <p>Those of you who are experienced with Clojure, I&#8217;d like your opinion on my use of namespaces and modules and other issues of style.</p> <p>Those of you who are not experienced with Clojure, should start. You might want to use this application as a tutorial.</p> <p>And just have fun watching the simulation of the coalescence of an accretion disk around a newly formed star.</p> Wed, 02 Jun 2010 17:08:56 -0500 urn:uuid:6e0975f7-8396-4428-90d5-1500c373c64a Uncle Bob http://blog.objectmentor.com/articles/2010/06/02/orbit-in-clojure Uncle Bob's Blatherings A Coverage Metric That Matters <p>How much test coverage should your code have? 80%? 90%? If you&#8217;ve been writing tests from the beginning of your project, you probably have a percentage that hovers around 90%, but what about the typical project? The project which was started years ago, and contains hundreds of thousands of lines of code? Or millions of lines of code? What can we expect from it?</p> <p>One of the things that I know is that in these code bases, one could spend one&#8217;s entire working life writing tests without doing anything else. There&#8217;s simply that much untested code. It&#8217;s better to write tests for the new code that you write and write tests for existing code you have to change, at the time you have to change it. Over time, you get more coverage, but your coverage percentage isn&#8217;t a goal. The goal is to make your changes safely. In a large existing code base, you may never get more than 20% coverage over its lifetime.</p> <p>Changes occur in clusters in applications. There&#8217;s some code that you will simply never change and there&#8217;s other areas of code which change quite often. The other day it occurred to me that we could use that fact to arrive at a better metric, one that is a bit less disheartening and also gives us a sense of our true progress.</p> <p>The metric I&#8217;m thinking about is percentage of commits on files which are covered by tests relative to the number of commits on files without tests.</p> <p>In the beginning, you can expect to have a very low percentage, but as you start to get tests in place for changes that you make, your percentage will rise rapidly. If you write tests for all of your changes, it will continue to rise. At a certain point, you may want to track only a window of commits, say, the commits which have happened only in the last year. When you do this, you can end up very close to 100%.</p> <p>If you think this through, it might seem a bit dodgy on a couple of fronts. The first is that having tests for code within a file does not mean that that code is completely covered by those tests. But, I often find that the hardest part of getting started with unit testing is getting classes isolated enough from their dependencies to be testable in a harness at all. Another dodgy bit is the fact that once you get some tests in place for a file, all of the commits you&#8217;ve ever done for that file count in the percentage. Again, that&#8217;s okay for fundamentally the same reason. Once you start getting coverage, you are in a good position with that particular code.</p> <p>What about the moving window? If you track this metric over, say, the last N months of commits, you&#8217;ll progressively lose information about the code that you just aren&#8217;t changing. To me, that&#8217;s fine. Coverage matters for the code that we are changing.</p> <p>The metric I&#8217;m considering (maybe we can call it &#8216;change coverage&#8217;) gives us information about how tests are really impacting our day to day work. Moreover, it&#8217;s likely that it would be a good motivational tool, and really, that&#8217;s one of the things that a good metric should be.</p> Fri, 28 May 2010 05:39:00 -0500 urn:uuid:69f3cdd3-eff2-4646-9dd1-d0488a651525 Michael Feathers http://blog.objectmentor.com/articles/2010/05/28/a-coverage-metric-that-matters Michaels Musings Hello World Revisited <p>Surprising revelations while taking a <span class="caps">TDD</span> approach to writing hello world.</p> <p>Here it nearly 21 years since I started writing in C++ (and more for C+) and I realize I&#8217;ve been blindly writing main functions to actually do something.</p> <p>This insanity must stop!</p> <p>What am I talking about? <a href="http://schuchert.wikispaces.com/Tdd.HelloWorld.Cpp">Read it here.</a></p> Thu, 20 May 2010 10:12:00 -0500 urn:uuid:d09424a6-eb8f-4d9a-8025-35839675f928 Brett Schuchert http://blog.objectmentor.com/articles/2010/05/20/hello-world-revisited Schuchert's Scattered Synapses TDD seam link Clojure Prime Factors <p>Can anyone create a simpler version of prime factors in Clojure?</p> <pre> (ns primeFactors) (defn of ([n] (of [] n 2)) ([factors n candidate] (cond (= n 1) factors (= 0 (rem n candidate)) (recur (conj factors candidate) (quot n candidate) candidate) (&gt; candidate (Math/sqrt n)) (conj factors n) :else (recur factors n (inc candidate)) ) ) ) </pre> Sat, 15 May 2010 19:09:59 -0500 urn:uuid:dc11f22c-be2f-4173-b06e-1f6926e7c70c Uncle Bob http://blog.objectmentor.com/articles/2010/05/15/clojure-prime-factors Uncle Bob's Blatherings TDD is wasting time if... <p>You have no design sense.</p> <p>OK, discuss.</p> Sat, 08 May 2010 10:36:00 -0500 urn:uuid:f6a0d637-2639-493f-ba51-4535409bd137 Brett Schuchert http://blog.objectmentor.com/articles/2010/05/08/tdd-is-wasting-time-if Schuchert's Scattered Synapses TDD design Sufficient Design means Damned Good Design. <p>@JoshuaKerievsky wrote a <a href="https://elearning.industriallogic.com/gh/submit?Action=PageAction&#38;album=blog2009&#38;path=blog2009/2010/sufficientDesign&#38;devLanguage=Java">blog</a> entitled &#8220;Sufficient Design&#8221;.</p> <p>Josh makes this point:</p> <blockquote> <p>&#8216;Yet some programmers argue that the software design quality of every last piece of code ought to be as high as possible. &#8220;Produce clean code or you are not a software craftsman!&#8221;&#8217;</p> </blockquote> <p>He goes on to say:</p> <blockquote> <p>&#8220;Yet ultimately the craftsmanship advice fails to consider simple economics: If you take the time to craft code of little or moderate value to users, you&#8217;re wasting time and money.&#8221;</p> </blockquote> <p>Now this sounds like heresy, and I can imagine that software craftsmanship supporters (like me) are ready to storm the halls of Industrial Logic and string the blighter up by his toenails!</p> <p>But hold on there craftsmen, don&#8217;t get the pitchforks out yet. Look at the scenario that Josh describes. It&#8217;s quite revealing.</p> <p>Josh&#8217;s example of &#8220;not being a craftsman&#8221; is his niggling worry over a function that returns a string but in one derivative case ought to return a void.</p> <p>Horrors! Horrors! He left a bit of evolved cruft in the design! Revoke his craftsman license and sick the dogs on him!</p> <p>Ah, but wait. He also says that he spent a half-day trying to refactor this into a better shape but eventually had to give up.</p> <p>The fool! The nincompoop! The anti-craftsman! A pox on him and all his ilk!</p> <hr> <p>OK, enough hyperbole. It seems to me that Josh was behaving exactly as a craftsman should. He was worrying about exactly the kinds of things a craftsman ought to worry about. He was making the kinds of pragmatic decisions a craftsman ought to make. He was not leaving a huge mess in the system and rushing on to the next feature to implement. Instead he was taking care of his code. The fact that he put so much energy, time, and thought into such a small issue as an inconsistent return type speaks volumes for Josh&#8217;s integrity as a software craftsman.</p> <p>So, as far as Josh Kerievsky is concerned &#8220;Sufficient Design&#8221; is &#8220;Pretty Damned Good Design&#8221;.</p> <p>Look, all our software will have little tiny warts. There&#8217;s no such thing as a perfect system. Craftsmen like Josh work hard to keep those warts as small as possible, and to sequester them into parts of the system where they can do the least harm.</p> <p>So the only aspect of Josh&#8217;s post that I disagree with is his contention that the &#8220;craftsman&#8221; message is one of unrelenting perfection. Craftsmen are first and foremost pragmatists. They seek very high quality code; but they are not so consumed with perfection that they make foolish economic tradeoffs.</p> Wed, 28 Apr 2010 18:02:10 -0500 urn:uuid:7af1f4ce-c8d6-40c7-aa72-57d9c40f32be Uncle Bob http://blog.objectmentor.com/articles/2010/04/28/sufficient-design-means-damned-good-design Uncle Bob's Blatherings Software Craftsmanship Certification: Don't Waste Your Time! <p>As I have said before, there&#8217;s nothing particularly wrong with the current mania for certification. If you want to be certified at the cost of a 2-day course, by all means get certified. If you want to certify people for attending your 2-day course, by all means hold the course and hand out the certificates. It&#8217;s all good. Make money! Be fruitful and multiply!</p> <p>But be careful not to waste your time.</p> <p>How could certification be a waste of time? That depends on your motive.</p> <ul> <li>If you are getting certified in order to impress someone, like a hiring manager, or a recruiter, or your peers, <em>you are wasting your time.</em> Nobody worth impressing is going to find this certification impressive. Indeed, the people you <em>really</em> want to impress are likely to find it a bit mundane. </li> <li>If you are getting certified in order to get hired, <em>you are wasting your time</em>. Nobody is going to hire you simply because of that &#8220;C&#8221;, and nobody worth working for is going to require that &#8220;C&#8221;. </li> <li>If you have decided to hire only <em>certified</em> people, <em>you are wasting your time</em>. The population of certified people is not richer in talent, skill, or knowledge. Indeed, it may be poorer. Remember, those who have talent don&#8217;t <em>need</em> certification as much as those who don&#8217;t.</li> </ul> <p/> <br/> <p>What part of certification is <em>not</em> a waste of time?</p> <ul> <li>The primary benefit you are getting is the instruction; but be careful: There are lots of pretty mediocre instructors out there. Some of the instructors teach pretty good courses, but others are just hoping that all you care about is the certification. </li> <li>So do a little research and find the best instructors. You may, in fact, find that some of the best instructors and courses do not offer certification. That shouldn&#8217;t stop you from considering them.</li> </ul> <p/> <br/> But wait, aren&#8217;t the instructors certified as trainers? <ul> <li>Sure. They paid the money and took the course to become a certified trainer. </li> <li>But that doesn&#8217;t necessarily mean that they: <ul> <li>are a good instructor.</li> <li>know what they are teaching.</li> <li>have done what they are teaching.</li> <li>are qualified to teach <em>you</em>.</li> </ul></li> </ul> <p/> <br/> OK, but isn&#8217;t there <em>some</em> benefit to the certification itself? <ul> <li>Sure. A nice piece of paper.</li> </ul> Tue, 27 Apr 2010 15:11:00 -0500 urn:uuid:0bd59c14-765c-48d4-9a9f-537c09e56da7 Uncle Bob http://blog.objectmentor.com/articles/2010/04/27/certification-dont-waste-your-time Uncle Bob's Blatherings Pair Management <p>Every once in a while in life, you get a lucky break. My lucky break was right as I was graduating from college. One of my favorite professors told the class that there were some people interviewing potential hires on campus and they were looking for a programmer. I remember standing dutifully outside his office, in line, waiting for my little mini-interview. When it was my turn, they didn’t see me for a little while – the door stayed closed after they let the last interviewee out. I found out later, that my professor was telling the interviewers that I was the guy that they wanted.</p> <p>I came in, and showed them some code I’d written outside of schoolwork, and we talked about it. I told them about my passion for programming languages and they said that the job would be at a research department and they needed someone to design and implement a new programming language. I was over the moon. It was my dream job. And, sure enough, it was real. When I was hired, I sat down with my boss and went over ideas for syntax with him, and he pretty much left me alone for a couple of months to design the language, and implement a compiler for it. I was sitting in my first job, with some real responsibility, struggling with <span class="caps">YACC</span>, designing a symbol table. It was all very heady.</p> <p>In retrospect, I was extremely lucky. I not only had more individual trust and responsibility than many developers ever get in their career, I also became part of an extremely good working environment. The guys who hired me, David Lopez de Quintana, and Carlos Perez, also ran the team I was part of. We were a group of about four which eventually grew to about 12. Although, we weren’t working on one big integrated project, we saw ourselves as a team and we had a great cooperative culture. We each had our area of expertise, and most of us were in our 20s, ready to stretch. We tackled all sorts of interesting problems at the intersection of software, mechanics, electronics, optics, physics, chemistry and biology.</p> <p>About six months into the job, I had an odd experience. Carlos called me to his office and told me he was going to give me my review. I was a bit shocked. The way I understood things, David was actually the guy I worked for, and Carlos headed up part of the team but not my part. Carlos gave me a big smile and said “Yeah, well, you’ve been working for me for the past few months, but we didn’t tell you.”</p> <p>The review went great and I happily went back to work. I always knew that, on paper we were two different teams, but Dave and Carlos treated us as one big team. We had one big meeting every week or so, and they shared responsibilities and pretty much kept us from having to care about anything outside the work we had to do.</p> <p>It was a very cool experience. Sometimes, Dave would spend more time outside the team, sort of managing our interface with the rest of the organization. Part of the group wrote software to support research but we had customers outside of our group too. Dave would be off at meetings, and Carlos would handle the day-to-day stuff with our team. Sometimes they reversed the roles. Dave would handle us day to day and Carlos would manage the world outside. The thing is, no one was asking them to allocate responsibilities that way; they just found it a comfortable way of working. It was pair management. Sort of like pair-programming, but at the management level.</p> <p>The funny thing is that I haven’t seen this much since. Yes, I’ve visited organizations with teams that do something close to this, but it seems like all sorts of forces are aligned against it. The thing which made it work for Dave and Carlos is that they were very good friends. They were hired at the same time in entry-level non-management positions and they rose through the ranks together. They saw each other outside work all the time and joked together at work, making it all a very rich experience. Importantly, their manager never seemed to put them in competition with each other. As I reflect on it more, I think that was the key. Managers are often in competition with each other and that can impede the sort of collaboration and culture that Dave and Carlos built up. They created a wonderful high-performing team. It was one of those once in a lifetime things, and it&#8217;s a time that I’ll always remember.</p> <p>Whenever I think about team health and culture, that first team I joined is my benchmark. I don&#8217;t know where the magic came from, but it was there and I think that the culture that Dave and Carlos created with pair management was a very important part of it. In their interactions with each other, they provided a model for us, showing us how to treat each other at work.</p> Mon, 26 Apr 2010 04:52:00 -0500 urn:uuid:5391d702-b996-475b-b84d-604766493c1c Michael Feathers http://blog.objectmentor.com/articles/2010/04/26/pair-management Michaels Musings The Tricky Bit <p>I once heard a story about the early days of the Concorde. A british MP was on board for a demonstration flight. As the jet went supersonic he disappointedly commented to one of the designers that it didn&#8217;t feel any different at all. The designer beamed and said: &#8220;Yes, <em>that</em> was the tricky bit.&#8221;</p> <p>I wonder if the MP would have been happier if the plane had begun to vibrate and shake and make terrifying noises.</p> <p>While at #openvolcano10, Gojko Adzic and Steve Freeman told the story of a company in which one team, among many, had gone agile. Over time that team managed to get into a nice rhythm, passing it&#8217;s continuous builds, adding lots of business value, working normal hours, and keeping their customers happy. Meanwhile other teams at this company were facing delays, defects, frustrated customers, and lots of overtime.</p> <p>The managers at this company looked at the agile team, working like a well-oiled machine, and looked at all the other teams toiling in vain at the bilge pump, and came to the conclusion that the project that the agile team was working on was too simple to keep them busy. That the other teams&#8217; projects were far more difficult. It didn&#8217;t even occur to them that the agile team had figured out the tricky bit.</p> Fri, 23 Apr 2010 04:28:35 -0500 urn:uuid:51763c35-d308-49f1-8291-7aa690e33425 Uncle Bob http://blog.objectmentor.com/articles/2010/04/23/the-tricky-bit Uncle Bob's Blatherings Agile Methods The R.E.A.L.I.T.Y. principles of Agile Software Certification. <p>As you are probably aware the Scrum Alliance is planning to offer a <em>Certified Scrum Developer</em> program. You can read about it <a href="http://www.scrumalliance.org/CSD">here</a>.</p> <p>Interestingly enough Microsoft, in collaboration with Ken Schwaber, is offering a <em>Professional Scrum Developer</em> program. You can read about that <a href="http://www.scrum.org/newsandupdates/tag/certified-scrum-developer">here</a> (look carefully at the url).</p> <p>The scrum alliance program seems to be about agile skills. The Microsoft program seems to be about Visual Studio. So all is right with the world.</p> <p>Is there anything wrong with this? Is this somehow immoral or <em>bad</em>? Not at all. This is just people doing what people do: Selling services and making money. I&#8217;m all for it. I expect the courses to be of a quality that you&#8217;d expect from professionals; and I&#8217;m sure that students will learn useful information. Indeed, from time to time, even I have offered <span class="caps">CSM</span> courses taught by people I trust and respect.</p> <p>There are, however, some claims that need to be dealt with. The most important is that these programs <em>shorten</em> the recruiting process.</p> <p>I&#8217;ve been thinking about offering a <em>Certified Recruiter for Agile Professionals</em> course. This fifty-two week course will teach, and reteach, a number of principles of Agile Software Certification. I call this repertoire of principles: R.E.A.L.I.T.Y.</p> <p>The first principle is the <em>Redaction of Certification Principle</em> (RCP). The principle states:</p> <blockquote> <p><em>Certifications generally certify nothing whatever about experience, knowledge, or skill. Generally they certify that the certificate holder has attended (or at least paid to attend) a course. Perhaps they took (and maybe even passed) an exam based on that course.</em></p> </blockquote> <p>Based on this principle, any recruiter taking my <em>Certified Recruiter for Agile Professionals</em> course will not be allowed to complete the course or receive their certification until they have taken the following oath.</p> <blockquote> <p> As a <em>Cerftified Recruiter for Agile Professionals</em> I solemnly swear before Knuth and all here present:</p> </blockquote> <blockquote> <p>That before I read a resume, I will find every use of the word &#8220;certified&#8221; on that document and redact it with whiteout.</p> </blockquote> <blockquote> <p>That if a candidate uses the word &#8220;certified&#8221; in an interview, I will ask the candidate to repeat him- or herself without using that word.</p> </blockquote> <blockquote> <p>That I will pay <em>no</em> attention whatever to any implications of that word, nor will that word in any way influence my opinions regarding that candidate.</p> </blockquote> <p>This oath is an exemplar of the <em>Certification Nullification Principle</em> (CNP), which is another of the R.E.A.L.I.T.Y. principles of common sense and moderately competent thinking. The principle states:</p> <blockquote> <p>The word &#8220;certified&#8221;, when used in the context of Agile Software Development, is a filler word that has no bearing on anything salient or interesting about individuals, skills, knowledge, or anything else. It is a marketing word similar to &#8220;new&#8221;, &#8220;improved&#8221;, &#8220;natural&#8221; and &#8220;organic&#8221;. It can safely be removed from all documents and discussions without changing their meaning.</p> </blockquote> <p>This principle leads to the well known <em>Certification Uncertainty Principle</em> (CUP), yet another of the R.E.A.L.I.T.Y. principles. This principle states:</p> <blockquote> <p>Any acronym that includes the letter &#8216;C&#8217; standing for the word &#8220;Certification&#8221; can be safely changed into a similar acronym that eliminates the letter &#8216;C&#8217; and puts a &#8217;?&#8217; at the end. This transformation of the acronym vastly improves the meaning of the orginal.</p> </blockquote> <p>That last sentence probably requires some justification. After all, extraordinary claims require extraordinary substantiation. So lets try a few experiments:</p> <pre> Statement Ac'nm CUP Resulting Statement ---------------------------- ----- ---- --------------------- Certified Scrum Master CSM SM? Scrum Master? Certified Scrum Developer CSD SD? Scrum Developer? Certified Scrum Trainer CST ST? Scrum Trainer? Certified Scrum Professional CSP SP? Scrum Professional? Certified Scrum Product Owner CSPO SPO? Scrum Product Owner? Certified Scrum Coach CSC SC? Scrum Coach? </pre> <p>As we can see, the meanings of the statements are indeed clarified. In my course the <em>Certified Recruiter for Agile Professionals</em> is taught that the question mark is the most significant aspect of each of the resultant statements.</p> <p>In recent weeks we have uncovered a potentially profound new principle which we may find necessary to include in the R.E.A.L.I.T.Y. repertoire. This is the so-called <em>Scrum Exclusion Principle</em> (SEP) which tentatively states:</p> <blockquote> <p>Wherever the word <span class="caps">SCRUM</span> appears in any statement, or is represented within any acronym, it can be safely excluded without changing any meaning.</p> </blockquote> <p>The following table show just how profound the effects of this principle are:</p> <pre> Statement Ac'nm CUP SEP Resulting Statement ---------------------------- ----- ---- ---- --------------------- Certified Scrum Master CSM SM? M? Master? Certified Scrum Developer CSD SD? D? Developer? Certified Scrum Trainer CST ST? T? Trainer? Certified Scrum Professional CSP SP? P? Professional? Certified Scrum Product Owner CSPO SPO? PO? Product Owner? Certified Scrum Coach CSC SC? C? Coach? </pre> <p>We are not yet willing to say that these transformation are a reliable feature of nature. We can only say that, at this point, there are very troubling implications that support it.</p> <p>Our final advice to <em>Certified Recruiters for Agile Professionals</em> is based on one final principle: The <em>Smoke and Mirrors</em> principle, (SAM) which states:</p> <p>Well&#8230; You know what it states.</p> Wed, 21 Apr 2010 05:29:00 -0500 urn:uuid:9ebfb589-8dc1-482f-a1bc-b170e3605e75 Uncle Bob http://blog.objectmentor.com/articles/2010/04/21/the-r-e-a-l-i-t-y-principles-of-agile-software-certification Uncle Bob's Blatherings The Mayans are Coming! <p>This one is just a quickie; too long for a tweet.</p> <p>I gave a lightning keynote (actually a key-rant) today at #accu2010. It was about a bet between John Lakos and Kevlin Henney. Kevlin &#8220;won&#8221; the bet last night by showing that he could get a C++ program to behave in a way that John said couldn&#8217;t be done. My rant was about how both of them were wrong (not technically, but morally) and so they both owed <em>me</em> the sum of the bet. (I&#8217;m always happy to insert myself into any available revenue stream.)</p> <p>The problem they had coded, and for which I presented a <em>far superior</em> solution in Clojure, was that old work-horse of prob/stat: &#8220;What&#8217;s the probability that out of N people in a room two will have the same birthday?&#8221;</p> <p>Now, just to show you how strange James Bach is (and why his strangeness is in some bizarre way actually valuable); once my talk was done, James got up and said &#8220;What if some of the people in the room are ancient Mayans who use a completely different kind of calendar making it impossible to compare their birthdays?&#8221;</p> <p>I&#8217;ve long said that testers were deviant souls with twisted minds that delight in reducing helpless software systems into piles of smoking slag. I believe James may be the exemplar.</p> Sat, 17 Apr 2010 11:22:59 -0500 urn:uuid:edce528f-1582-4928-b139-3d3393c0e5ae Uncle Bob http://blog.objectmentor.com/articles/2010/04/17/the-mayans-are-coming Uncle Bob's Blatherings Parts 5 and 6 of the 4-part series <p>The title says it all. I was bothered by a few things in the Shunting Yard Algorithm (actually many more things), but I felt compelled to fix two of those things.</p> So if you have a <a href="http://vimeo.com/album/210446">look at the album</a>, you&#8217;ll notice 2 more videos: <ul> <li><a href="http://vimeo.com/10979675">Video 5 of 4</a>: Remove the need for spaces between tokens.</li> <li><a href="http://vimeo.com/10994492">Video 6 of 4</a>: Remove duplication of operators in algorithm and tokenizer.</li> </ul> <p>Hope these are interesting or at least entertaining.</p> Fri, 16 Apr 2010 20:57:00 -0500 urn:uuid:e2b52b26-ffe1-4953-8749-9f6987cb224a Brett Schuchert http://blog.objectmentor.com/articles/2010/04/16/parts-5-and-6-of-the-4-part-series Schuchert's Scattered Synapses c TDD visual studio resharper shunting yard algorithm dry SRP don t repeat yourself single responsibility Principle refactoring Sapient Testing: The &quot;Professionalism&quot; meme. <p>James Bach gave a stirring keynote today at <span class="caps">ACCU 2010</span>. He described a vision of testing that our industry sorely needs. Towit: Testing requires sapience.</p> <p>Testing, according to Bach, is not about assuring conformance to requirements; rather it is about <em>understanding</em> the requirements. Even that&#8217;s not quite right. It is not sufficient to simply understand and verify the requirements. A good tester uses the behavior of the system and the descriptions in the requirements, (and face-to-face interaction with the authors of both) to <em>understand the motivation behind the system</em>. Ultimately it is the tester&#8217;s job to divine the system that the customer <em>imagined</em>; and then to illuminate those parts of the system that are not consistent with that imagination.</p> <p>It seems to me that James is attempting to define &#8220;professionalism&#8221; as it applies to testing. A professional tester does not blindly follow a test plan. A professional tester does not simply write test plans that reflect the stated requirements. Rather a professional tester takes responsibility for <em>interpreting</em> the requirements with intelligence. He tests, not only the system, but also (and more importantly) the assumptions of the programmers, and specifiers.</p> <p>I like this view. I like it a lot. I like the fact that testers are seeking professionalism in the same way that developer are. I like the fact that testing is becoming a <em>craft</em>, and that people like James are passionate about that craft. There may yet be hope for our industry!</p> <p>There has been a long standing frission between James&#8217; view of testing and the Agile emphasis on <span class="caps">TDD</span> and automated tests. Agilists have been very focussed on creating suites of automated tests, and exposing the insanity (and inanity) of huge manual testing suites. This focus can be (and has been) misinterpreted as an <em>anti-tester</em> bias.</p> <p>It seems to me that professional testers are completely compatible with agile development. No, that&#8217;s wrong. I think professional testers are <em>utterly essential</em> to agile development. I don&#8217;t want testers who rotely execute brain-dead manual test plans. I want testers <em>using their brains</em>! I want testers to be partners in the effort to create world-class, high-quality software. As a professional developer I want &#8211; I need &#8211; professional testers helping me find my blind spots, illuminating the naivete of my assumptions, and partnering with me to satisfy the needs of our customers.</p> Thu, 15 Apr 2010 06:18:00 -0500 urn:uuid:b9343975-d80a-4e70-86ef-41a3c95ec5fd Uncle Bob http://blog.objectmentor.com/articles/2010/04/15/sapient-testing-the-professionalism-meme Uncle Bob's Blatherings Software Craftsmanship Agile Methods C# TDD Videos - You asked for them <p>Several people asked for them, so here is a series of 4 videos. The first series on the <span class="caps">RPN</span> calculator in Java was a bit rough, these are even rougher.</p> <p>Even so, hope you find them valuable.</p> <p><a href="http://vimeo.com/album/210446">Shunting Yard Algorithm in C# Video Album</a></p> <p>Comments and feedback welcome.</p> Wed, 14 Apr 2010 23:29:00 -0500 urn:uuid:1cbbb31c-687f-4789-97f7-496168f5d0e4 Brett Schuchert http://blog.objectmentor.com/articles/2010/04/14/c-tdd-videos-you-asked-for-them Schuchert's Scattered Synapses c TDD visual studio resharper shunting yard algorithm Open Spaces at conferences, what's your take? <p>I&#8217;m the host for an open space this year at <a href="http://www.agiletestingdays.com/">Agile Testing Days 2010, Berlin</a> (October 4th &#8211; 7th, the open space being the 7th). I&#8217;ve attended a few open spaces and I have some ideas on what the role of host might entail.</p> <p>But, I know I&#8217;m better at collecting requirements than sourcing them, so what have you experienced that worked. What has not worked. Any advice you want to give me?</p> <p>Please help me better understand what I can do to facilitate a successful open space.</p> <p>What questions should I be asking?</p> <p>Do you think having a few things scheduled up front in one room, and several unscheduled rooms left to be determined October 4th &#8211; 6th, through a a mix if you will, is an OK thing to do, or should what happens be left completely open?</p> <p>Or, leave everything completely open until the 7th, then start with the &#8220;traditional&#8221; introductions and let the agenda form then an there?</p> <p>I&#8217;m aware of a few models of open spaces. What I really want to know is, what works for<i> <b>you</i></b>.</p> Wed, 07 Apr 2010 10:39:00 -0500 urn:uuid:135e7271-d989-42a8-b37c-632b0b6ddc96 Brett Schuchert http://blog.objectmentor.com/articles/2010/04/07/open-spaces-at-conferences-whats-your-take Schuchert's Scattered Synapses open space agile testing days 20% more bugs? Or 20% less features? <p>People often make the argument that time to market is more important that quality. I&#8217;m not sure just what they mean by that. Do they mean that it&#8217;s ok if 20% of the features don&#8217;t work so long as they deliver quickly? If so, that&#8217;s just stupid. Why not develop 20% fewer features, and develop them well. It seems to me that <em>choosing</em> which 20% you are not going to develop and then <em>choosing</em> to develop the other 80% to a high standard of quality is a better management decision than telling the developers to work sloppily.</p> Tue, 06 Apr 2010 22:03:23 -0500 urn:uuid:9282cb2f-5432-45d6-a819-1df5fde99b61 Uncle Bob http://blog.objectmentor.com/articles/2010/04/06/20-more-bugs-or-20-less-features Uncle Bob's Blatherings Clean Code First Pass Completed: Rough Draft TDD Demonstration Videos <p>As promised, I&#8217;ve made a complete sweep through a series of videos. You can find all of them: <a href="http://www.vimeo.com/album/205252">here</a>.</p> <p>These videos include several warts and false starts. Depending on the interest and feedback, I&#8217;ll redo these at some point in the future.</p> <p>Question: Should I repeat this series in C#, or some other language? Some people have expressed interest in this. It&#8217;s probably 15 hours of work in C#, so I&#8217;d need to know it was worth the effort. What&#8217;s your opinion on that?</p> The videos are meant to be watched in order. The link above is to an album that is in the correct order. Here are the direct links (also in the intended order): <ul> <li><a href="http://vimeo.com/10569751">Getting Started</a></li> <li><a href="http://vimeo.com/10570537">Adding Basic Operators</a></li> <li><a href="http://vimeo.com/10597511">Removing Duplication</a></li> <li><a href="http://vimeo.com/10597797">Extracting to Strategy</a></li> <li><a href="http://vimeo.com/10639853">Removing Duplication via Refactoring</a> or <a href="http://vimeo.com/10647496">Removing Duplication via Tdd using Mockito</a></li> <li><a href="http://vimeo.com/10647851">Introducing an Abstract Factory</a></li> <li><a href="http://vimeo.com/10679730">Adding a Sum operator</a></li> <li><a href="http://vimeo.com/10681803">Adding Prime Factors Operator</a></li> <li><a href="http://vimeo.com/10685388">Composing Operators and Programming the Calculator</a></li> <li><a href="http://vimeo.com/10686005">Using FitNesse to Program the Calculator</a></li> </ul> <p>I&#8217;ve already received several comments both here on the blog as well as with the videos. I&#8217;ll keep track of those comments and incorporate the ones that fit for me.</p> Each video has a link on its page to download it. However, to download a video, you will have to create an account and log in. So here are the links, these won&#8217;t work without first creating an account (I&#8217;ll update original blog with these as well): <ul> <li><a href="http://vimeo.com/download/video:18304530?v=2&#38;e=1270570714&#38;h=b96f13f4196fb68985933c1c21fb5806&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Getting Started Download</a></li> <li><a href="http://vimeo.com/download/video:18306776?v=2&#38;e=1270570773&#38;h=c38f8df6121e8df77af35fcd36e419bf&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Adding Basic Ops Download</a></li> <li><a href="http://vimeo.com/download/video:18366822?v=2&#38;e=1270570794&#38;h=407bf072c5fca10490bcf35d77ccf220&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Removing Duplication Download</a></li> <li><a href="http://vimeo.com/download/video:18367523?v=2&#38;e=1270570821&#38;h=318f20bb72e306d89fe8970ab7005ab0&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Extracting to Strategy</a></li> <li><a href="http://vimeo.com/download/video:18461046?v=2&#38;e=1270570837&#38;h=a77d9a69d45406e22265ab01b899c9f3&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Removing Dups/Refactoring Download</a></li> <li><a href="http://vimeo.com/download/video:18514764?v=2&#38;e=1270570854&#38;h=44c7be60020a70b78731eae5e5d9eb45&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Removing Dups/Tdd Download</a></li> <li><a href="http://vimeo.com/download/video:18507614?v=2&#38;e=1270570871&#38;h=1d52c79bdec4ab10c5201eb58b1024c7&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Abstract Factory Download</a></li> <li><a href="http://vimeo.com/download/video:18549114?v=2&#38;e=1270570893&#38;h=70bb69d0d935a26baf4048ec173bb6ae&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Sum Operator Download</a></li> <li><a href="http://vimeo.com/download/video:18553519?v=2&#38;e=1270570907&#38;h=e6147f1020074049b8047a38623940e7&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Prime Factors Download</a></li> <li><a href="http://vimeo.com/download/video:18561716?v=2&#38;e=1270570924&#38;h=5ef2bec871f87e2c694c7baaddab20b2&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Composing Math Operators Download</a></li> <li><a href="http://vimeo.com/download/video:18563340?v=2&#38;e=1270570944&#38;h=cfe26669faf53b7521f6ef9b992311ec&#38;uh=336ace2a37cb6bd8e82e9fac1c0b7f02">Using FitNesse Download</a></li> </ul> Mon, 05 Apr 2010 01:15:00 -0500 urn:uuid:6b7e69d3-afbb-42a9-9d56-0319292ef786 Brett Schuchert http://blog.objectmentor.com/articles/2010/04/05/first-pass-completed-rough-draft-tdd-demonstration-videos Schuchert's Scattered Synapses TDD mockito FitNesse video Eclipse Java Some Rough Draft TDD Demonstration Videos <p>I&#8217;m doing a series of videos on <span class="caps">TDD</span>. The ultimate result will be a much more polished version with embedded slides, and such. But as a part of the development process, I&#8217;m creating scratch videos.</p> <p>Much of what you see in these videos will be in the final versions, but those are far in the future relative to this work.</p> <p>Hope you find them interesting.</p> <p>Comments welcome.</p> Here is what is already available: <ul> <li><a href="http://vimeo.com/10569751">Getting started</a></li> <li><a href="http://vimeo.com/10570537">Adding Operators</a></li> </ul> Next up: <ul> <li>Removing violation of Open/Closed principle</li> <li>Removing duplication in operations with a combination of the Strategy pattern and the Template Method pattern</li> <li>Adding new operators after the removal of duplication.</li> <li>Reducing coupling by using the Abstract Factory pattern, Dependency Inversion and Dependency Injection</li> <li>Adding a few more operations</li> <li>Allowing the creation of complex &#8220;programs&#8221; or &#8220;macros&#8221; by using the Composite pattern &#8211; and avoiding Liskov Substitution Principle inherent in the GoF version of the pattern</li> <li>Driving the calculator via FitNesse + Slim</li> </ul> <p>Anyway, that&#8217;s the plan. I&#8217;ll try to add each of these videos over the next few weeks.</p> Tue, 30 Mar 2010 21:01:00 -0500 urn:uuid:f9144f21-6bbf-4e5d-b525-9e526c000fe8 Brett Schuchert http://blog.objectmentor.com/articles/2010/03/30/some-rough-draft-tdd-demonstration-videos Schuchert's Scattered Synapses TDD bdd video demonstration design patterns SRP LSP OCP DIP Injecting Those Dependencies <p>Last week I was teaching a class with a good group of C++ developers in Chicago. They were up on C++, current standardization efforts, virtual machines, performance analysis and tuning. At one point I mentioned a metric for virtual method dispatch on the <span class="caps">JVM</span> and one of the students used my numbers to work backwards to determine the number of instructions on different processors.</p> <p>I was teaching our Working Effectively with Legacy Code class. Michael Feathers usually teaches this class, but he was busy (probably working with legacy code somewhere, which, ironically, is why he wrote the book &#8211; to solve the problem once and for all and to stop working with legacy code).</p> In an early project we have some problem code (the class was in Java, but we discussed C++ quite a bit): <div class="typocode"><pre><code class="typocode_default "> public void addEvent(Event event) { event.added(); events.add(event); mailService.sendMail(&quot;jacques@spg1.com&quot;, &quot;Event Notification&quot;, event .toString()); display.showEvent(event); }</code></pre></div> The problem with this code, however, comes from what happens in the constructor: <div class="typocode"><pre><code class="typocode_default "> public Scheduler(String owner, SchedulerDisplay display) { this.owner = owner; mailService = MailService.getInstance(); this.display = new SchedulerDisplay(); }</code></pre></div> <p>The display object is associated with a real device (OK, not in our simulation, but you get the point). We need to fix that dependency.</p> So we traditionally talk about a few ways to address that: <ol> <li>Create an interface and then have a concrete and test-double implementation</li> <li>Create a test subclass</li> </ol> Those are a few typical ways to handle this problem, but given that the students also worked in C++ and were very concerned with performance (and dynamic binding), so we discussed more alternatives: 1. Link seam &#8211; build the system using the original SchedulerDispaly header file but link in a different version of the class. 2. Template parameter (compiler seam) &#8211; introduce a template parameter and compile in the dependency rather than link it in. <div class="typocode"><pre><code class="typocode_default ">#pragma once template&lt;class D&gt; class Scheduler { public: Scheduler(D &amp;display); ~Scheduler(); void handleEvent(); private: D &amp;display; };</code></pre></div> So here are 4 ways to remove the dependency (working bottom up in a sense): <ol> <li>Link seam: link in a different version of SchedulerDisplay</li> <li>Compiler seam: use a template parameter</li> <li>Dynamic seam: create a test subclass that removes external dependency</li> <li>Dynamic seam: extract an interface from existing concrete class, and make Scheduler depend on the new interface.</li> </ol> <p>For C++, the first option might be a good option if it allows a very quick build/test cycle. Imagine using a class that brings in several unwanted dependencies. By making a test version replacement and linking to it, you might be able to get up and running quickly. On the other hand, you have to have a custom build target, which is really outside of the language.</p> The second option is good for C++ and maybe C#, but not Java. Java&#8217;s implementation of generics is so bad, that it requires an interface for this particular case, so you end up with the final option anyway. Using templates puts the seam into the language rather than the build system. It will affect clients because either: <ol> <li>They will have to provide a template parameter</li> <li>Or, by providing a default value for the template parameter, clients will be aware of a class they were not previously aware of. Still, a viable option, but it will increase build time at least a little.</li> </ol> <p>The third option may not work in any language without changing the original problem code. Imagine a no argument constructor that performs some static initialization. Without changing the constructor, you cannot guarantee that this approach will work. In any case, the problem as presented requires a change since the constructor was doing the initialization of the display; it did not allow for dependency injection.</p> <p>The final option requires a bit more change, but is pretty flexible if you can afford the virtual method overhead. In Java this isn&#8217;t much of an issue (for a number of reasons, mostly related to effective <span class="caps">JIT</span> optimization). The cost is a bit more of a problem in C++ because introducing a first virtual method is a big deal. Personally, I don&#8217;t work on embedded systems, so I can generally ignore that problem. But this is not something to simply ignore, context does matter.</p> <p>So which option is the best?</p> <p>None of the above.</p> <p>As a developer, you should probably be aware of all of these options (or maybe not the template option of you&#8217;re strictly a Java developer). Then, when you are faced with a legacy coding problem, you&#8217;ll have more tools from which to choose.</p> Mon, 22 Mar 2010 16:00:00 -0500 urn:uuid:079869bc-e7ef-4708-9a69-7b24541bd190 Brett Schuchert http://blog.objectmentor.com/articles/2010/03/22/injecting-those-dependencies Schuchert's Scattered Synapses welc refactoring dependency injection Developer Certification WTF? <p>Watch the following video. It will convince you that we have to do <em>something</em> about the horrible state of software engineering.</p> <object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=9981123&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=9981123&amp;server=vimeo.com&amp;show_title=1&amp;show_byline=1&amp;show_portrait=0&amp;color=&amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/9981123">Bad Code</a> from <a href="http://vimeo.com/user947916">unclebob</a> on <a href="http://vimeo.com">Vimeo</a>.</p> <p>How could any team of disciplined professionals have produced a wretched mess like that? Clearly they were ignorant of good practices. Clearly they were inexperienced novices. Clearly their priorities and values were all wrong. If only they had been taught good coding practices, and good development skills. If only we could have gotten to them before they made such a horrible mess.</p> <p>What we need to do is create a <em>certification program</em> that provides developers with the knowledge and skills that they need. This program will involve a course that teaches good development practice, and a <em>certification</em> that they are now knowledgeable developers. They can use that certification to prove to their employers and their fellow professionals that they are worthy of being considered true and clean software developers.</p> <p>That&#8217;s what we need. Right?....</p> <h1><strong>Eagle&#8217;s Entrails! Deer Droppings! and Elephant Phlatulence!</strong></h1> <p>I&#8217;m sorry, am I being vague? Is my opinion not clear enough? All right then, allow me to elaborate.</p> <h2>What Problem does Certification solve?</h2> <p>Certainly there are certification organizations who have the problem of dwindling revenues. A new developer certification program would likely solve <em>their</em> problem.</p> <p>And just as certainly there are tin-men who need hearts, lions who need courage, scarecrows who need brains, and developers who need self-esteem. A new developer certification program might just help those lackluster developers.</p> <p>But who else is served by a developer certification program? Employers?</p> <h2>The Trials of Hercules.</h2> <p>Consider Doctors and Lawyers. When a medical student earns an M.D., or a law student passes the Bar, that&#8217;s an <em>achievement</em>. The certification, in those cases is deeply meaningful because the certification is <em>not easily won</em>. To get it you have to spend many years, and many tens of thousands of dollars. What&#8217;s more, you have to acquire in-depth knowledge and at least a modicum of provable skill. You have to do something <em>significant</em>.</p> <p>If we had a developer certification like <em>that</em>, then employers might find it useful. But I know of no developer certification program (except for one that I&#8217;ll mention later) that offers proof that the developer has accomplished anything of significance. Most certification programs prove little more than that the &#8220;developer&#8221; paid to attend a 3-5 day course. As an employer, I&#8217;m not particularly interested in the ability of a developer to pay to attend a 3-5 day course. As an employer I want to know what the developer can <em>do</em>.</p> <h2>Michaelangelo&#8217;s Apprentice.</h2> <p>If you were hiring a guitarist for your band, you might be very impressed with someone who toured with Clapton. You don&#8217;t get to tour with Clapton unless you are talented. But more than just talented, you have to show up every day, you have to work well with others, you have to be willing to get the job done under pressure. Clapton doesn&#8217;t work with slouches!</p> <p>A signed letter of recommendation from <em>Clapton</em> is a certification of <em>significance</em>! Not just anyone can get one of those. That letter will impress potential employers forever after.</p> <p>As an employer, I want to hire people who have succeeded at working with others in the past. The more I trust those others, the better! No developer certification program that I know of (except for one that I&#8217;ll mention later) provides that kind of credible reference.</p> <h2>Over-promise and Under-deliver.</h2> <p>The certification programs that I know of (except for one that I&#8217;ll mention later) make implicit promises that they can&#8217;t hope to begin to deliver. The implied promise is that the certificant has been shown to have some <em>significant</em> skill, ability, or knowledge. The reality is that you have to look at the word &#8220;significant&#8221; through the wrong end of some very powerful binoculars before it matches the truth. Indeed, there are certification programs that show absolutely nothing about the certificant except that they bought a seat in a class.</p> <p>Notice that I said that the promises were <em>implicit</em>. That&#8217;s the whole key to making lightweight certifications profitable. The goal is to imply that the benefits of certification are so huge that people will pay to get the certification. Often that implication can be as simple and subtle as the choice of words used to <em>name</em> the certification.</p> <p>Consider, for example, the title of &#8220;Certified Development Chief&#8221; imprinted on the certificate of someone who just took a &#8220;Development Chief&#8221; course. Who wouldn&#8217;t want to be a <em>Certified</em> Development Chief? And if you aren&#8217;t a <em>Certified</em> Development Chief, then what kind of Development Chief are you?</p> <h2>A course, a card, and a Bridge to sell.</h2> <p>What significant accomplishment can a developer make by paying to attend (or even actually attending) an 3-5 day course? How credible a recommendation about any of the 20-odd students could an instructor of such a course make? I can answer both questions in two words, with apologies to <span class="caps">SNL</span>. &#8220;Jack&#8221; and &#8220;Cheese&#8221;. The accomplishment is miniscule, and the recommendation is meaningless.</p> <p>So as an employer of developers I think you can take your course and card and show it to some other sucker. It don&#8217;t impress me much. Go away and come back later when you&#8217;ve accomplished the trials of Hercules and apprenticed under Michaelangelo. And make sure you bring letters of reference. <span class="caps">NEXT</span>!</p> <h2>The one I said I&#8217;d mention later.</h2> <p>I&#8217;ve got an idea for a certification program that just might work. Now, bear with me because this is a little complicated. It&#8217;s an idea so revolutionary, so different, so incredibly <em>new</em> that I&#8217;m getting giddy just thinking about it.</p> <p>What if we asked young graduates to actually get jobs as &#8220;interns&#8221; for awhile. What if we gave out responsibility to them in small incremental measures. What if they gradually learned more and more things while working for us. What if we guided them to ever greater accomplishments. What if we slowly gave them trials of Hercules to follows, and had them work with Michaelangelos.</p> <p>Of course some of our people might leave and go to greener pastures. We&#8217;ll need to replace them. Also, our company might succeed and grow, so we&#8217;ll need to hire more good developers. So what if we&#8230;</p> <p>OK, now hold on to your hat because this is where it gets really tricky. You might want to get up and walk around a bit, get a diet coke, eat a twinkie, or something to get your brain working.</p> <p>Ready? OK, here we go&#8230;</p> <p>So what if we&#8230; <em>interviewed</em> ... candidate developers? What if we asked them what accomplishments they&#8217;d achieved in previous employment. What if we asked them who they used to work with. And&#8230; ok, this is even wilder ... what if we <em>called</em> those references and checked them out?</p> <p>Are you still with me?</p> <p>What if we&#8230;.</p> <p><em>Naaaaahhhhh.</em> Dumb idea.</p> <p>Honestly, I think I&#8217;ve wasted your time. It&#8217;s a stupid idea. Never mind. We should all just go get certified instead.</p> Sun, 07 Mar 2010 12:16:43 -0600 urn:uuid:0867886b-db75-4f5a-a52c-c00ea09f6b89 Uncle Bob http://blog.objectmentor.com/articles/2010/03/07/developer-certification-wtf Uncle Bob's Blatherings One way to configure FitNesse for team Development <p>Here are some notes (and instructions) on a way to configure FitNesse for use in a team environment: <a href="http://schuchert.wikispaces.com/FitNesse.PageHierarchyForTeamDevelopment">Page Hierarchy For Team Development</a>.</p> <p>Comments and suggestions welcome.</p> Fri, 19 Feb 2010 14:12:00 -0600 urn:uuid:35d8f8e2-f3c5-4b68-a893-9d8e457c67ed Brett Schuchert http://blog.objectmentor.com/articles/2010/02/19/one-way-to-configure-fitnesse-for-team-develomment Schuchert's Scattered Synapses FitNesse team development server configuration Updated ConTest Instructions <p>Just updated the instructions for using ConTest &#8211; a tool to assist in testing concurrent applications for Java. Check them out here: <a href="http://tinyurl.com/ydq83rn">ConTest Instructions</a></p> Thu, 18 Feb 2010 12:12:00 -0600 urn:uuid:fb2adb07-9afb-44d4-9f18-f8efe67dd563 Brett Schuchert http://blog.objectmentor.com/articles/2010/02/18/updated-contest-instructions Schuchert's Scattered Synapses concurrent testing DotNet Development Using Parallels Is No Longer Painful <p>Because of the travel involved with being an Object Mentor, my main computer is my laptop, a MacBookPro. I have to be able to work wherever I happen to be, whether I&#8217;m at home, at Object Mentor Galactic Headquarters, or in a plane, train, or automobile. We&#8217;re allowed to buy whatever we want, and we all have independently settled on Macs, running <span class="caps">OS X</span>. I&#8217;ve developed on lots of different platforms over the years, but I find that <span class="caps">OS X</span> is <b>the</b> most productive development environment that I&#8217;ve ever used.</p> <p>Besides the travel, we have to be jacks of all trades. One week I&#8217;m programming in Java, the next week I&#8217;m teaching a design class, and the next I&#8217;m developing in .NET. I&#8217;m able to do it all on my Mac, even the .NET work, through the magic of virtualization. I choose to run Parallels so that I&#8217;m able to run Windows as a process under <span class="caps">OS X</span>. Windows crashing isn&#8217;t a problem anymore, in that it doesn&#8217;t bring my entire computer down. One process just dies (or I&#8217;m forced to kill it) and I just start it up again, and all the other running processes just keep right on working.</p> <p>I&#8217;m a backup fanatic. Besides having bootable backups produced using SuperDuper, I just love the way TimeMachine is built into <span class="caps">OS X</span>, allowing me to recover versions of any file on my computer going back months. And it&#8217;s all automatic. TimeMachine just runs in the background, keeping me safe.</p> <p>But the thing about Parallels + TimeMachine that I just hate, is that Parallels stores all of Windows as one big file. A big one. Huge! So whenever I&#8217;m working in Parallels, the one big file is being changed and is going to be backed up again the next time TimeMachine runs. Needless to say this takes up a lot of space on my TimeMachine drive, but it&#8217;s also a damn nuisance. About the time that TimeMachine finishes its backup, it&#8217;s time to start all over again just because of the file size. Yet I dare not back up. I&#8217;m in the camp that believes it&#8217;s not a question of <b>if</b> your computer will fail, but <b>when</b>.</p> <p>Because Parallels creates a share with my home directory on the <span class="caps">OS X</span> side, I thought about just keeping my source code there. That actually works, until I try to build or do anything with the code other than edit it, and then I get a security violation of some sort.</p> <p>While I&#8217;m developing in Windows, I do frequent commits to git, my new favorite source code control system. It&#8217;s easy to go back to a previous version of any file, something that I can&#8217;t say about ctrl-z in Visual Studio.</p> <p>The light finally lit up over my bald head. Git is a <i>distributed</i> version control system. Distributed doesn&#8217;t have to be any farther away than the <span class="caps">OS X</span> side of my file system.</p> <p>I set up a git repository in <span class="caps">OS X</span> for every project that I work on. Then I can push/pull from/to it, just like I would do if I was working on a team project hosted on github. Why don&#8217;t I just get a private github account? This is easier and I don&#8217;t have to be connected to the net to do push/pulls.</p> <p>Here are the details in case anyone wants to try it.</p> <p>In a Terminal window in <span class="caps">OS X</span>:</p> <code> <pre> MBP:~ bob$ cd Archive/git MBP:git bob$ mkdir PresenterAsStateMachine.git MBP:git bob$ cd PresenterAsStateMachine.git MBP:PresenterAsStateMachine.git bob$ MBP:PresenterAsStateMachine.git bob$ git --bare init Initialized empty Git repository in /Users/bob/Archive/git/PresenterAsStateMachine.git/ MBP:PresenterAsStateMachine.git bob$ </pre> </code> <p>then, in Windows, using the bash window that comes with git:</p> <code> <pre> $ git init Initialized empty Git repository in c:/Documents and Settings/Administrator/My Documents/Visual Studio 2008/Projects/PresenterAsStateMachine/.git/ $ git add . $ git commit -a -m "Initial commit. Ready to add state machine." [master (root-commit) f844369] Initial commit. Ready to add state machine. 16 files changed, 795 insertions(+), 0 deletions(-) create mode 100644 .gitignore create mode 100644 PresenterAsStateMachine.sln create mode 100644 PresenterAsStateMachine.suo create mode 100644 PresenterAsStateMachine/Form1.Designer.cs create mode 100644 PresenterAsStateMachine/Form1.cs create mode 100644 PresenterAsStateMachine/Form1.resx create mode 100644 PresenterAsStateMachine/LoginPresenter.cs create mode 100644 PresenterAsStateMachine/LoginPresenterTest.cs create mode 100644 PresenterAsStateMachine/LoginView.cs create mode 100644 PresenterAsStateMachine/PresenterAsStateMachine.csproj create mode 100644 PresenterAsStateMachine/Program.cs create mode 100644 PresenterAsStateMachine/Properties/AssemblyInfo.cs create mode 100644 PresenterAsStateMachine/Properties/Resources.Designer.cs create mode 100644 PresenterAsStateMachine/Properties/Resources.resx create mode 100644 PresenterAsStateMachine/Properties/Settings.Designer.cs create mode 100644 PresenterAsStateMachine/Properties/Settings.settings </pre> </code> <p>Now I set up the git repository that I had previously created in <span class="caps">OS X</span> as the remote:</p> <code> <pre> $ git remote add origin //.psf/Home/Archive/git/PresenterAsStateMachine.git/ $ git push origin master Counting objects: 20, done. Compressing objects: 100% (19/19), done. Writing objects: 100% (20/20), 12.74 KiB, done. Total 20 (delta 1), reused 0 (delta 0) Unpacking objects: 100% (20/20), done. To //.psf/Home/Archive/git/PresenterAsStateMachine.git/ * [new branch] master -&gt; master </pre> </code> <p>And now push and pull to my heart&#8217;s content, as well as add and commit to my local repository.</p> <p>Now I configure TimeMachine to not back up the Parallels virtual machine directory. It still gets backed up daily by SuperDuper, but they only files that I want to be able to recover versions of is the source code that I&#8217;m working on &#8211; and this technique serves me well for that.</p> Tue, 16 Feb 2010 15:16:00 -0600 urn:uuid:5d549c00-51a6-45cc-930f-3fd9b4088c28 Bob Koss http://blog.objectmentor.com/articles/2010/02/16/dotnet-development-using-parallels-is-no-longer-painful Young Bob's Rants Getting Started in Objective-C with XCode <p>As I mentioned in a previous <a href="http://blog.objectmentor.com/articles/2010/02/08/rudimentary-tdd-with-xcode-and-objective-c">previous blog</a>, I wrote up some notes on getting started practicing <span class="caps">TDD</span> using XCode and Objective-C. I&#8217;m intending to write a bit more, so the top level of the overall tutorial path starts here: <a href="http://schuchert.wikispaces.com/tdd.objectivec.AFirstProject">A First Objective-C Project</a></p> <p>If you just want to see the details of getting started: <a href="http://schuchert.wikispaces.com/tdd.objectivec.XCodeProjectSetup">XCodeProjectSetup</a></p> <p>The biggest change from the previous blog is an embedded video demonstration. If you&#8217;re just interested in the video: <a href="http://vimeo.com/9394596">Getting started</a></p> <p>Want to seem more? Something in particular? Let me know.</p> <p>Comments welcome.</p> Thu, 11 Feb 2010 23:07:00 -0600 urn:uuid:24a88145-37df-44a3-94f7-e91671b790af Brett Schuchert http://blog.objectmentor.com/articles/2010/02/11/getting-started-in-objective-c-with-xcode Schuchert's Scattered Synapses TDD objective c getting started Is TDD Language Neutral? On another blog, a commenter wrote (I&#8217;m leaving names out, though you can see the original blog if you look): <blockquote> I don’t think that it makes sense to say “teach a <span class="caps">TDD</span> class in several languages simultaneously”. <span class="caps">TDD</span> is a language-independent technique. </blockquote> <p>What follows is a slightly changed version of my response. What I&#8217;m wondering is this: Do you think the practice of <span class="caps">TDD</span> is fundamentally impacted by your programming language?</p> <p>Read on for my response. You might want to add a comment before reading my response to avoid &#8220;group think.&#8221;</p> <p>Based on the original comment, I started with: It seems to me that you’ve not written professionally in many different languages. Or if you have, you’ve not effectively used those different programming languages.</p> <p>Now let me be a bit more clear. Java and C++ are different languages, to be sure. However, they are both class-based, statically typed languages without lambdas (well C++ and Java will both be getting them, but they don’t have them now).</p> <p>Contrast Java and C++ with Smaltalk and Self. Smalltalk is class based and supports inheritance but it is dynamically typed. Self is object-oriented, but it does not have classes. In fact, it technically does not have inheritance, but it fully supports <span class="caps">OOP</span>. How? Delegation. JavaScript is closer to Self than it is to Smalltalk. But JavaScript, Self and Smalltalk are all closer than C++, Java, C# and Objective-C.</p> <p>How about the Open/Closed principle? How I interpret that design principle depends on the context (language) in which work. In raw Java, what I think needs to be closed is different than say raw Ruby. If I add Aspect Oriented Programming into the mix (yes, I’ve actually written and deployed systems that used Aspect J – in a limited fashion), then that opens things up a bit, but still not as much as in Ruby.</p> <p>In Smalltalk, the closest analog to static methods are class methods. However, a class method in Smalltalk is actually an instance method on a class object, which is a subclass of the Class class. (Yes, that’s what I meant.)</p> <p>Why is this important? When I’m working with legacy code in C++/Java/C#/VB.Net – languages where static methods are never dynamically bound, I avoid using static methods and, in fact, I redesign using what Michel Feathers calls “Introducing an Instance Delegator”.</p> <p>In Smalltalk, this technique is irrelevant and unnecessary.</p> <p>In languages like JavaScript, Self, Smaltalk, Ruby, etc., interfaces are not really necessary. Sure you can use them, but they are more for documentation.</p> <p>Consider templates in C++ versus generics in Java. In Java, generics experience type erasure so you often need to use interfaces with generics – or at least tell the compiler a type it can assume will always be used with a generic. In C++, the most you really need to do is let the complier know that a template parameter is a typename as opposed to a primitive. When the code is compiled, any implied requirements of the type parameter will either be satisfied or not. (Woe be it to you if they are not!)</p> <p>Why? In Java, generics are syntactic sugar. C++ generates a unique class for each template occurrence. C# is much closer to C++ than Java in this respect. Java got it wrong (in my opinion) – though what they did add did improve the language a bit.</p> <p>How about moving away from OO languages? Scala is a mixed language, as is F#. Haskel is not. Lisp as well. How you break a problem into parts is (or at least should be) different in these languages. I don’t mean different in syntax, to be sure it will be. I mean how you break a problem into its parts is fundamentally different in pure functional languages than OO languages.</p> <p>Or consider <span class="caps">COBOL</span>. I’ve programmed in it. I can thank <span class="caps">COBOL</span> for my touch-typing skills. <span class="caps">COBOL</span> is yet a different kind of language. Yes, syntactically, but that’s not the interesting difference. <span class="caps">COBOL</span> is a record-oriented processing language. It is well suited to batch processing. <span class="caps">AWK</span> is similar in this respect as is <span class="caps">SNOBOL</span>. (I’ve used <span class="caps">AWK</span> quite a bit, and I’ve used a variant of <span class="caps">SNOBOL</span> called <span class="caps">SPITBOL</span> as well.)</p> <p>Let’s continue with a building analogy. If all I have to build is bamboo then I have available to me certain techniques for building a house. If I have steel, I have different alternatives. The design of my house will be directly impacted by the media (language) available.</p> <p>Additionally, if I’m building on clay versus bedrock, I will also make fundamentally different design issues. When I lived in Texas I had a floating slab foundation, which were common for several reasons: cost, temperature zone, available building materials. Texas was the first place I lived that did not in general have basements. The other option, pier and beam, was no longer practiced in general due to cost.</p> <p>I’m originally from the Mid-West (Iowa). In Iowa, buildings are built such that their foundation is below the frost line. The frost line was something like 30” (I’m remembering something from 20 – 30 years ago). So all the houses had basements. Or if not basements, half-basements.</p> <p>The same kinds of things can be said about programming languages as well as their ecosystems as well as the political environment. I’ve already made the language point above. But what about the political environment?</p> <p>I have worked at places where open source was forbidden. So this rules out Hibernate and Spring. Taking away these tools does not stop me from building a system, but it does have an impact on gross assignment of responsibility, which is an important component of software architecture.</p> <p>Now, back down to a <span class="caps">TDD</span> class. When I teach <span class="caps">TDD</span>, I am not teaching just <span class="caps">TDD</span>. Furthermore, I am not just talking about <span class="caps">TDD</span>. I want students to apply the practice. So I start with a problem – a requirements statement. That does not initially vary with the language. In practice it eventually does for several reasons:</p> <ul> <li>How far the class can get with the problem is impacted by by their skills as well as the programming language. C++ and vi are slower to work in that Java and Eclipse.</li> <li>What you can reasonably do is impacted by both the language as its environment. For example, it is easy to look at a <span class="caps">DLL</span> and dynamically find all concrete implementations of an interface in any .Net language. It’s harder to do that in Java, though possible. In C++ it is platform specific.</li> <li>There are more…</li> </ul> <p>The students do need to learn the mechanics:</p> <ul> <li>How to write a test using a particular unit testing framework</li> <li>How to write production code</li> <li>The shortcut keys of the environment</li> <li>The refactoring support in the <span class="caps">IDE</span></li> </ul> <p>But what are the students testing? Units? Sure, let’s go there.</p> <p>Language affects the units. You are testing units. Different kinds of units, different kinds of responsibilities. Different kinds of responsibilities to be verified, different unit tests.</p> <p>Things are not so cleanly separated as you would like to imagine.</p> <p>This very idea can be seen in natural languages. Different languages are better/worse at expressing things. The language you use directly affects how you interpret the world. This actually impacts the physical wiring in the brain. Really, it does.</p> <p>So I do not agree.</p> <p>And I challenge you to write the same problem in two fundamentally different languages (e.g. Java and Lisp) using <span class="caps">TDD</span>. Then have those two different solutions reviewed by experts in each of those languages.</p> <p>I claim that if you’ve done an effective job of using those languages, your solutions will be different <span class="caps">AND</span> the unit tests you created to get to those solutions will be fundamentally different (not just mechanically different).</p> <p>If, on the other hands, the unit tests are the same (other than the mechanics), then at least one group of people will say your solution is a bad use of their particular language. You’ll either be programming Java in Lisp or Lisp in Java.</p> Tue, 09 Feb 2010 09:38:00 -0600 urn:uuid:99b04a35-41dd-4abc-9cc7-feeb9d67c715 Brett Schuchert http://blog.objectmentor.com/articles/2010/02/09/is-tdd-language-neutral Schuchert's Scattered Synapses language impact TDD Rudimentary TDD with XCode and Objective-C We have a potential client that would like us to teach a <span class="caps">TDD</span> class in several languages simultaneously: <ul> <li>Java</li> <li>JavaScript</li> <li>C++</li> <li>Objective-C</li> </ul> <p>In turns out that for what we teach in our <span class="caps">TDD</span> class, Java, C++ and Objective-C can be taught at the same time fairly easily. JavaScript, however, not so much. It is a very different (great, but different) beast.</p> <p>In fact I could add C# to the mix as well, but I&#8217;d have to leave out <span class="caps">LINQ</span> and Lambdas.</p> <p>In any case, to teach a class like that, I prefer to have the students do a bit of preliminary work so that they know how to set up their environments. When there&#8217;s just one language, I do this on the fly. But when there&#8217;s 3, I don&#8217;t want 2/3rds of the class waiting while 1/3rd learns how to create a basic project supporting <span class="caps">TDD</span>.</p> <p>The last time I used Objective-C was in 1991, so I needed to figure out how to do this in the environment it is most likely to be used. This turned out to be a bit more work than I expected. I found it all using the good old google-machine, but in pieces. Since there really wasn&#8217;t a great (in my opinion) one-stop place that clearly laid out all of the steps, <a href="http://schuchert.wikispaces.com/tdd.objectivec.XCodeProjectSetup">I created one</a>.</p> <p>This is in a early state. If you have comments, I&#8217;d appreciate them. I&#8217;ll probably add more. (If you&#8217;d like to see more, let me know that as well.) At this point, the basics are pretty much there, so I don&#8217;t actually need to do anything else. However, I have taken this just a bit further: <a href=http://schuchert.wikispaces.com/tdd.objectivec.AFirstProject">This is the top-level of the tutorial</a></p> <p>Again, comments and suggestions welcome.</p> Mon, 08 Feb 2010 18:24:00 -0600 urn:uuid:76caf33c-893e-4e12-9803-e4f2992165ba Brett Schuchert http://blog.objectmentor.com/articles/2010/02/08/rudimentary-tdd-with-xcode-and-objective-c Schuchert's Scattered Synapses TDD objective c xcode ocunit