tag:blogger.com,1999:blog-32828604292305878682024-03-13T01:23:19.611-05:00On Software DevelopmentThoughts on software design, development, and process.Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-3282860429230587868.post-26622954365518796922009-02-23T18:08:00.004-06:002009-02-23T18:13:26.469-06:00Make it Maintainable and Readable First<div xmlns="http://www.w3.org/1999/xhtml">You're probably aware of the Donald Knuth quote <a href="http://en.wikiquote.org/wiki/Donald_Knuth">"Premature optimization is the root of all evil (or at least most of it) in programming."</a>. I reviewed some code recently that reminded me of that quote and why making code readable and maintainable is the first order of business. The code I reviewed reversed the usual order for checking for a null reference to -<br /><pre><code><br />if (null != instance) { ...}<br /></code>></pre><br />I don't like this code because it uses a non-standard idiom and forces me to stop and read the code from right to left to understand it. I've run across this idiom once before and the best reason I have gotten for using it is that it is supposed to be faster. Well, I can't imagine why it would be faster and even it if was there are certainly better performance optimizations that don't affect code readability. Being curious I decided to test the this optimization and wrote a little java test code.<br /><pre><code><br />public class NullTest {<br />public static long testNullFirstAgainstNonNull(int count, boolean display) {<br /> long start = System.currentTimeMillis();<br /> Object obj = getObject();<br /> int x = 0;<br /><br /> for (int i = 0; i < count; i++) {<br /> if (null == obj) {<br /> x++;<br /> }<br /> }<br /><br /> long end = System.currentTimeMillis();<br /> if (display) System.out.println("if (null == [non-null]) -- " + (end - start));<br /> return x;<br />}<br /><br />public static int testNullFirstAgainstNull(int count, boolean display) {<br /> long start = System.currentTimeMillis();<br /> Object obj = getNullObject();<br /> int x = 0;<br /><br /> for (int i = 0; i < count; i++) {<br /> if (null != obj) {<br /> x++;<br /> }<br /> }<br /><br /> long end = System.currentTimeMillis();<br /> if (display) System.out.println("if (null != [null]) -- " + (end - start));<br /> return x;<br />}<br /><br />public static int testNullLastAgainstNonNull(int count, boolean display) {<br /> long start = System.currentTimeMillis();<br /> Object obj = getObject();<br /> int x = 0;<br /><br /> for (int i = 0; i < count; i++) {<br /> if (obj == null) {<br /> x++;<br /> }<br /> }<br /><br /> long end = System.currentTimeMillis();<br /> if (display) System.out.println("if ([non-null] == null) -- " + (end - start));<br /> return x;<br />}<br /><br />public static int testNullLastAgainstNull(int count, boolean display) {<br /> long start = System.currentTimeMillis();<br /> Object obj = getNullObject();<br /> int x = 0;<br /><br /> for (int i = 0; i < count; i++) {<br /> if (obj != null) {<br /> x++;<br /> }<br /> }<br /><br /> long end = System.currentTimeMillis();<br /> if (display) System.out.println("if ([null] != null) -- " + (end - start));<br /> return x;<br />}<br /><br /><br />private static Object getObject() {<br /> return new Object();<br />}<br /><br />private static Object getNullObject() {<br /> return null;<br />}<br /><br />public static void main(String[] args) {<br /> int count = 100000;<br /> testNullFirstAgainstNonNull(count, false);<br /> testNullFirstAgainstNull(count, false);<br /> testNullLastAgainstNonNull(count, false);<br /> testNullLastAgainstNull(count, false);<br /> testNullFirstAgainstNonNull(count, false);<br /> testNullFirstAgainstNull(count, false);<br /> testNullLastAgainstNonNull(count, false);<br /> testNullLastAgainstNull(count, false);<br /><br /> count = 100000000;<br /> System.out.println(" Results from " + count + " executions.");<br /> System.out.println("============================================================");<br /> testNullFirstAgainstNonNull(count, true);<br /> testNullFirstAgainstNull(count, true);<br /> testNullLastAgainstNonNull(count, true);<br /> testNullLastAgainstNull(count, true);<br /> System.out.println();<br /> testNullFirstAgainstNonNull(count, true);<br /> testNullFirstAgainstNull(count, true);<br /> testNullLastAgainstNonNull(count, true);<br /> testNullLastAgainstNull(count, true);<br /> System.out.println();<br /> testNullFirstAgainstNonNull(count, true);<br /> testNullFirstAgainstNull(count, true);<br /> testNullLastAgainstNonNull(count, true);<br /> testNullLastAgainstNull(count, true);<br /> System.out.println();<br /> testNullFirstAgainstNonNull(count, true);<br /> testNullFirstAgainstNull(count, true);<br /> testNullLastAgainstNonNull(count, true);<br /> testNullLastAgainstNull(count, true);<br /> System.out.println();<br /> testNullFirstAgainstNonNull(count, true);<br /> testNullFirstAgainstNull(count, true);<br /> testNullLastAgainstNonNull(count, true);<br /> testNullLastAgainstNull(count, true);<br /> System.out.println();<br />}<br />}<br /></pre></code><br />The test tries to prime execution and warmup the JVM by running each test before displaying any results. The usual caveats about micro-benchmarks, etc. apply to the results below. I ran this under to Sun JVMs, 1.4 and 6, with similar results that show no performance benefits and just reinforce for me the importance of writing code that is readable, maintainable and understandable.<br /><pre><br />$ /c/j2sdk1.4.2_17/bin/java -version<br />java version "1.4.2_17"<br />Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_17-b06)<br />Java HotSpot(TM) Client VM (build 1.4.2_17-b06, mixed mode)<br /><br />$ /c/j2sdk1.4.2_17/bin/java NullTest<br />Results from 100000000 executions.<br />============================================================<br />if (null == [non-null]) -- 141<br />if (null != [null]) -- 156<br />if ([non-null] == null) -- 141<br />if ([null] != null) -- 172<br /><br />if (null == [non-null]) -- 141<br />if (null != [null]) -- 156<br />if ([non-null] == null) -- 140<br />if ([null] != null) -- 172<br /><br />if (null == [non-null]) -- 141<br />if (null != [null]) -- 172<br />if ([non-null] == null) -- 140<br />if ([null] != null) -- 157<br /><br />if (null == [non-null]) -- 140<br />if (null != [null]) -- 172<br />if ([non-null] == null) -- 141<br />if ([null] != null) -- 156<br /><br />if (null == [non-null]) -- 141<br />if (null != [null]) -- 172<br />if ([non-null] == null) -- 140<br />if ([null] != null) -- 172<br /><br /><br />$ java -version<br />java version "1.6.0_07"<br />Java(TM) SE Runtime Environment (build 1.6.0_07-b06)<br />Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)<br /><br />$ java NullTest<br />Results from 100000000 executions.<br />============================================================<br />if (null == [non-null]) -- 62<br />if (null != [null]) -- 63<br />if ([non-null] == null) -- 62<br />if ([null] != null) -- 63<br /><br />if (null == [non-null]) -- 62<br />if (null != [null]) -- 78<br />if ([non-null] == null) -- 63<br />if ([null] != null) -- 62<br /><br />if (null == [non-null]) -- 63<br />if (null != [null]) -- 62<br />if ([non-null] == null) -- 63<br />if ([null] != null) -- 62<br /><br />if (null == [non-null]) -- 63<br />if (null != [null]) -- 62<br />if ([non-null] == null) -- 63<br />if ([null] != null) -- 62<br /><br />if (null == [non-null]) -- 63<br />if (null != [null]) -- 62<br />if ([non-null] == null) -- 63<br />if ([null] != null) -- 62<br /></pre><br /><br /><br /><div class="zemanta-pixie"><img src="http://img.zemanta.com/pixy.gif?x-id=aa080d8e-e1d8-4c8b-8000-08c0c6c2f18f" class="zemanta-pixie-img" /></div></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com8tag:blogger.com,1999:blog-3282860429230587868.post-26574709245336851592008-07-26T14:15:00.005-05:002008-07-26T14:21:12.014-05:00Just Say No to Deflaut Configuration<div xmlns="http://www.w3.org/1999/xhtml">What I'm talking about is when an application sets its configurable properties using default values because the configuration for the environment the application is intended to run in cannot be set. Default configuration can be the result of specific application logic or a feature of the configuration framework or mechanism used. How this usually plays out is that some generic set of values, often the ones used in the "dev" environment, are used instead of the values for a specific environment like "qa", "stage", or "prod". Sometimes a debug or info message or, if you are lucky, a warning message will be logged. But just as often there is no direct evidence that the desired configuration has not been used.<br /><br />At first blush having a default configuration to fall back on seems like a good idea. It can simplify development, especially unit testing, because things just work. There is no need to understand or be bothered with the details about configuration before you've even started coding. Where this will come back to bite you, and I guarantee that sooner or later it will, is when someone forgets to configure your application before a new production deployment. Everything looks great, the smoke tests pass, and everyone is happy. At least they are happy until, for some unknown reason, the pricing for widget XYZ is wrong or the customer ABC just seems to have disappeared. Since you turned off info and debug logging in production, there is nothing in your logs to indicate a problem. Now you get to spend some time frantically looking through code for the change, that doesn't exist, that is causing the problems.<br /><br />Using default configuration violates the principle of failing fast. When there is a problem in your application, the application code should fail as soon as possible and it should be crystal clear why it failed. You don't want to detect a problem through side effects. When there is a serious error, and what could be more serious than incorrect configuration, I want to see a big red flag waving or at least a big loud error message in the logs! I want my application to fail before it can startup and cause even greater problems by reading or writing the wrong database or processing messages from the wrong message queue.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com5tag:blogger.com,1999:blog-3282860429230587868.post-3597863767249969912008-07-24T18:38:00.004-05:002008-07-26T13:25:15.335-05:00Bonehead Exception Handling<div xmlns="http://www.w3.org/1999/xhtml">I found this bit of Java exception handling code in a major open source project -<br /><pre><code> <br />try {<br /> .... <br />} catch (ClassNotFoundException e) {<br /> throw new IntegrationException("Rule Set jar is not correctly formed.");<br />} catch (IOException e) { <br /> throw new IntegrationException("Rule Set jar is not correctly formed."); <br />};<br /></code></pre><br />The specifics of the code in the try block are unimportant, what does matter is how the exceptions thrown by that code are handled. Besides being completely amateurish, the exception handling is wrong in at least three ways.<br /><br />First it completely loses the original exception. Whatever context the original exception had is just gone. Since Java 1.4 it has been possible to include the root cause of the error. Before Java 1.4 the programmer could at least have appended the original error message.<br /><br />Second it turns two completely different types of errors in a one type. Great so now I get an error that could have two very different causes and no way to figure out the actual cause.<br /><br />Third the error message doesn't say anything at all useful. There is absolutely nothing in the error message that helps me understand or fix the problem. What does "not correctly formed" mean and what in the world does being or not being well formed have to do with a ClassNotFoundException or an IOException?<br /><br />I suppose I should take some solace in the fact that at least it reports an error. But frankly this code is only slightly better than just swallowing the errors.</div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com2tag:blogger.com,1999:blog-3282860429230587868.post-88508604365853953302008-03-25T19:16:00.001-05:002008-03-25T19:16:39.496-05:0010 Principles for Developer Testing<div xmlns='http://www.w3.org/1999/xhtml'><b>1) Code a Little, Test a Little</b><br/><br/>Test driven development is all the rage and is a great way to do "test a little, code a little". But it is important to remember that it is the results not how you achieve them that matter most. As long as test code is written concurrently with implementation code, it doesn't matter if you follow strict test driven development practices because when the tests are done you won't be able to tell what method was followed. The only wrong way to write test code is after the implementation code is done.<br/><br/><b>2) Use Tests to Improve the Design</b><br/><br/>Testability is an excellent indicator of design quality. If your code is hard to test then the design needs to be fixed. Look for warning signs and use the tests to guide the design. Hard to test code includes singletons, static calls, and too many parameters. Warnings signs of a design that needs help include making private methods public for testing, complicated test setup, excessive test assertions and mocking concrete classes.<br/><br/><b>3) Write as Much Test Code as Implementation Code</b><br/><br/>On average you should expect to write at least as many lines of test code as there are implementation code.<br/><br/><b>4) Test the Right Thing</b><br/><br/>It's a <b>unit test</b>, so it should be testing one unit. Since most of us are doing object oriented development the unit is a class. Make sure you are only testing the class under test and not some infrastructure such as database or web server. Make sure you are only testing the class under test and not other classes it may depend on, the dependent classes should already have been well tested by their own unit tests. Make sure you test the things that are likely to break and that usually does not include things like simple getters and setters.<br/><br/><b>5) Test the Error Handling</b><br/><br/>You need to test more than the expected paths through the code. Make sure to test what the code will do under error conditions. Is it catching the right exceptions? Does it handle errors gracefully and cleanup things like database connections?<br/><br/><b>6) Always Write a Test Before Fixing a Bug</b><br/><br/>Whenever you find a bug write a test that fails because of the bug before you try and fix the bug. If you don't have a test before you attempt fix the bug how exactly will you know the bug is gone? Adding a test for every bug will also help ensure that the same bug does not creep back into the system later.<br/><br/><b>7) Mock Objects are Your Friends<br/><br/></b>If you are not using mock objects you need to start. There are numerous excellent and mature open source mock object frameworks for most any language. The benefits of mock objects are to great to ignore. Mock objects let you write truly isolated unit tests, speed up you unit tests, and test things such as error handling that would probably be impossible to automate without mocks. <br/><br/><b>8) Use a Code Coverage Analyzer</b><br/><br/>Test coverage analyzers are wonderful tools that can help find inadequately tested code. But always keep in mind that test coverage is about the journey not the destination. Your goal is to have better tested code not necessary 100% code coverage. There are many excellent open source and commercial coverage tools available so there is no reason not to use one.<br/><br/><b>9) Don't be Fooled by High Code Coverage Numbers</b><br/><br/>Depending on the metric used it is possible to have 100% coverage with garbage unit tests. Statement coverage is the poorest way to measure coverage because it only says which lines were executed and says nothing about what branches or paths in the code were tested. Branch coverage tells you which branches in a control structure such as an if or switch statement were executed. So branch coverage combined with statement coverage is pretty good. A better metric is path coverage that will tell you which execution paths through the code were covered.<br/><br/><b>10) Know Your Cyclometric Complexity</b><br/><br/>Cyclometric complexity is a measure of how many execution paths there are through a piece of code. A method or function with no control flow, such as a if statement, will have a complexity of one. The complexity goes up for each execution branch such as and if or else statement. Cyclometric complexity is a good way to get a feel for how many tests a method needs to cover all execution paths through it.<br/> </div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com6tag:blogger.com,1999:blog-3282860429230587868.post-24654862831740307662008-02-26T22:03:00.004-06:002008-02-27T17:51:39.441-06:00Behavior Driven Development is not Domain Driven Design?<div xmlns="http://www.w3.org/1999/xhtml">I had been aware of behavior driven development for a while, but researching my previous post on <a href="http://rwhansen.blogspot.com/2008/02/test-driven-devlopement-reality-check.html">Test Driven Development</a> I came across something that really had me scratching my head. The general view of BDD is an evolution or refinement of TDD with the goal of making TDD more natural and easier to understand. A big part of BDD is a change in mindset from thinking about testing to thinking about behavior and class design. To this end doing BDD has behavior classes, not test cases. BDD also has methods that specify behavior with names that clearly describe the expected behavior and begin with "should" instead of "test". All this is well and good and I expect will make things easier to understand, especially for developers new to agile development.<br /><br />What has me more than a little bothered is the linking of BDD with "<a href="http://www.domaindrivendesign.org/">domain driven design</a>" and the "<a href="http://domaindrivendesign.org/discussion/messageboardarchive/UbiquitousLanguage.html">ubiquitous language</a>" as described by Eric Evans in his <a href="http://www.amazon.com/exec/obidos/ASIN/0321125215">excellent book</a>. The <a href="http://behaviour-driven.org/BehaviourDrivenDevelopment">Behaviour-Driven Development</a> web site and <a href="http://en.wikipedia.org/wiki/Behavior_driven_development">Wikipedia entry</a> read as if BDD is somehow a logical extension of domain driven design. I read everything I could find and saw nothing to backup the claim. Maybe the site is incomplete, or perhaps it just shows the weakness of implementing the Behaviour-Driven Development site as a wiki. So far I am not convinced that BDD has the depth to accomplish domain driven design. From <a href="http://domaindrivendesign.org/">Domain-Driven Design</a> - <blockquote>"Domain-driven design is not a technology or a methodology. It is a way of thinking and a set of priorities, aimed at accelerating software projects that have to deal with complicated domains."</blockquote><a href="http://dannorth.net/whats-in-a-story">Stories</a> will not produce the rich domain model that is needed. Here is the template for a story -<br /><pre><br />Title (one line describing the story)<br /><br />Narrative:<br />As a [role]<br />I want [feature]<br />So that [benefit]<br /><br />Acceptance Criteria: (presented as Scenarios)<br /></pre>This is just an variation on the agile user story and is still too simple, low level, to narrow in focus to result in deep domain knowledge. BDD may give you a well crafted set of classes that implement a feature or story. But how will those classes look in the context of the domain? Will the result superficial or insightful? Will the object connections and interactions be deep and rich, full of meaning, or shallow and empty?<br /><br />Will the developers following BDD understand the vision of the domain model? Will they understand that changing the code is changes the model and the changing the model requires changing the code? It's an issue of the old saying "not seeing the forest for the trees". How do you see the big picture when the focus is so tight on a story and feature and the classes that implement them.<br /><br />"<a href="http://behaviour-driven.org/GettingTheWordsRight">Getting the Words Right</a>" and method names that start with "should" and read like sentences won't guide anyone toward a ubiquitous language for the domain. Getting the language right requires a thorough understanding the the problem domain and that does not come from coding user stories.<br /><br />Don't get me wrong I'm a big believer in agile development and unit testing. I understand that TDD and BDD are as much about design as they are about testing. I been using JUnit since something like 1999. I know how much better unit tests make my code and how much they can improve the design of the classes being tested. But I don't use tests to for domain modeling.<br /><big><br /><em>References</em></big><br /><br /><a href="http://dannorth.net/introducing-bdd">DanNorth.net » Introducing BDD</a><br /><a href="http://video.google.com/videoplay?docid=8135690990081075324">Beyond Test Driven Development: Behaviour Driven Development</a> (Google Video)<br /><a href="http://www.ibm.com/developerworks/web/library/j-cq09187/index.html">In pursuit of code quality: Adventures in behavior-driven development</a><br /><a href="http://www.testearly.com/2007/07/16/using-bdd-to-drive-development/">Test Early » Using BDD to drive development</a></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com6tag:blogger.com,1999:blog-3282860429230587868.post-25388765646981499182008-02-22T22:31:00.009-06:002008-02-22T22:44:56.606-06:00Test Driven Devlopement Reality Check<div xmlns="http://www.w3.org/1999/xhtml">Over the last few months I've been reading blogs and articles evaluating the scope and scale of TDD -<br /><br /><a href="http://www.ddj.com/architect/205207998">Scaling Test-Driven Development</a><br /><a href="http://www.odecee.com.au/blogs/?p=12">Unit testing; how far do you push the envelope?</a><br /><a href="http://scruffylookingcatherder.com/archive/2008/01/22/tdd-proven-effective-or-is-it.aspx">TDD Proven Effective! Or is it?</a><br /><a href="http://agiletesting.blogspot.com/2007/10/whats-more-important-tdd-or-acceptance.html">What's more important: TDD or acceptance testing?</a><br /><br />But what really got my attention was a blog by James Coplien, "<a href="http://www.artima.com/weblogs/viewpost.jsp?thread=216434">Religion's Newfound Restraint on Progress</a>", and a debate about the value of TDD between <a href="http://www.infoq.com/interviews/coplien-martin-tdd">Coplien and Bob Martin</a> recently posted at InfoQ. James Coplien has been on the forefront of software development trends for a couple decades. He is an object oriented and design patterns guy from way back and an agile coach today. His opinion is worth is paying attention. That's why it was quite a surprise to read how opposed he is to TDD. Whether you agree or not it's certainly worth some consideration. All the quotes below are by James Coplien from his blog or his comments on several other blogs (you'll need to read the blog comments for the full text of some of the quotes below).<br /><blockquote>'<a href="http://agiletesting.blogspot.com/2007/10/whats-more-important-tdd-or-acceptance.html">The answer, I think, is to focus on Quality and to find the techniques that work best and are the most cost-effective for your project. Just answering "both" to the "TDD-or-acceptance" question is not only at the wrong scope, it is missing the whole point.</a>'<br /></blockquote>I think Coplein's objections come down two main points, cost effectiveness and the effects that TDD may have on a system's architecture. Further he is concerned that the procedural nature of TDD just does not fit well with the object prardigm.<br /><blockquote>'<a href="http://www.odecee.com.au/blogs/?p=12">Most of TDD is based on xUnit, and the unit of any given test is a procedure.</a>'<br /><br />'<a href="http://www.odecee.com.au/blogs/?p=12">Testing the functionality of object member functions causes one to focus on the functions and lose sight of the objects ...</a>'</blockquote>I've been programming with objects since the late 1980's so this hits home. The overall quality of an object oriented application is much more than the quality of the individual objects. It's about how the objects interact and fit together. We need to look at a higher level than a method or even a class to understand that interaction and create a good design. <blockquote><a href="http://www.odecee.com.au/blogs/?p=12">'... this implies that TDD doesn’t make sense for a system where objects are the primary organizing principle. I don’t know how to test an object. Objects are about structure; what needs to be tested is the degree to which they map the user’s cognitive model of the domain.</a>'</blockquote>I'm still trying to absorb this completely, but my take again is that it's not about a single method or class, it's about the whole system and the objects it is constructed from. On the other hand I know from experience that tests inform class design. When a class is hard to test, perhaps I feel the need to make a private method public to test it properly, I take that as a sign that the class probably needs work.<br /><blockquote>'<a href="http://www.odecee.com.au/blogs/?p=12">In the past five years I have yet to run into a single person who is doing it for other than one of two reasons: that it makes them feel good about themself, or that they are a lemming.</a>'<br /></blockquote>Ouch, seems a bit strong and even hurts a little because I have to admit that good JUnit tests do make me happier. (The rest of these quotes are from "<a href="http://www.artima.com/weblogs/viewpost.jsp?thread=216434">Religion's Newfound Restraint on Progress</a>").<br /><blockquote>'Discussions in this area inspire passion. Why? ... People have tied their Agile success to their introduction of TDD practices into their work. It's the one thing they can do as individuals rather than as an enterprise.'<br /></blockquote>It's true, but I think part of it is also that "good" developers have pride in their work. TDD and unit tests in general are a way we get to directly impact the quality of our code without interference.<br /><blockquote>'On one hand we should be encouraged to use every weapon in our arsenal; on the other hand, we'll never get done if we try to do everything. It then becomes a matter of cost effectiveness. Integration and system testing have long been demonstrated to be the least efficient way of finding bugs. Recent studies (Siniaalto and Abrahamsson) of TDD show that it may have no benefits over traditional test-last development and that in some cases has deteriorated the code and that it has other alarming (their word) effects. The one that worries me the most is that it deteriorates the architecture. And acceptance testing is orders of magnitude less efficient than good old-fashioned code inspections, extremely expensive, and comes too late to keep the design clean.'<br /></blockquote><blockquote>'Sorting these things out requires a system view. It used to be called "systems engineering," but the New Age Agile movements consistently move away from such practices. It shows in the quality of our interfaces, in the incredible code bloat we have today relative to two decades ago..'</blockquote>It seems reasonable to ask if complete unit test coverage is really the most cost effective way to reduce bugs? I know unit testing has improved the quality of the applications I've worked on the last eight years. But could we have written fewer tests and gotten the same level of quality?<br /><br />I've always been skeptical that TFD or TDD alone can produce a good architecture for the long haul. As much as I love refactoring, I'm not convinced that I can refactor my way to a great design. The idea that there is no need for any overall system design is crap. At the same time the idea that an architect can completely design a system upfront is just as crappy. Some level of system design and vision needed, but we have to learn from the system and adjust the design as we iterate. I'm a big proponent of "<a href="http://www.domaindrivendesign.org/">domain driven design</a>" and the bottom line is I just don't think a real domain design will just emerge from coding, testing and refactoring. Domain design takes hard work and thinking, design effort not coding. Writing code is too low-level, too focused on details rather than useful domain abstractions.<br /><blockquote>'Agile is about engaging that user; TDD, about engaging the code. TDD is a methodology. TDD is about tools and processes over people and interactions. Woops.'<br /></blockquote>That's a pretty stinging indictment. If true if TDD isn't following <a href="http://agilemanifesto.org/">agile principles</a>. But I wonder if some the power of TDD is the simplicity and explicitness of its method. The best developers can succeed no matter what the process, but we all no that most software is not written by star developers. TDD sems simple enough fpr anyone to understand and follow to at least improve the quality of class level design and that's be worth something.<br /><blockquote>'It's about thinking, not about checklists.'</blockquote>I can't disagree here because I've know too many developers who want easy answers or rules to follow. Software isn't like that, it's to much of a craft and takes constant attention and thinking to do well.<br /><br />Overall I don't agree with James Coplien, but I think the discussion is worth having and hope everyone will keep an open mind. I know that unit testing (and lot's of it) has improved the quality of the my code and code written by my teams over the last eight years. I'm not a believer in one true way for software development or anything else. I think it is necessary to create a software process that works for you, taking the best practices that work for your in you environment.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com11tag:blogger.com,1999:blog-3282860429230587868.post-79420024138093542002007-11-02T17:40:00.001-05:002008-02-22T20:31:18.163-06:00Big Ball of MudThis <a href="http://blog.objectmentor.com/articles/2007/10/27/big-balls-of-mud-and-shanty-towns">post</a> at Object Mentor reminded me that I'd never actually read the <a href="http://www.laputan.org/mud/">"Big Ball of Mud"</a> paper by Brian Foote's and Joseph Yoder. Quoting from the paper -<br /><blockquote>"A BIG BALL OF MUD is haphazardly structured, sprawling, sloppy, duct-tape and bailing wire, spaghetti code jungle. We’ve all seen them. These systems show unmistakable signs of unregulated growth, and repeated, expedient repair."</blockquote>I'm sure everyone has seen one, worked on one, and even created one. I'm also certain that in general things aren't much different since that paper was first published in 1999. Here is a link to a <a href="http://video.google.com/videoplay?docid=8693679271218408739">"Big Ball Of Mud"</a> Google video presentation by Brian Foote from August 2007. I guess that since the authors are still talking about the pattern we should expect it to be around for a while longer.<br /><br />The next time you need to wade into the swamp, you might want to take a copy of the book <a href="http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052/ref=pd_bbs_sr_1/103-0058491-5390273?ie=UTF8&s=books&qid=1194044172&sr=8-1">"Working Effectively with Legacy Code"</a> with you.Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com4tag:blogger.com,1999:blog-3282860429230587868.post-78148035725346699122007-10-10T18:30:00.002-05:002008-02-22T20:31:49.431-06:00Testability and Design<div xmlns='http://www.w3.org/1999/xhtml'>As Michael Feathers notes, <a href='http://michaelfeathers.typepad.com/michael_feathers_blog/2007/09/the-deep-synerg.html'>'The Deep Synergy Between Testability and Good Design'</a>, there is a lot of discussion about how to test private methods. I think he's absolutely correct that the need to test a private method is a hint about the design. I've been reviewing a class that I was never completely happy with because it exposes private methods for testing. Looking at it today I'm sure it would be possible to extract a class that would improve the design and fix the problem. It would have been much easier to clean this up when I was writing the code than to find the time to fix it now. I wish I had listened closer to the hint that my test was giving me. <br/><br/>It's pretty amazing how much we learn about the goodness of a design when try to test it. In the past I used to write fewer and larger classes than I do today. Most of the reason for the change is for better unit tests. <br/></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com4tag:blogger.com,1999:blog-3282860429230587868.post-27241511040480454262007-10-03T16:50:00.000-05:002007-10-03T16:59:31.640-05:00The Discipline of AgileAn <a href="http://www.ddj.com/architect/20180424">article</a> by Scott Ambler at Dr. Dobb's does a nice job refuting the idea that agile development is not disciplined. I think some of this might come from the lack of ceremony on agile development projects. Things get done and no one makes a big deal of it. Software is normally usable (and very likely releasable) at the end of every iteration, so the actual release can be anti-climatic. Contrast that with traditional methods where every phase or milestone is a big deal and release is often an earth shaking event. Maybe the traditionalists are just mistaking all their ceremony for real discipline.Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com0tag:blogger.com,1999:blog-3282860429230587868.post-36291181844898739642007-09-28T20:25:00.001-05:002007-10-03T16:59:53.950-05:00Never Start With the Data Model<div xmlns="http://www.w3.org/1999/xhtml">My bias is for object oriented design and domain modeling. I am convinced that you don't build great software by starting design with a data model. I think starting with the data model is just about the worst idea and pretty much guarantees mediocre software. The best systems start with a domain model and work through the various layers of the system down to the database, not the other way around.<br /><br />The database should be left until as late in development as possible. Experience shows this is not the case because creating the database is usually one of the first things on a project task list. Instead we should be asking how soon do we really need a database? The unit tests will be better and faster when they don't need a database. You know that data access should be encapsulated behind an interface. Why not leave the database until we know what the data requirements of an at least partially working system are?<br /><br />Honestly, I can't think of a harder way to try to conceptualize a system than through a data model. Do your users understand a database schema? Is a database schema the model of your system you want to carry around in your head? Great software requires a model that can be used to communicate with users, developers, product owners, and domain experts. I don't think a data model is how any business person conceptualizes their business processes. What you need is a consistent coherent domain model that can can be used to make sense of a system at any level. You must be able to "peel the onion" to discover details as needed. Design by data model immediately forces all the nasty gnarly implementation details front and center. It is a well understood user interface design principle that bad designs expose details of the data model via data entry screens. The worst designs percolate the data model from top to bottom.<br /><br />The best software solutions model a problem in the problem domain. A data model is a solution in the database domain not the problem domain. So why is the database schema where design so often starts? Maybe it's the mainframe mentality in big corporations, or naive developers who don't really understand object orientation, or just a general ignorance of object oriented design and domain modeling. Eric Evans wrote great book on <a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_bbs_sr_1/105-6100086-4002858?ie=UTF8&s=books&qid=1191023591&sr=1-1">domain driven design</a> that is not as widely read as it deserves to be. In that book he talks about the "ubiquitous language" of a software project -<br /><blockquote><i>"A domain model can be the core of a common language for a software project. The model is a set of concepts built up in the heads of people on the project, with terms and relationships that reflect domain insight. These terms and interrelationships provide the semantics of a language that is tailored to the domain ..."</i></blockquote>I don't see such a language ever coming from a data model.<br /><br />What prompted me to write this was a <a href="http://www.javalobby.org/java/forums/t101428.html?start=0">post</a> touting the new release of an <a href="http://en.wikipedia.org/wiki/Active_record_pattern">"active record"</a> object relational mapping framework for Java and some controversy it generated in this <a href="http://www.javalobby.org/java/forums/t101596.html">post</a>. As you can probably guess, I'm not really a fan of the active record design pattern. But reading the posts and the comments, and knowing how popular Ruby on Rails is, it's clear that lot's of developers are very big fans.<br /><br />I don't get it. Maybe it's because active record is so easy to understand. I suppose active record might work for small systems. But I would never want to use it on any even moderately sized enterprise software project. I see enough ugly code, highly coupled, tangled classes, and mangled hierarchies without database access code mixed into my business classes and immediately coupling my design to the database. I shudder to imagine the maintenance headaches it would cause. At least I'm in good company -<br /><blockquote><i>"Another argument against Active Record is the fact that it couples the object design to the database design. This makes it more difficult to refactor either design as a project goes forward."</i><br /><br /><small>Martin Fowler, Patterns of Enterprise Application Integration</small><br /></blockquote><blockquote><i>"In an object oriented program, UI, database, and other support code often gets written directly into the business objects. Additional business logic is embedded in the behavior of the UI widgets and database scripts. This happens because it is the easiest way to make things work, in the short run.<br /><br />When the domain-related code is diffused through such a large amount of code, it becomes extremely difficult to see and to reason about. Superficial changes to the UI can actually change business logic. To change a business rule may require require meticulous tracing of UI code, database code, or other program elements."</i><br /><br /><small>Eric Evans, Domain Driven Design</small></blockquote><br />I hope the fans of active record know what they could be getting themselves into, but as usual I doubt that is the case.</div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com9tag:blogger.com,1999:blog-3282860429230587868.post-127524492231255582007-09-19T21:00:00.002-05:002008-02-22T20:32:33.076-06:00There Aren't Any Rules<div xmlns="http://www.w3.org/1999/xhtml">I know a lot of programmers won't agree but there are few, if any, "rules" for writing good code. It doesn't matter what platform or language or type of software you are writing. If you think someone can hand you a set of rules that you can follow to write good code you are mistaken. I try not to call anything a rule anymore. Now I call them guidelines or principles. The difference is that a guideline needs to be interpreted and judged to know when it should be applied. A guideline might also apply to more than one case.<br /><br />Sorry, but I reserve the right to change my mind tomorrow about what I told you today was the right thing. This profession is too young, changes too fast, and is too much of a craft for rules written in stone. I've been doing this long enough to know that many things we consider best practices today are likely to change tomorrow. Remember <a href="http://en.wikipedia.org/wiki/Hungarian_notation">hungarian notation?</a> At one point you would have flunked a code review if you didn't use it, now you'd be more likely to flunk if you did. How about object oriented design? I remember when inheritance and polymorphism were going to save the world. Now too much inheritance is a sure sign of bad design. How about unit testing? We're still discovering the best techniques for things like mock objects.<br /><br />Much of what makes good code depends on situation and context. Michaels Feathers says it very clearly -<br /><blockquote>"Good programming is contextual. Practice is contextual. We can articulate rules about how to use language constructs correctly, but they're just guidelines. Context is king."<br /><br /><a href="http://beautifulcode.oreillynet.com/2007/09/when_good_code_looks_bad.php">When Good Code Looks Bad</a>, Michael Feathers<br /></blockquote>I'd like to add that it is also about having the knowledge and judgment to know which guideline to apply when. There aren't any shortcuts, it takes judgment, practice, and study to write good code. Becoming a good programmer is hard work and you won't be one by following a set of rules. But you might become one if you practice and study the art of programming.<br /><br /><br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com0tag:blogger.com,1999:blog-3282860429230587868.post-29561542781163500202007-09-05T20:39:00.000-05:002007-09-05T20:53:41.194-05:00Metrics To Improve Unit TestingAt <a href="http://www.testoften.com/">Test Often</a> Joe Ponczak lists seven metrics that you can use to make your methods more testable, <a href="http://www.testoften.com/2007/07/7-metrics-to-improve-your-unit-testing.html">"Seven Metrics to Improve Your Unit Testing"</a>. Experienced unit testers will probably be familiar with the metrics but it never hurts to review. I mainly mention this because it is the blog for <a href="http://codign.com/">CODIGN Software</a> which makes some nice reasonably priced Eclipse plug-ins for writing JUnit tests and analyzing code coverage.<br /><br />p.s. I sure don't like the white on black color scheme on the blog though.Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com0tag:blogger.com,1999:blog-3282860429230587868.post-788439784650896672007-09-04T19:43:00.001-05:002007-09-04T19:45:00.907-05:00What makes software so hard?<div xmlns="http://www.w3.org/1999/xhtml">Great article in the August issue of The Rational Edge, <a href="http://www.ibm.com/developerworks/rational/library/aug07/lennhamn/index.html">"What makes software so hard?"</a>. I have been <a href="http://rwhansen.blogspot.com/2007/08/michael-feathers-has-recent-blog-its.html">convinced</a> for some time that software is a design and not a manufacturing process. The article clearly describes the difference in explaining where in each type of process lie -<br /><blockquote>"On the other hand, for software projects, the relationship between<br />architecture and design versus production is not only inverted, but in<br />fact approaches infinity: since the production or manufacturing costs<br />for software are almost nil, almost all cost for a software<br />project comes from the workflows dealing with the creative parts --<br />that is, the invention and design of software." </blockquote>Another great quote is the author's comparison of software to writing a novel. The metaphor fits so well -<br /><blockquote>"In a sense, creating software is far more closely related to writing a novel than to any traditional engineering effort -- an author is free to construct whatever type of story, limited only by his imagination and whatever facts may be necessary to the narrative. Furthermore, the author must construct the architecture of the story in his head, and to make sure the design and implementation of the story is consistent with the overall architecture. The quality of the author's product is to a high degree based on whether he succeeds in keeping the details of the story consistent with the architecture."</blockquote>It is the notion that software is like manufacuring that has really turned me against big process improvement efforts like CMMi that are pushed from the top down. Anyone in a corporate environment has likely lived through at least one such effort. They usually seem so to be attempts to create predictability that does not exist in software and turn developers into interchangeable pieces that can be shuffled around a Gantt chart.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com5tag:blogger.com,1999:blog-3282860429230587868.post-57943925554086825232007-08-30T22:02:00.001-05:002007-09-19T19:49:21.938-05:00The Mysteries of Debugging?<div xmlns="http://www.w3.org/1999/xhtml">Why do so many programmers find debugging so hard? Sure there are exceptionally wicked bugs, but most of the time we make debugging harder than it needs to be. The only secret I know of is having the right attitude and using the right approach.<br /><br /><big><b><big>How Not to Debug</big></b></big><br /><br /><b>Trial and error</b><br /><br />Just guess at what the problem is. Add lots of print statements to the code and hope one of them shows you what the problem is. Make changes until the problem goes away. You don't need to know the cause as long as the bug is fixed.<br /><br /><b>Blame it on the ...</b><br /><br />That's impossible, certainly it can't be a mistake in my code. It must be the compiler, database, network, and so on and so on.<br /><br /><b>Don't Understand the Problem</b><br /><br />Don't dig deep enough to understand the cause. Fix the first and most obvious thing you find. Then fix the next most obvious thing when the same bug shows up again later.<br /><br /><b>Gentlemen Start Your Debuggers</b><br /><br />That's what the debugger is for so fire that sucker up and start stepping. We'll just step through every line of code until we find the bug. You've got nothing but time right?<br /><br /><br /><big><b><big>The Right Approach to Debugging</big></b><br /></big><br />First <a href="http://en.wikipedia.org/wiki/Don%27t_Panic_%28Hitchhiker%27s_Guide_to_the_Galaxy%29">don't panic!</a> Programming is about solving problems and a bug is just another problem to solve. Of course you must approach debugging in a logical and organized way. The first thing you need are some some clues. Using the clues you can develop a theory and tests to validate the theory. Once your theory is validated you can implement a fix. This is very similar to applying the <a href="http://en.wikipedia.org/wiki/Scientific_method">scientific method</a> :<br /><ol><li>Gather data</li><li>Form a hypothesis</li><li>Perform experiments that test the hypothesis</li><li>Prove or disprove the hypothesis</li><li>Rinse and repeat as needed</li></ol><big><b><big><br />Techniques for Successful Debugging</big></b></big><br /><br /><b>Repeatability</b><br /><br />You need to reliably reproduce the bug. If you can't reproduce it when needed you can't test it or know when it is fixed. Reproducing a bug can be the hardest part of debugging.<br /><br />Find the simplest test case that demonstrates the bug. You want to make it quick and easy because you will need to recreate the bug many times. The harder the bug is to recreate the less sure you will be of the cause and your solution. It is often worth the effort to create the smallest simplest program with the least code and clutter that shows the bug.<br /><br /><b>Analyze All the Available Data</b><br /><br />Before rushing into a theory about the cause of a bug you need to make sure you have completely analyzed all the data that you have about it. Don't jump to conclusions because your first instinct will often be wrong. Look at the problem from as many directions as possible first.<br /><br />Make sure you understand what the data is saying about the problem. We've got a great new technology called an exception that holds enough information all by itself to tell you the exact problem and the line of code where it occurred. Take the time to read and understand the full exception output. Time and gain I find myself pointing out to a programmer that the exception is telling them <i>exactly</i> what the problem is and all they need to do is read the exception output.<br /><br />Turn on as much application logging as possible and take the time to thoroughly examine the log or trace files. There are so many freely available open source, high quality, easy to use, logging and tracing frameworks available for every platform that there is no excuse for any application not to generate high quality error and debug logs.<br /><br /><b>Narrow Things Down </b><br /><br />Use a binary search or divide and conquer technique to zero in on the problem code. You need an organized hunting expedition not a haphazard ramble through the code to find bugs.<br /><br />Look at what has changed recently. If things worked fine last week then figure out what has changed in the code or its runtime environment and look there first.<br /><br /><b>Explain the Bug to Somebody Else</b><br /><br />When you aren't making any progress, stop, take a breath and find someone else to talk the problem over with. So often the simple act of explaining a problem generates an insight before you are even finished with the explanation. If just explaining things doesn't work then the other person may have a great idea of their own.<br /><br /><b>Fix the Real Problem</b><br /><br />The symptom you see may not be the actual bug. You need to find and fix the root cause not the symptom. Be sure you are fixing the problem and not just treating a symptom. When you find the problem look around for any similar problems. We all tend to make the same mistake more than once.<br /><br /><b>Write a Test Before You Fix</b><br /><br />First, The test will be a good demonstration of the bug and when the test succeeds it can be proof that the bug is fixed. Second, you just spent valuable time finding and fixing the bug and a test will help ensure that it does not come back to waste your time again.<br /><br /><b>The Compiler is Not Broken</b><br /><br />The compiler, database, wahtever is not broken. There could be bug there, but don't start from that assumption it will just waste time. Believe me it is not a bug in the compiler, compiler writers are way smarter than you or me.<br /><br /><b>One Change at a Time</b><br /><br />Never make more than one change before testing the bug again. If you make two changes how will you know which one fixed the bug and if which change is actually needed.<br /><br /><b>Check the Simplest Thing First</b><br /><br />Bugs are often caused by some silly mistake or oversight and the simple things are easy to check and fix. The unlikely things are hard to check, so save them for later.<br /><br /><b>Use the Debugger</b><br /><br />I saved this one almost for last because it should be a last resort. Debuggers are wonderful and powerful tools! But debuggers can also be tedious, time consuming, and confusing. Sometimes they are the only way to figure a problem out, but to use a debugger effectively you first need to narrow down the code that needs to be checked. Don't let the debugger be the first tool you reach for.<br /><br /><b>Use Tools to Find Bugs Before You Deploy</b><br /><br />The best way to fix a bug is to never let it get deployed. It should not be necessary to remind any programmer to turn on as many compiler warnings as possible, but unfortunately, I know it is. When you have all the compiler warnings removed from your code, run a static analysis tool aver it too. There are many open source and commercial code analysis tools available so get at least one and use it to analysis ALL of your code for bugs.<br /><br /><b><big>References</big></b><br /><br /><a href="http://www.amazon.com/gp/product/020161622X/ref=cm_arms_pdp_dp/104-3040781-0217522">"The Pragmatic Programmer: From Journeyman to Master"</a> by Andrew Hunt, David Thomas<br /><a href="http://www.amazon.com/Code-Complete-Second-Steve-McConnell/dp/0735619670/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&amp;amp;amp;amp;amp;amp;qid=1186105947&sr=1-1">"Code Complete"</a> by Steve McConnell<br /><a href="http://www.amazon.com/Practice-Programming-Addison-Wesley-Professional-Computing/dp/020161586X/ref=pd_bbs_sr_1/002-7139735-4598411?ie=UTF8&s=books&qid=1190249214&sr=1-1">"The Practice of Programming"</a> by Brian W. Kernighan, Rob Pike<br /><a href="http://faassen.n--tree.net/blog/view/weblog/2007/04/14/0">Debugging strategy: easy stuff first</a><br /><a href="http://www.pointy-stick.com/blog/2007/09/04/fix-bug-not-symptom/">Fix The Bug, Not The Symptom</a><br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com4tag:blogger.com,1999:blog-3282860429230587868.post-67033506553854337142007-08-28T17:25:00.001-05:002007-09-01T12:37:40.636-05:00New Application of the Builder Pattern<div xmlns="http://www.w3.org/1999/xhtml">At <a href="http://nat.truemesh.com/">"Mistaeks I Hav Made"</a> Nat Pryce writes about <a href="http://nat.truemesh.com/archives/000714.html">an alternative to the Object Mother pattern</a> that is based on the <a href="http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html">Builder pattern I blogged about previously.</a> It looks like a useful application of the Builder pattern. <a href="http://www.martinfowler.com/bliki/ObjectMother.html">Object Mother</a> is a technique for creating test data for unit tests. I've used Object Mothers and the article is right that overtime they get messy and bloated.<br /><br />In he last line of the article Nat says -<br /><blockquote><i>"In some cases, Builders have so improved the code that they ended up being used in the production code as well."</i></blockquote><br />Which is a nice validation of underlying the Builder pattern. I wonder if they used the same builder, complete with the default values, in the production code or wrote new ones.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com0tag:blogger.com,1999:blog-3282860429230587868.post-55679001513190934072007-08-27T17:49:00.001-05:002007-08-28T17:28:20.470-05:00Developer Testing is Habit Forming (and Habit Changing)<div xmlns="http://www.w3.org/1999/xhtml">A while back Tim Ottinger wrote a great article about how <a href="http://blog.objectmentor.com/articles/2007/07/17/testing-will-challenge-your-conventions">"Testing Will Challenge Your Conventions"</a>. Among the points that really hit home for me were -<br /><br /><ol><li>"Interfaces suddenly seem like a really good idea...". Mock objects can be so useful when used correctly that creating an interface is often the first thing I do.<br /></li><li>"Singletons and static methods no longer seem like a great way to do work...". As I hope everyone knows by now the Singleton pattern is way overrated and makes writing truly isolated unit tests very hard. </li><li>"Private makes less sense...". I still struggle with making a method public just for testing but sometimes there is no other way. Whenever I find the need to do so, I give my design a hard look to make sure it is as good as it should be.</li><li>"You need to be able to pass a class everything it might need at construction time...". To write isolated unit tests your classes cannot configure themselves. Of course long constructor parameter lists can be a problem but I can use the <a href="http://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.html">builder pattern</a> as one way to counter that.</li><li>"Smaller methods are the norm." When I think about the size of methods I write now compared to a few years ago I am amazed at how small the methods are now. It is getting to where I can't read or don't have the patience to read methods over 10 to 15 lines long.</li></ol>That's a few of my thoughts go read the whole things for yourself.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com4tag:blogger.com,1999:blog-3282860429230587868.post-51284352813622596322007-08-24T18:31:00.001-05:002007-08-25T16:21:58.059-05:00Discpline and Software Development<div xmlns="http://www.w3.org/1999/xhtml">Jeff Atwood writes over at <a href="http://www.codinghorror.com/blog/">Coding Horror</a> that <a href="http://www.codinghorror.com/blog/archives/000931.html">"Discipline Makes Strong Developers"</a>. Discipline is important and the best developers are certainly disciplined. But what sort of discipline are we actually talking about? Let's start with what sort of discipline we are not interested in -<br /><ul><li>Not imposed discipline.</li><li>Not about drill sergeants or enforcers.</li><li>Not about being able to code in low level languages like C or assembler.</li><li>Not about being anal-retentive.</li><li>While I have great respect for Watt's Humphrey, it's not about recording and reporting every minute detail of your work day.<br /></li></ul>Disciplined software development is about -<br /><ul><li>self-discipline</li><li>focus</li><li>attitude</li><li>approach</li><li>organization</li><li>responsibility and accountability </li></ul>This includes the having the discipline to -<br /><ul><li> write the unit tests</li><li> add the Java Doc comments</li><li> find the best name for a variable or method</li><li> leave the code better than you found it</li><li> fix problems not of your making</li><li> improve your skills</li><li> learn new things</li><li> keep the coding standards</li><li> use source control<br /></li><li>check-in changes frequently</li><li> run the units often</li><li> run the unit tests before every check-in</li><li> write a test for a bug before you fix it<br /></li><li> get your code reviewed<br /></li><li> fix the problem not just treat the symptom</li><li> keep code consistent</li></ul> As a technical lead I struggle with this. I have no desire to be the cop, but there can be too much bad code to ignore. One helpful option is automation. Use analysis tools to identify coding problems, violations of coding standards, and generate test coverage metrics. Automate your builds and do a nightly integration build or preferably a <a href="http://www.integratebutton.com/blog/">continuous integration</a> build after every change. Run the analysis as part of every integration build. Fail the build if there are to many violations and notify the development team of every failure.<br /><br />I think that ultimately it is up the individual developer to have pride in his or her work. I think the <a href="http://www.pragmaticprogrammer.com/ppbook/index.shtml">Pragmatic Programmers</a> said it best. A developer must "Care About Your Craft" and "Think! About Your Work".<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com4tag:blogger.com,1999:blog-3282860429230587868.post-18703145251004978852007-08-21T21:20:00.000-05:002007-08-25T16:22:13.480-05:00What is software design?Michael Feathers has a recent blog <a href="http://beautifulcode.oreillynet.com/2007/08/its_all_design.php">"It's All Design"</a> where he says:<br /><blockquote><p>When I think about what we do in software development, I find it hard to imagine similar things happening in other fields.<br /></p></blockquote>He goes on to speculate that an auto designer would never be given a requirement such as there must be fifteen drink holders. I think he's wrong and that we operate in the same way as in many other fields. Come on, there really are vehicles with fifteen cup holders and I can't imagine any auto designer doing that without such a requirement.<br /><br />In the comments Michael says "I try to imagine what happens in conversations with architects.". Well my wife has a degree in Architecture, but worked in the field only briefly before moving into software development. She has found great parallels between the work in both fields. We are currently working with an architect to design an addition to our house and one of the first things our architect did was ask about any features and requirements we had in mind.<br /><br />Don't get me wrong, I agree that software development is just one big design process. I really hate how the software development process is so often compared to a manufacturing process. In software the manufacturing is not the development of an application it is copying that application to a disk. What we do, even the lowest level coding, is design not manufacturing.<br /><br />But I don't agree with Michael Feathers that requirements and design are the same thing:<br /><blockquote><p>Maybe requirements is just a word that we use because we're dividing our design work between two groups.. a group that determines the higher level design (what the product will do); and the lower level design (how the product will do it).<br /></p></blockquote>Requirements frame design but are the same as design. Something like a performance requirement does not say anything about the design of a product. Software development is a design process and requirements are part of the process, but a stating a requirement is not the same as making a design decision.Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com2tag:blogger.com,1999:blog-3282860429230587868.post-4377424262405311142007-08-16T17:18:00.001-05:002007-08-25T16:22:30.738-05:00"Mocks Aren't Stubs" Revisited<div xmlns="http://www.w3.org/1999/xhtml">Reading the book <a href="http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Addison-Wesley/dp/0131495054/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;qid=1187138662&sr=8-1">"xUnit Test Patterns: Refactoring Test Code"</a> made me take another look at Martin Fowler's 2004 article <a href="http://martinfowler.com/articles/mocksArentStubs.html">"Mocks Aren't Stubs"</a>. I'm glad I did because the article has been significantly updated (it's practically a rewrite and nearly twice as long) to reflect new thinking about mock objects. The first thing I noticed was the new terminology that is consistent with the "xUnit Test Patterns" book. The second thing I noticed is the new ideas about the different styles of using mock objects. The updated article is definitely worth a read or a re-read.<br /><br />It looks like we are beginning to develop a shared language around unit testing, like what happened with refactoring and design patterns. It's interesting to watch this kind of thing as it matures and we learn more. It reminds we of how much object oriented development has changed over the last twenty years.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com5tag:blogger.com,1999:blog-3282860429230587868.post-21310181254529932502007-08-14T21:43:00.001-05:002007-09-01T12:42:40.108-05:00Java Mock Object Frameworks Reviewed<div xmlns="http://www.w3.org/1999/xhtml">I've been reading the book <a href="http://www.amazon.com/xUnit-Test-Patterns-Refactoring-Addison-Wesley/dp/0131495054/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;qid=1187138662&sr=8-1"><b>"xUnit Test Patterns: Refactoring Test Code"</b></a> so you are going to get a few posts on unit testing. The book is huge, 27 chapters and 944 pages, and packed with useful information. This clearly was no hastily compiled book, the author has invested a lot time and effort. The book has a website <a href="http://xunitpatterns.com/">here</a>. Right now I'm reading the chapter on "Test Doubles", what you and I would probably call mock objects, but the author classifies into five types: Dummy Object, Test Stub, Test Spy, Mock Object, and Fake Object. The classification is sensible and really makes you think about how you use mocks and stubs. I've been using mock objects for years and never really thought that much about it.<br /><br />Despite using mock objects for years, I haven't kept up with the the mock objects frameworks. Until recently I've been using the original static mockobjects.com libraries and had not tried any of the dynamic mock frameworks like DynaMock, <a href="http://www.easymock.org/">EasyMock</a>, or <a href="http://www.jmock.org/">jMock</a>. I've finally gotten tried of writing custom mock objects and decided ti was time to try something new. Over the last couple weeks I've been testing EasyMock, jMock, and <a href="http://rmock.sourceforge.net/">rMock</a>. So here are my thoughts on the those frameworks.<br /><br /><b><big>EasyMock 1 (Java 1.3 or 1.4)</big></b><br /><br />EasyMock uses recording to set expectations. A mock instance is created and the expected method calls are specified by method calls with the expected parameters.<br /><ul><li>Documentation is decent and better than other v1 kits.<br /></li><li>Includes a tutorial with source code.</li><li>Generally seems simpler than the others to understand.</li><li>Some extra code, instances of the control and mock instance for each mock.</li><li>Need calls to the replay and verify methods for each mock used in a test.</li><li>Recording expectations using actual method calls is an easy to understand metaphor.</li><li>Specifying return values is not so easy to understand. I thought it clashed with the recording model. The inconsistencies with the model of recording of expectations makes things harder.<br /></li><li>Had to record method calls, using null values, even when I did not care about what parameters were used to invoke a method. It seems like this would make it harder for someone else to understand the intent of the test.<br /></li><li>Less proxy casting than jMock, but two variables are needed for each mock. Need the mock and a a reference to the interface that the mock implements.</li><li>Tests extend standard JUnit TestCase.<br /></li></ul> <b><big>jMock 1 (</big></b><b><big>Java 1.3 or 1.4</big></b><b><big>)</big></b><br /><br />jMock uses expectation specification and essentially implements it's own little language for setting expectations on a mock.<br /><ul><li>Documentation is ok, but could be better. There are lots of classes so it can be hard to figure out where to look for something in the Java Doc. The tutorial is not included in the download. There is no full example with source code.</li><li>jMock Usage is very consistent across all aspects of setting expectations and return values.</li><li>Expectation definition at first seems verbose, but needs fewer lines of code than EasyMock. Expectations and return values are specified together which can make them easier to read and understand.<br /></li><li>Method names are specified as strings and may hamper refactoring.<br /></li><li>Casting proxies is annoying.</li><li>Tests must extend MockObjectTestCase.<br /></li></ul> <b><big>rMock 2 (Java 1.3 and up)</big></b><br /><br />rMock follows the same model of recording expectations as EasyMock.<br /><ul><li>Quite a bit of documentation, but it was not as useful. Had to generate my own Java Doc. No source code examples are included.<br /></li><li>This framework seems to want to totally redefine how unit tests are written. It implements a whole new assert framework which I found confusing, but it does work with JUnit.</li><li>No advantage over EasyMock.</li><li>No special support for JUnit 4 features or Java 5+.</li><li>Tests must extend RMockTestCase.<br /></li></ul> <b><big>EasyMock 2 (Java 5 and up)</big></b><br /><br />This is a nice upgrade from version 1.<br /><ul><li>Documentation the same quality as version 1. Includes a tutorial with source code.</li><li>Much improved over version 1.</li><li>Less code than version 1, no control objects, no proxy casting.</li><li>Does require static imports for the cleanest looking code. More static imports than jMock.<br /></li><li>Still requires calls to replay and verify methods for every mock in a test.<br /></li><li>Still relatively the simplest to understand.</li><li>Same inconsistencies in the model between recording expectations and setting return values as the previous version.</li><li>Tests extend standard JUnit TestCase.<br /></li></ul> <b><big>jMock 2 </big></b><b><big>(Java 5 and up)</big></b><br /><br />This is a significant upgrade that I found much easier to use.<br /><ul><li>Documentation is better. The tutorial is not included in the download. Still no full source code examples.<br /></li><li>Less code, no proxy casting.</li><li>Does require static imports for the cleanest looking code.</li><li>Model is more consistent and simpler.</li><li>The syntax of expectation setup needs a little getting used to.</li><li>All mock variables must be declared final.</li><li>Seems to have the best features of record and play back without the inconsistencies.</li><li>Tests no longer have to extend MockObjectTestCase. Extending MockObjectTestCase is probably still the easiest thing for JUnit 3.<br /></li></ul>While I prefered JMock, EasyMock is also an excellent framework. Either jMock or EasyMocl would be a good choice. I do not recommend rMock. The choice between EasyMock or jMock will come down to personal preference and perhaps the skills of your developers. I think the slightly steeper learning curve of jMock is worth it for the consistency of its model. I was pleasantly surprised at how much easier jMock 2 was to use over jMock 1.<br /></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com3tag:blogger.com,1999:blog-3282860429230587868.post-35967151214000911202007-08-10T17:43:00.000-05:002007-08-15T17:50:08.692-05:00New Version of Cobertura Code Coverage Tool Released<span style="font-size:100%;">This is not exactly new, but version 1.9 of <a href="http://cobertura.sourceforge.net/">Cobertura</a> is available. It's not a big update but is worth getting just for the improvements to the branch coverage reporting. I found the branch coverage of no use at all prior to the 1.9 release. Now it is one of the best features. Instead of marking an "if" statement as 100% covered when the "if" block was never entered, Cobertura now requires all conditions to be tested for 100%. The html report even has a nice context popup that tells exactly how many conditions have been tested.<br /><br />Version 1.9 is a seamless upgrade. I was able to drop it into our builds without any changes to the Ant scripts.<br /><br /><br /> </span>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com0tag:blogger.com,1999:blog-3282860429230587868.post-78308802997979904912007-08-03T20:43:00.001-05:002007-08-15T17:50:26.017-05:00Recommended Books<div xmlns="http://www.w3.org/1999/xhtml">Here is a list of the top books on various software development topics I recommend. Believe it or not, I've read all but one or two of them, which should give you a hint as to how long I have been doing this.<br /><br /><span style="font-size:180%;">Design<br /></span><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Object-Design-Roles-Responsibilities-Collaborations/dp/0201379430/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;qid=1185492396&sr=8-1">"Object Design: Roles, Responsibilities, and Collaborations"</a></span><br /><i> by Rebecca Wirfs-Brock, Alan McKean</i><br /><br />This is one of the best books on object oriented design you will find. This books focuses is on using approach to object oriented design.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1185492554&sr=1-1">"Domain-Driven Design: Tackling Complexity in the Heart of Software"</a></span><br /><i> by Eric Evans</i><br /><br />This is an amazing book and still a favorite. This book explains how to model the problem domain knowledge and create a ubiquitous domain language.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Object-Thinking-DV-Microsoft-Professional-David/dp/0735619654/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1185493040&sr=1-1">"Object Thinking"</a></span><br /><i> by David West</i><br /><br />This is a quirky book and I suspect it won't be to everyone's liking. But for serious OO designers it is well worth reading and full of thought provoking ideas and opinions.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Head-First-Object-Oriented-Analysis-Design/dp/0596008678/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186018707&sr=8-1">"Head First Object-Oriented Analysis and Design: A Brain Friendly Guide to OOA&D"</a></span><br /><i> by Brett D. McLaughlin, Gary Pollice, Dave West</i><br /><br />A gentle and entertaining introduction to the subject. This book will is mainly aimed at novice designers and will probably bore more experienced developers.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&amp;qid=1186019175&sr=1-1">"Design Patterns: Elements of Reusable Object-Oriented Software"</a></span><br /><i>by Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides</i><br /><br />What is left to say about the book that started the design patterns movement other than every serious developer should read this book at least twice. Just please ignore the Singleton pattern.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Software-Development-Principles-Patterns-Practices/dp/0135974445/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186019299&sr=1-1">"Agile Software Development, Principles, Patterns, and Practices"</a></span><br /><i> by Robert C. Martin</i><br /><br />A great book with lots of example code that really lays out some key OO design principles such as DRY (Don't Repeat Yourself). Though I thought the bowling example was a bit weak and I told Robert Martin so.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/UML-Distilled-Standard-Modeling-Language/dp/0321193687/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186019361&sr=1-1">"UML Distilled: A Brief Guide to the Standard Object Modeling Language, (3rd Edition)"</a><br /><i> by Martin Fowler</i></span><br /><br />You won't find a simpler, shorter, or more readable introduction to UML anywhere.<br /><br /><span style="font-size:180%;">Development</span><br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186019450&sr=1-1">"The Mythical Man-Month: Essays on Software Engineering"</a></span><br /><i> by Frederick P. Brooks</i><br /><br />Who would have thought this book would still ring true after so many years. This is a classic that you really ought to read.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Extreme-Programming-Explained-Embrace-Change/dp/0321278658/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186019497&sr=1-1">"Extreme Programming Explained: Embrace Change, (2nd Edition)"</a></span><br /><i> by Kent Beck, Cynthia Andres<br /><br /></i>Kent Beck is arguably the leading voice for agile development and this is the book that started it all. A must read for any anyone interested in agile software development. Sadly, so far I've only read the first edition.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Lean-Software-Development-Toolkit-Managers/dp/0321150783/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186019835&sr=1-1">"Lean Software Development: An Agile Toolkit for Software Development Managers"</a><br /></span><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Implementing-Lean-Software-Development-Addison-Wesley/dp/0321437381/ref=pd_bbs_sr_2/104-3040781-0217522?ie=UTF8&s=books&qid=1186019835&sr=1-2">"Implementing Lean Software Development: From Concept to Cash"</a></span><br /><i> by Mary Poppendieck, Tom Poppendieck</i><br /><br />Having trouble convincing your management that agile software development makes sense? If these two books don't help then nothing will.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Waltzing-Bears-Managing-Software-Projects/dp/0932633609/ref=sr_1_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186021437&sr=1-1">"Waltzing With Bears: Managing Risk on Software Projects"</a></span><br /><i> by Tom Demarco, Timothy Lister</i><br /><br />Another classic that still works. If you only read one book on software project risk this should be it.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Software-Configuration-Management-Patterns-Integration/dp/0201741172/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186021604&sr=1-1">"Software Configuration Management Patterns: Effective Teamwork, Practical Integration"</a></span><br /><i> by Stephen P. Berczuk, Brad Appleton</i><br /><br />This book will help you move beyond simple check-in an check-out to managing your project's artifacts. It explains the proven SCM patterns and practices needed to succeed.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Pragmatic-Version-Control-Using-CVS/dp/0974514004/ref=sr_1_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186105729&sr=1-1">"Pragmatic Version Control Using CVS"</a></span><br /><i> by Dave Thomas, Andy Hunt</i><br /><br />An excellent concise introduction to version control in general and CVS in particular. This is a great book for the new or inexperienced version control user.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Continuous-Integration-Improving-Addison-Wesley-Signature/dp/0321336380/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186021705&sr=1-1">"Continuous Integration: Improving Software Quality and Reducing Risk"</a></span><br /><i> by Paul Duvall</i><br /><br />This is a very good book. Ever since Martin Fowler's seminal article on the subject we've badly needed this book. I only wish it had been written a couple years earlier. This book will be most useful to those new to the concepts of "Continuous Integration".<br /><br /><span style="font-size:180%;">Programming</span><br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186023883&sr=1-1">"Refactoring: Improving the Design of Existing Code"</a></span><br /><i>by Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts</i><br /><br />This is the bible on refactoring. If have not read this book and think you practice "refactoring" then think again. Refactoring, along with unit testing, are key techniques of agile development.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Refactoring-Patterns-Addison-Wesley-Signature-Kerievsky/dp/0321213351/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186024232&sr=1-1">"Refactoring to Patterns"</a></span><br /><i>by Joshua Kerievsky</i><br /><br />This book is about using patterns to improving existing designs of existing code bases.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/gp/product/020161622X/ref=cm_arms_pdp_dp/104-3040781-0217522">"The Pragmatic Programmer: From Journeyman to Master"</a></span><br /><i>by Andrew Hunt, David Thomas </i><br /><br />This is a must read for every programmer. It is full of all sorts of techniques for improving your craft. Ever wonder why the best programmers are 10 or 20 times more productive? It's probably because they are already use the techniques in the book.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Working-Effectively-Legacy-Robert-Martin/dp/0131177052/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186105509&sr=1-1">"Working Effectively with Legacy Code"</a></span><br /><i>by Michael Feathers</i><br /><br />Strategies for fixing that crusty old untested legacy code.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Code-Complete-Second-Steve-McConnell/dp/0735619670/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186105947&sr=1-1">"Code Complete"</a></span><br /><i>by Steve McConnell</i><br /><br />I first read this book twenty years ago. The newest edition is just as good a guide to the why and how of writing great code as the original. This should be on every programmer's bookshelf.<br /><br /><span style="font-size:180%;">Java Programming</span><br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Pragmatic-Unit-Testing-Java-JUnit/dp/0974514012/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186106099&sr=1-1">"Pragmatic Unit Testing in Java with JUnit"</a></span><br /><i> by Andy Hunt, Dave Thomas</i><br /><br />You won't find a better tutorial on unit testing or JUnit. Give this book to any programmer new to developer testing.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Effective-Java-Programming-Language-Guide/dp/0201310058/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186106251&sr=1-1">"Effective Java Programming Language Guide"</a></span><br /><i> by Joshua Bloch</i><br /><br />Every Java programmer must read this book! Any Java programmer that hasn't should not be allowed anywhere near a Java compiler.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Java-Generics-Collections-Maurice-Naftalin/dp/0596527756/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186106492&sr=1-1">"Java Generics and Collections"</a></span><br /><i> by Maurice Naftalin, Philip Wadler</i><br /><br />A clear guide to a tough subject. I think everyone will learn at least one new thing.<br /><br /><span style="font-size:130%;"><a href="http://www.amazon.com/Thinking-Java-4th-Bruce-Eckel/dp/0131872486/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186179460&sr=8-1">"Thinking in Java (5th Edition)"</a></span><br /><i> by Bruce Eckel</i><br /><br /><span style="font-size:180%;">Architecture<br /></span><span style="font-size:130%;"><br /><a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=pd_bbs_sr_1/104-3040781-0217522?ie=UTF8&s=books&qid=1186179574&sr=1-1">"Patterns of Enterprise Application Architecture"</a></span><br /><i> by Martin Fowler</i><br /><br /><a href="http://www.amazon.com/Enterprise-Integration-Patterns-Designing-Addison-Wesley/dp/0321200683/ref=pd_bxgy_b_img_b/104-3040781-0217522?ie=UTF8&amp;qid=1186179574&sr=1-1">"Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions"</a><br /><i> by Gregor Hohpe, Bobby Woolf</i></div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com0tag:blogger.com,1999:blog-3282860429230587868.post-85513211571306933042007-07-20T18:21:00.001-05:002007-08-15T17:49:19.197-05:00Java Dates, Calendars and TimeZones<div xmlns="http://www.w3.org/1999/xhtml">We all know Java date handling is a pain. I'm sure most Java developers give as little thought as possible to dates, less to calendars, and none to time zones. We use <code> new java.util.Date()</code> as much as possible and avoid <code>java.util.Calendar</code> like the plague. This works out, more or less, until you need to account for time zones. Java dates don't include any time zone related methods so it's easy to ignore them, we forget that dates really have a time zone of Greenwich Mean Time (GMT).<br /><br />The thing to remember is that a Java date is a very simple object . If you remove the deprecated constructors and methods there is not much left besides <code>equals(), hashCode()</code> and <code>getTime()</code>. A date is really just a wrapper around a Java long integer value and that long integer is the number of milliseconds since January 1, 1970, 00:00:00 GMT. We forget about the GMT business because whenever we print a date it looks like this -<br /><br />Sun Jul 15 10:00:00 CDT 2007<br /><br />It is easy to forget that the output of <code>toString()</code> is the value of the date in a localized format for display and not the real value. The same date printed in two different time zones would look different even though the actual long integer value is the same. Here is an example that may help -<br /><pre><code><br />import java.util.Calendar;<br />import java.util.Date;<br />import java.util.GregorianCalendar;<br />import java.util.TimeZone;<br /><br />public class CalendarTimeZoneTest {<br />private static String getCalendarDate(Calendar cal) {<br /> return (cal.get(Calendar.MONTH) + 1) + "/" +<br /> cal.get(Calendar.DAY_OF_MONTH) + "/" +<br /> cal.get(Calendar.YEAR) + " " +<br /> cal.get(Calendar.HOUR_OF_DAY) + ":" +<br /> cal.get(Calendar.MINUTE) + ":" +<br /> cal.get(Calendar.SECOND);<br />}<br /><br />private static Calendar getCalendarForTimeZone(TimeZone tz) {<br /> Calendar cal = new GregorianCalendar(tz);<br /> cal.clear();<br /> cal.set(Calendar.HOUR_OF_DAY, 10);<br /> cal.set(Calendar.MINUTE, 0);<br /> cal.set(Calendar.SECOND, 0);<br /> cal.set(Calendar.MONTH, 6);<br /> cal.set(Calendar.YEAR, 2007);<br /> cal.set(Calendar.DAY_OF_MONTH, 15);<br /> return cal;<br />}<br /><br />private static void showDate(Calendar Cal) {<br /> System.out.println(" Time zone : " +<br /> Cal.getTimeZone().getDisplayName());<br /> System.out.println(" Milliseconds : " +<br /> Cal.getTimeInMillis());<br /> System.out.println(" Calendar Date: " +<br /> getCalendarDate(Cal));<br /> System.out.println(" Local Date : " +<br /> new Date(Cal.getTimeInMillis()));<br /> System.out.println();<br />}<br /><br />public static void main(String[] args) {<br /> Calendar localCal =<br /> getCalendarForTimeZone(TimeZone.getTimeZone("America/Chicago"));<br /> Calendar japanCal =<br /> getCalendarForTimeZone(TimeZone.getTimeZone("Japan"));<br /> System.out.println("Same date/time in different time zones");<br /> showDate(localCal);<br /> showDate(japanCal);<br /> System.out.println();<br /><br /> japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));<br /> japanCal.setTimeInMillis(localCal.getTimeInMillis());<br /> System.out.println("Same milliseconds in different time zones");<br /> showDate(localCal);<br /> showDate(japanCal);<br />}<br /></code></pre><br />First the example creates two calendars with the same date and time for two different time zones. This results in two dates with different millisecond values. Next, the example creates two calendars with the same milliseconds in two different time zones. The output looks like -<br /><pre><br />Same date/time in different time zones<br />Time zone : Central Standard Time<br />Milliseconds : 1184511600000<br />Calendar Date: 7/15/2007 10:0:0<br />Local Date : Sun Jul 15 10:00:00 CDT 2007<br /><br />Time zone : Japan Standard Time<br />Milliseconds : 1184461200000<br />Calendar Date: 7/15/2007 10:0:0<br />Local Date : Sat Jul 14 20:00:00 CDT 2007<br /><br /><br />Same milliseconds in different time zones<br />Time zone : Central Standard Time<br />Milliseconds : 1184511600000<br />Calendar Date: 7/15/2007 10:0:0<br />Local Date : Sun Jul 15 10:00:00 CDT 2007<br /><br />Time zone : Japan Standard Time<br />Milliseconds : 1184511600000<br />Calendar Date: 7/16/2007 0:0:0<br />Local Date : Sun Jul 15 10:00:00 CDT 2007<br /></pre><br />What I hope the example demonstrates is that the same Java date, i.e. millisecond value, has different meanings in different time zones. If you want the same date and time in different time zones you must take the offset between time zones into account. The easiest way to do this using the standard Java libraries is to create a date from its parts, year, month, day, etc., using a Java calendar object.</div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com3tag:blogger.com,1999:blog-3282860429230587868.post-1476854792272116602007-07-15T19:04:00.001-05:002007-08-15T17:49:19.197-05:00Lazy Initialization Using an On Demand Holder<div xmlns="http://www.w3.org/1999/xhtml">I was reminded of the "On Demand Holder" idiom the other day. If you're not familiar with it, the idiom is a thread safe replacement for lazy initialization using double checked locking. As we all know <a href="http://www.cs.umd.edu/%7Epugh/java/memoryModel/DoubleCheckedLocking.html">double checked locking is broken.</a> Here is an example implementation -<br /><pre><code>public class Something {<br />private Something() { }<br /><br />private static class Holder {<br /> private static final Something instance = new Something();<br />}<br /><br />public static Something getInstance() {<br /> return Holder.instance;<br />}<br />}<br /></code></pre><br />This works because of the way classes are loaded. The inner class Holder is not loaded and initialized until a thread references it, so the static instance of Something is not created until the first time that the getInstance() method is called. Here is more information and references for <a href="http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom">"On Demand Holder"</a>.</div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com6tag:blogger.com,1999:blog-3282860429230587868.post-29447998463858734272007-07-14T11:27:00.001-05:002007-07-14T11:32:06.317-05:00Programmer Personality Test<div xmlns="http://www.w3.org/1999/xhtml">Here's a link to an interesting <a href="http://www.doolwind.com/index.php?page=11">"Programmer Personality Test"</a>. If you've ever taken a Meyers-Briggs test, then the test should be familiar. It's short, painless, and worth taking if just for the entertainment value. You might learn something and it could spark interesting discussions with your teammates. A test like this could be useful as part of the hiring process, but this one is short and I'm not sure how accurate it is.</div>Richard Hansenhttp://www.blogger.com/profile/16660904790879456310noreply@blogger.com3