<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3653104956070157954</id><updated>2011-09-23T14:03:56.200-05:00</updated><category term='ruby'/><category term='javascript jquery'/><category term='agile'/><category term='struts'/><category term='java'/><category term='process'/><category term='consulting'/><category term='software engineering'/><category term='software design'/><category term='unit-testing'/><category term='productivity'/><category term='teams'/><category term='SWT'/><title type='text'>Developing good software well</title><subtitle type='html'>Observations, experiences, thoughts and ramblings about the process of creating software.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-4155283185038115784</id><published>2011-07-22T05:06:00.002-05:00</published><updated>2011-07-22T05:29:38.640-05:00</updated><title type='text'>From Months to Minutes</title><content type='html'>&lt;p&gt;I found &lt;a href="http://www.infoq.com/presentations/From-Months-to-Minutes"&gt;another presentation on InfoQ&lt;/a&gt;, this time by Dan North. In it, he puts many Agile practices through the wringer, and turns them inside out and on their head. Dan questions why we do them, what they do for us, and offers pointers on how to intelligently apply them to become a high performing team.&lt;/p&gt;

&lt;p&gt;It's a great and very fast-paced discussion, and it got me thinking a lot about what I do and what I recommend to my teams.&lt;/p&gt;

&lt;p&gt;My favorite parts, which are also the most important steps to effectively delivering software, is about the need for one team. In his case, he talks of developers working side by side with traders. He talks about how the developers know as much about trading as the traders do, having learned this by spending time talking with the traders while they work making trades. There is no difference between the business and the engineers. It's one team, consisting of both engineers and traders.&lt;/p&gt;

&lt;p&gt;He also talks about minimizing boundaries and hand-offs, particularly &lt;em&gt;within the team&lt;/em&gt;. The team does not have members who are analysts, QA's, DBA's, etc. Those roles exist, and are filled by the team members as needed. Particularly, the developers are the ones talking to the traders about features. There is no handoff from customer to analyst to designer to developer. The developers talk directly with the traders, and then implement the features. There is no loss of fidelity; the message does not have a chance to be misunderstood. This is helped by the fact that the traders and developers work together.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-4155283185038115784?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/4155283185038115784/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2011/07/from-months-to-minutes.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4155283185038115784'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4155283185038115784'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2011/07/from-months-to-minutes.html' title='From Months to Minutes'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-7978851775142875156</id><published>2011-07-21T16:08:00.008-05:00</published><updated>2011-07-21T17:04:20.250-05:00</updated><title type='text'>Craft and Software Engineering</title><content type='html'>&lt;p&gt;
Glenn Vanderburg has a &lt;a href="http://www.infoq.com/presentations/Craft-and-Software-Engineering"&gt;great presentation available on InfoQ&lt;/a&gt; titled &lt;em&gt;Craft and Software Engineering&lt;/em&gt;. In it, he describes where Software Engineering came from, some of the fallacies, and a direction to make it more like other Engineering disciplines. It's a great talk and moves quite well through the content. I'd recommend it to anyone involved in software development.
&lt;/p&gt;

&lt;p&gt;One of the things he talks about is feedback, and how the different XP provide feedback at different levels of granularity, and at different timescales. He also discusses this in his 2005 paper &lt;em&gt;&lt;a href="http://vanderburg.org/Writing/xpannealed.pdf"&gt;XP Annealed&lt;/a&gt;&lt;/em&gt;. Here's what this looks like in a table:&lt;/p&gt;

&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;
            &lt;th&gt;XP Practice&lt;/th&gt;
            &lt;th&gt;Feedback&lt;/th&gt;
            &lt;th&gt;Timeframe&lt;/th&gt;
        &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;
            &lt;td&gt;short releases&lt;/td&gt;
            &lt;td&gt;solutions&lt;/td&gt;
            &lt;td&gt;months&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;planning game&lt;/td&gt;
            &lt;td&gt;priorities&lt;/td&gt;
            &lt;td&gt;weeks&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;acceptance testing&lt;/td&gt;
            &lt;td&gt;features&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;collective ownership&lt;/td&gt;
            &lt;td&gt;architecture&lt;/td&gt;
            &lt;td&gt;days&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;on-site customer&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;continuous integration&lt;/td&gt;
            &lt;td&gt;design&lt;/td&gt;
            &lt;td&gt;hours&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;system metaphor&lt;/td&gt;
            &lt;td&gt;classes and interfaces&lt;/td&gt;
            &lt;td&gt;minutes&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;unit testing&lt;/td&gt;
            &lt;td&gt;statements and methods&lt;/td&gt;
            &lt;td&gt;seconds&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
            &lt;td&gt;pair programming&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
            &lt;td&gt;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;In his paper, he goes on to describe how the nested levels of feedback are effective and &lt;em&gt;efficient&lt;/em&gt; because the practices support each other, and cover for each other. Each practice, at each level of granularity and timeframe, covers and is covered by nearby practices.&lt;/p&gt;

&lt;p&gt;Observation: The feedback can be broadly classified as technical at the lower levels, and business at the higher levels. Taken broadly, there are only two types of roles needed to implement the project. Technical (developers) to work out the design and testing, and business (non-technical) to provide the vision, the priorities and acceptance criteria.&lt;/p&gt;

&lt;p&gt;Taking it one step further, putting these people together, as one collocated team, would be the most effective way to facilitate this communication. Nothing original here, but it seems to be a natural progression. It minimizes the number of hops that need to happen for any communication.&lt;/p&gt;

&lt;p&gt;That's not to say there is no room for specialists, for things such as the environment, deployment, acceptance testing, UI design, and so on. However, they should all be part of the same collocated team.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-7978851775142875156?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/7978851775142875156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2011/07/craft-and-software-engineering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7978851775142875156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7978851775142875156'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2011/07/craft-and-software-engineering.html' title='Craft and Software Engineering'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-2067634230199791064</id><published>2011-05-13T12:01:00.001-05:00</published><updated>2011-05-13T12:01:59.425-05:00</updated><title type='text'>Learning Apache and Linux</title><content type='html'>&lt;p&gt;A co-worker asked me if I knew any good books where he could read up on using Apache and Linux. I thought for a second, and quickly answered “Nope, not a one.”&lt;/p&gt;

&lt;p&gt;“Oh!”, he said, looking somewhat dejected. Well, neither of us were looking for that response.&lt;/p&gt;

&lt;p&gt;Then I had an idea. “Why a book? Just get a &lt;em&gt;slice&lt;/em&gt; and just practice. It’ll probably be cheaper than a book, and you’ll learn more.”  &lt;/p&gt;

&lt;p&gt;After planting that idea, I went looking at what it would really take. I was close.&lt;/p&gt;

&lt;h3&gt;Get a &lt;em&gt;slice&lt;/em&gt;&lt;/h3&gt;

&lt;p id="scroll_to_here"&gt;I checkout out what &lt;a href="http://www.slicehost.com"&gt;Slicehost&lt;/a&gt; was offering. For $20/month, you can get a linux instance with 256MB of memory, 10GB of disk. Not bad, but that seemed a little pricey to me. I kept looking.&lt;/p&gt;

&lt;p&gt;I didn’t have to go far. Slicehost is owned by &lt;a href="http://www.rackspace.com/cloud/cloud_hosting_products/servers/pricing/"&gt;Rackspace&lt;/a&gt;, which offers the same instance for about $10.95/month. You’re only charged for the time your server is running, so you could bring it offline to save some dough.&lt;/p&gt;

&lt;h3&gt;Not very original&lt;/h3&gt;

&lt;p&gt;The idea of learning as you go on your own virtual instance wasn’t very original — Slicehost was promoting the same idea right on their &lt;a href="http://www.slicehost.com/questions/#noob"&gt;faq&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;h4&gt;I’m kind of new to this, will it be too hard?&lt;/h4&gt;
  
  &lt;p&gt;Maybe. Our Slices are full distros with root access. Many people coming from shared hosting are used to a cPanel type control system and limited shell access. We’re geared for people who want to start from scratch and tune a system for their purposes. However, everyone has to start somewhere. A 256slice is a great place to cut your teeth on building production boxes from scratch. Tweak, explore, learn. If you screw up, login to SliceManager and restart the box. If you really screw up, login and reinstall ;). You’ll be a Linux guru in no time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;Now what?&lt;/h3&gt;

&lt;p&gt;So you got a slice. How do you start? This is where the options (and opportunities) are endless. The key point would be to start playing and see how far you can get. And maybe O’Reilly’s &lt;a href="http://www.onlamp.com"&gt;Lamp&lt;/a&gt; could help as an initial resource.&lt;/p&gt;

&lt;p&gt;Some ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;a href="http://httpd.apache.org/"&gt;Apache&lt;/a&gt; and get a static website deployed.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="http://www.php.net/"&gt;PHP&lt;/a&gt;, &lt;a href="http://www.perl.org/"&gt;Perl&lt;/a&gt; or &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt; and get a dynamic website going.&lt;/li&gt;
&lt;li&gt;Install a database, maybe &lt;a href="http://www.postgresql.org/"&gt;Postgres&lt;/a&gt; or &lt;a href="http://www.mysql.com/"&gt;MySQL&lt;/a&gt;. Develop an deploy a small application.&lt;/li&gt;
&lt;li&gt;Install &lt;a href="http://www.ruby-lang.org/en/"&gt;Ruby&lt;/a&gt; and deploy a &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt; or Rails application.&lt;/li&gt;
&lt;li&gt;For the advanced — install and use another datastore, like &lt;a href="http://redis.io/"&gt;redis&lt;/a&gt; or &lt;a href="http://www.mongodb.org/"&gt;mongoDB&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;For extra credit — deploy several applications together on the same host.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-2067634230199791064?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/2067634230199791064/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2011/05/learning-apache-and-linux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2067634230199791064'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2067634230199791064'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2011/05/learning-apache-and-linux.html' title='Learning Apache and Linux'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-7666561071891198618</id><published>2010-12-02T23:47:00.010-06:00</published><updated>2010-12-02T23:59:32.795-06:00</updated><title type='text'>Thin, valuable features</title><content type='html'>&lt;p&gt;
You're on a team developing an e-commerce site for a traditional retailer. The product owner has a great idea about the Store Locator feature. As you start to discuss this story, you start to wonder how many ITERATIONS it will take you to develop the functionality. 
&lt;/p&gt;
&lt;p&gt;
Users can search for a store by zip code or city and state. The five closest stores will be displayed with their address, phone number and store hours. A map will be displayed showing the five closest stores, with the ability to zoom in and out. Finally, the search results will also show the regional managers name, phone number, email and picture. Oh, and if the user is logged in, lets pre-fill their address to search.
&lt;/p&gt;
&lt;h3&gt;Too much at once&lt;/h3&gt;
&lt;p&gt;
After thinking about this "story" or "feature", you decide that it's too much work for one pair to complete in a week, and might even be too much to complete in two weeks. What can you do? You think about breaking it up so that you complete the domain models and services in the first week, and then the user interface during the second week. This could work, but there are a few problems with this approach. 
&lt;/p&gt;
&lt;p&gt;
First, will the models that you develop during the first week be sufficient to complete the user interface without changes? Will they have enough functionality, and will the functionality be correct?
&lt;/p&gt;
&lt;p&gt;
Second, what will tell your product owner when he asks how the story is going? Will you give say that you're 40% done? If you are 40% done, when will you be all done? More importantly, will you be able to show any functionality along the way? 
&lt;/p&gt;
&lt;p&gt;
Finally, if someone offers to help with this story, will you be able to hand-off any tasks? Can any of the work be done in parallel?
&lt;/p&gt;
&lt;p&gt;
Breaking up your story in this way, focusing on models and services first, and then on user interface, leads to alot of difficult questions. The answers, unfortunately are either "no" or "I don't know". So, what can you do to improve the situation?
&lt;/p&gt;
&lt;h3&gt;Strands of functionality&lt;/h3&gt;
&lt;p&gt;
What if you take this "story", and instead re-word it into several end-to-end features? Each piece of functionality is much smaller. Once complete, each feature can be demonstrated to the product owner. Once some critical features are complete, other features can be developed in parallel. Finally, once the product owner starts to see this story built out he may have other ideas, or want to change direction altogether. So, what do we need to do to give our team all of these options?
&lt;/p&gt;
&lt;p&gt;
First, lets break this story down into features. The difference is subtle, and development teams may use these words interchangeably. I like to think about a feature as a single, end to end, piece of functionality, that adds value to the user. So how can we break the Store Locator story down into some constituent features? Here's one way:
&lt;ol&gt;
&lt;li&gt;User searches by zip code, and sees a list of stores with address and hours.&lt;/li&gt;
&lt;li&gt;User searches by address.&lt;/li&gt;
&lt;li&gt;Results are displayed with a static map.&lt;/li&gt;
&lt;li&gt;Map can zoom in, zoom out, and pan.&lt;/li&gt;
&lt;li&gt;Display the regional managers name, phone and email.&lt;/li&gt;
&lt;li&gt;Display the regional managers picture.&lt;/li&gt;
&lt;li&gt;Pre-fill the search when the user is logged in.&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;h3&gt;Good for everyone&lt;/h3&gt;
&lt;p&gt;
When we think about this story by features this way, alot of opportunities open up. Each feature is small and focus, and therefore easier to develop. After the initial search with results is developed, features can be developed in parallel. The product manager will be able to see real progress much easier. The individual features can be prioritized amongst each other, as well as among other stories, so that only the most valuable features are developed.
&lt;/p&gt;
&lt;p&gt;
Though I initially looked at breaking up the stories from the product owners perspective, there are also benefits for the developer. The biggest benefit is that development can focus on just one slice of functionality at time. This is much easier to think about than the original, full story. You can focus on search without worrying about maps or regional managers. Often when working on a large sotry, it's hard to know where to start. Breaking it down into thin features makes it much easier to focus.
&lt;/p&gt;
&lt;p&gt;
Working on thin slices is also alot of fun to develop. The combination of quick wins and rapid feedback energizes developers. The laser focus of the features keeps their mental stack light. 
&lt;/p&gt;
&lt;h3&gt;Nuances&lt;/h3&gt;
&lt;p&gt;
It's not always easy, or straightforward, to break a large story down into small, thin slices. The key is to think about what brings the user value, and what can be demonstrated to the user. You don't want your stories too thin, so that there is nothing to demonstrate. You want them going end to end in your system, from the user interface, into your domain logic, persistence and even collaborating systems.
&lt;/p&gt;
&lt;p&gt;
This example isn't made up or theoretical. It came from a real project I recently worked on. We refer back to it often as a good way to add functionality to our system. 
&lt;/p&gt;
&lt;h3&gt;Take-away&lt;/h3&gt;
&lt;p&gt;
Once you have demonstrated working functionality, you are in a position to get the feedback and iteration needed to make a really spectacular system. This is very fertile ground for controlled innovation and growth, because it all starts with demonstrating value. Focus on this slices of functionality, and continuously stay in this sweet spot of value and innovation.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-7666561071891198618?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/7666561071891198618/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/12/thin-valuable-features.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7666561071891198618'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7666561071891198618'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/12/thin-valuable-features.html' title='Thin, valuable features'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-2209257666668700404</id><published>2010-11-23T22:58:00.001-06:00</published><updated>2010-11-23T23:16:03.939-06:00</updated><title type='text'>Fun development</title><content type='html'>&lt;p&gt; Several things came together today, and though not evident at first, they are all somewhat related.  &lt;/p&gt;
&lt;h3&gt; FIRST &lt;/h3&gt;
&lt;p&gt; My pair kept asking why I was so adamant about not writing any code without specifying it first. I explained how specifying kept us focused on what we needed to do, helped us drive out the overall design, and eventually provided a safety net for testing and refactoring. In particular, we were practicing outside-in development in Rails, using Cucumber and RSpec. The goals we were achieving, in order, were:
&lt;ol&gt;
&lt;li&gt;understanding our problem&lt;/li&gt;
&lt;li&gt;designing and developing our solution&lt;/li&gt;
&lt;li&gt;building up tests for the future.&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;p&gt; The cucumber scenarios help us focus on understanding the requirements, from the end-user's point of view. They also drive out the high-level interface of the app, particularly the URL's. The URL's then lead us to create routes, and the routes lead us to create controllers. The cucumber scenarios also drive out any expectations we may have on any models, which the controller will usually set as instance variables.  &lt;/p&gt;
&lt;p&gt; Once we know we need a particular controller, we jump in to specify the controller, and the detailed behavior we expect there. Fleshing out the controller may drive out any additional functionality needed on the model. Finally, we spec out the model. At this point, we work through any additional functionality in the cucumber scenario. Once all scenarios and specs are passing, and we can't think of any more to write, we're done.  &lt;/p&gt;
&lt;p&gt; Obviously, my description is quite simplified. There is alot of subtlety here. That's why I suggested that I send some links to some good videos online, which talk about outside in development, specification, integration tests, and design in general. My friend Tom had done &lt;a href="http://floorsweepings.blogspot.com/2010/07/testing-and-design.html"&gt;something similar&lt;/a&gt; earlier this year.  &lt;/p&gt;
&lt;p&gt; Here is my list, in suggested viewing order. The first is fairly concrete, and then they get more abstract and theoretical.
&lt;ol&gt;
&lt;li&gt;Joseph Wilk's &lt;a href="http://scotland-on-rails.s3.amazonaws.com/1A06_JosephWilk-SOR.mp4"&gt;Working Outside-in with Cucumber and RSpec&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;J.B. Rainsbergers &lt;a href="http://www.infoq.com/presentations/integration-tests-scam"&gt;Integration Tests are a Scam&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Michael Feathers' &lt;a href="http://streaming.ndc2010.no/tcs/?id=E524650B-F5BD-4450-8B39-502AAD7FC053"&gt;The Deep Synergy Between Testability and Good Design&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;
&lt;h3&gt; SECOND &lt;/h3&gt;
&lt;p&gt; On the way home, I saw that my coworker Mike tweeted about a &lt;a href="http://just3ws.com/why-are-altnet-developers-moving-towards-ruby"&gt;blog post he wrote today&lt;/a&gt;. This struck a chord with me, especially when I got to the end. The entire article rings true in the Enterprise Java space as it does in .NET. Then he clinched it with this:
&lt;blockquote&gt;If I do ever go back to working on a .NET project, I'll bring a lot of new knowledge and ideas that will likely make that a more enjoyable experience.&lt;/blockquote&gt;
&lt;/p&gt;
&lt;p&gt;
Over the last few months, I've been having tremendous amounts of fun developing with Cucumber, RSpec and Rails. There seems to be a huge sweet spot, where it's very easy to get into the flow. You start writing the scenarios and specifications, and the application starts to write itself.
&lt;/p&gt;
&lt;p&gt;
I had practiced acceptance testing and unit testing in the java world, and it was alot of hard work! With these tools, it's great fun, and it practically does the work for you. There is still alot of thinking involved, but it is much more focused on the problem domain.
&lt;/p&gt;
&lt;h3&gt; THIRD &lt;/h3&gt;
&lt;p&gt;Andy talked about a &lt;a href="http://andymaleh.blogspot.com/2010/11/generating-tests.html"&gt;powerful technique&lt;/a&gt; to write and grow your specs. In addition, he talks about how the developer specifications, when printed up pretty, made great documentation for a non-technical client. Consider how much stronger his collaboration was because he could share his specifications with his client. Shared language and shared understanding lead to better communication and increased collaboration. &lt;/p&gt;
&lt;h3&gt; FINALLY &lt;/h3&gt;
&lt;p&gt; Syntactically, the Ruby language is not very large. You can start reading ruby code very quickly. And, you can read most any ruby code that you want. As an interpreted language, all libraries are shipped in very readable files. In addition, the community seems very open to keeping things open and readable. I have yet to see any library that is obfuscated.  &lt;/p&gt;
&lt;p&gt; Which brings us to Colin, and his &lt;a href="http://twitter.com/aberant/status/7089010031722496"&gt;tweet&lt;/a&gt; at the end of the day:
&lt;blockquote&gt;pro-tip: every week read up on a new class in the #ruby stdlib. i don't think enough people know what's available to them.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;You could wield alot of power when you are given the chance to understand every piece of every library that you are using. This power comes in the form of understanding what you're using.
&lt;/p&gt;
&lt;h3&gt; TAKEAWAY &lt;/h3&gt;
&lt;p&gt; Learn powerful tools and techniques. Read as much code as you can. Understand the guts of what you're working with. Go out and have fun developing!!!&lt;/p&gt;
&lt;p&gt;Your days will be alot more enjoyable, and your work will be alot more professional. &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-2209257666668700404?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/2209257666668700404/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/11/fun-development.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2209257666668700404'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2209257666668700404'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/11/fun-development.html' title='Fun development'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-8299941850187599323</id><published>2010-11-12T20:23:00.007-06:00</published><updated>2010-11-12T20:35:54.273-06:00</updated><title type='text'>A Perfect Programming Day</title><content type='html'>&lt;p&gt;
I had what I would consider a nearly perfect programming day today. It really started yesterday before I left, when Jim (tech lead) reviewed an upcoming task with me. I was in the middle of another task, so I suggested we pick up in the morning.
&lt;/p&gt;

&lt;p&gt;
The api team was processing a product file, and we needed to adapt that process so that the web team could also consume it. The next day, Jim and I reviewed the current implementation of the process, as well as the goals of the updates. The process took a file, filtered and translated it, and created a new file. We wanted to add to that process, to create a second file to be used by the web team.
&lt;/p&gt;

&lt;p&gt;
Our BA came by to discuss the details of the fields and the formats we would be getting, as well as how we wanted to filter the records. We all agreed to an approach. Our BA would do the write-up for the sake of sharing the understanding with QA and other team members. We also agreed not to wait for a detailed write-up before starting development. 
&lt;/p&gt;

&lt;p&gt;
I was going to work with Matt, who had written the initial process. When Matt arrived, he asked what we needed to do. I gave him an overview of what I understood. He immediately knew where to jump into the code and start. We were working at a station that had not been used for this project before, so first we synched with source control. Then we ran the test suite. After installing a couple of gem dependencies, the tests passed.
&lt;/p&gt;

&lt;p&gt;
Matt showed me the classes involved in the process, and gave me a detailed walk through of how the input was filtered and transformed. This took about 10 minutes. We then talked about what parts were common and could be re-used, and what would change to support the creation of a second file. At that point, instead of digging in, we decided to refactor the current implementation. This would allow us to more easily add the code to create the second file. 
&lt;/p&gt;

&lt;p&gt;
This process consisted of two classes: a &lt;code&gt;Processor&lt;/code&gt; and a &lt;code&gt;Line&lt;/code&gt;. The &lt;code&gt;Processor&lt;/code&gt; looped through source file, passed each line to a &lt;code&gt;Line&lt;/code&gt; instance to be filtered and transformed, and wrote the output file. The &lt;code&gt;Line&lt;/code&gt; class was responsible for the actual filtering and transforming.
&lt;/p&gt;

&lt;p&gt;
We spent a few minutes creating a superclass, and moving common processing up into the superclass. We ran all tests, and they passed. We didn't change any tests along the way. We only changed the implementation by introducing a superclass. This was pure refactoring. We were ready for an initial local commit.
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;
We spent a few minutes trying different names for the superclass and the subclass with the current implementation. Initially, the &lt;code&gt;Line&lt;/code&gt; class was called &lt;code&gt;SocLine&lt;/code&gt;, named after the file which was being filtered and transformed. We tried &lt;code&gt;Line&lt;/code&gt; for the superclass, but that was too generic. We finally went with &lt;code&gt;ProductFileLine&lt;/code&gt; as the superclass, representing the source of the data, and &lt;code&gt;ApiLine&lt;/code&gt; for the subclass.
&lt;/p&gt;

&lt;p&gt;
In afterthought, these classes' responsibilities were filtering and transforming. Maybe better names would have been &lt;code&gt;ProductFileLineTransformer&lt;/code&gt; and &lt;code&gt;ApiLineTransformer&lt;/code&gt;.
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;
Next, we looked at the code that was looping through the input file, filtering and transforming, and creating the output file. We added acceptance tests to check that a second file was being created. We modified the loop to create a second file, and our tests passed.
&lt;/p&gt;

&lt;p&gt;
Now we wanted to implement the new filtering and transformation for the web file. This we decided would be better served through unit tests. First we wrote the specs for the new filtering rules, and then the code to get those to pass. Then we wrote the specs to transform each line to the correct format. 
&lt;/p&gt;

&lt;p&gt;
At this point, we were done with the happy path for this story. What remained were a couple of specific transformations, and any final cleanup. We also wanted to look at an example input file for any special data considerations. We continued after lunch.
&lt;/p&gt;

&lt;p&gt;
We transformed several columns to change their data types from text flags to booleans. Our specs failed as expected. We updated them to pass, and continued.
&lt;/p&gt;

&lt;p&gt;
We reviewed the order of the data we were exporting, and arranged the fields in a more logical order. We also reviewed the BA's write-up (which was done at this point) for anything that we may have missed. We identified a small item, fixed it, and continued.
&lt;/p&gt;

&lt;p&gt;
At this point, we squashed our local commits down to one, pushed our changes up to source control, and called it a day.
&lt;/p&gt;

&lt;h3&gt;Why perfect?&lt;/h3&gt;

&lt;p&gt;
The obvious point is that the day flew by, and it was incredibly fun. But there is more to it than just fun.
&lt;/p&gt;

&lt;p&gt;
Working with Jim and our BA, we were able to start development quickly with a minimal amount of ceremony. I was able to start developing while the BA was detailing the story. At the end of the day, we were able to do a final check before moving the story to QA. We went with a light a process as we could, and we worked in parallel once we had a good common understanding.
&lt;/p&gt;

&lt;p&gt;
We never strayed too far from all tests passing. We kept our changes small. We worked in small increments, and committed (locally) whenever we were at a stable point. Though there was no need today, had we needed to go back and take a different approach, it would have been as easy as reverting a commit or two.
&lt;/p&gt;

&lt;p&gt;
The code that we started with was already well-factored. This made it easy to make our changes.
&lt;/p&gt;

&lt;p&gt;
There were tests in place when we started, so that refactoring was safe. When we finished refactoring, we were quite confident that we hadn't broken anything.
&lt;/p&gt;

&lt;p&gt;
Finally, we were pairing. Both Matt and I were at the keyboard, and taking turns driving and thinking throughout the episode.
&lt;/p&gt;

&lt;h3&gt;PS: Towards a stronger design&lt;/h3&gt;

&lt;p&gt;
The extension to the design that we did today was sufficient. We could have taken it further, having our &lt;code&gt;Processor&lt;/code&gt; class follow the Open-Close Principle. That way, it's core functionality would not need to change when we needed to add another output file. We would simply need to add a new &lt;code&gt;Line&lt;/code&gt; class with it's own filters and transformations.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-8299941850187599323?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/8299941850187599323/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/11/perfect-programming-day.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8299941850187599323'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8299941850187599323'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/11/perfect-programming-day.html' title='A Perfect Programming Day'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-4138015055864314049</id><published>2010-09-13T22:17:00.003-05:00</published><updated>2010-09-13T22:24:58.185-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='javascript jquery'/><title type='text'>A little learned, a little desired</title><content type='html'>&lt;p&gt;You can't use &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; to dynamically set the title of your web page, even though the syntax (and the documentation) would lead you to believe that you could. I spent about an hour today tracking this one down, before coming across this &lt;a href="http://forum.jquery.com/topic/altering-content-of-title-in-head-fails"&gt;gem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Instead of saying:
&lt;code&gt;
$('title').html('My new page title');
&lt;/code&gt;

what you really want to do is go back to simple javascript:

&lt;code&gt;
document.tile = 'My new page title';
&lt;/code&gt;
&lt;/p&gt;

&lt;p&gt;To really put a wrench in the whole matter, the jQuery call works in Firefox and Safari, but not in IE.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-4138015055864314049?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/4138015055864314049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/09/little-learned-little-desired.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4138015055864314049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4138015055864314049'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/09/little-learned-little-desired.html' title='A little learned, a little desired'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-4750112846879649172</id><published>2010-05-17T22:46:00.001-05:00</published><updated>2010-05-17T22:48:46.853-05:00</updated><title type='text'>FloorSweepings: Efficiency and Trust</title><content type='html'>&lt;p&gt;My friend recently went on this tirade at &lt;a href="http://floorsweepings.blogspot.com/2010/05/efficiency-and-trust.html#links"&gt;FloorSweepings: Efficiency and Trust&lt;/a&gt; about ceremony and dress code. Though I should probably be chopping it up about ceremony with him, the dress code part ignited some emotions.&lt;/p&gt;
&lt;p&gt;I've always thought that people shouldn't judge you based on what you wear. Instead, they should look at the work you perform, and the value that you bring to your team and your organization. Unfortunately, people aren't so rational.&lt;/p&gt;
&lt;p&gt;I've been reading &lt;a href="http://www.amazon.com/Influence-Practice-Robert-B-Cialdini/dp/0205609996/"&gt;&lt;em&gt;Influence&lt;/em&gt; by Robert Cialdini&lt;/a&gt;. It's chock full of anecdotes, backed up by real research, about why people act the way they do. It's been quite eye-opening. In particular, one area of research deals with how people respond to others "in uniform". His examples include people posing as security guards, priests, and businessmen in pinstripes. In every case, people are able to exert significantly more influence when the look the part. That is to say, "customers" and "suckers" are more likely to believe your message when your clothes match your role.&lt;/p&gt;
&lt;p&gt;Back to my friends rant, I don't think that his consulting manager is out to get him four days a week by asking him to dress no jeans, no sneakers, with dress shirt. Nor is it declaring itself "Old Biz" or non-"Agile" by requesting a certain level of dress. This company understands that most people aren't so enlightened as to focus on the work you do and the value, and is playing it safe by dressing "one-level up". Add to it that most consultancies should be called what they are -- staff augmentation firms -- and you can see why consulting managers want to do everything they can to exert any influence possible on an organization.&lt;/p&gt;
&lt;p&gt;So, do you prefer your shirts on hangers or boxed?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-4750112846879649172?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/4750112846879649172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/05/floorsweepings-efficiency-and-trust.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4750112846879649172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4750112846879649172'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/05/floorsweepings-efficiency-and-trust.html' title='FloorSweepings: Efficiency and Trust'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-8051993694994071337</id><published>2010-05-11T00:18:00.006-05:00</published><updated>2010-05-11T11:13:37.220-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><title type='text'>Good enough software</title><content type='html'>&lt;p&gt;Around 2000-2001, the &lt;a href="http://pragprog.com/the-pragmatic-programmer/extracts/toc"&gt;Pragmatic Programmers&lt;/a&gt; introduced me to this term. At the time, I took it to mean doing just enough design to get your feature working. I didn't really take to heart the longer-term trade-offs that lingered around, including technical debt.&lt;/p&gt;
&lt;p&gt;Fast-forward to the spring of 2010...I've run across some great articles by &lt;a href="http://xprogramming.com/articles/quality"&gt;Ron Jeffries&lt;/a&gt; and &lt;a href="https://elearning.industriallogic.com/gh/submit?Action=PageAction&amp;album=blog2009&amp;path=blog2009/2010/sufficientDesign&amp;devLanguage=Java"&gt;Josh Kerievsky&lt;/a&gt; addressing this topic, and framing it against product value and productivity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take-aways:&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Extremely poor quality slows us down. Striving for perfection also slows us down. We need to find the sweet-spot somewhere short of perfection, where we are not slowed by neither defects nor perfection.&lt;/li&gt;
&lt;li&gt;We need to design &lt;em&gt;towards&lt;/em&gt; perfection on the more important, more valuable parts of the system. Here, value is what the customer perceives, or areas of code where we spend much of our time and cannot afford slow development.&lt;/li&gt;
&lt;li&gt;We should back away from perfection, and spend less time designing the areas of the software that are not as critical.&lt;/li&gt;
&lt;li&gt;These decisions should be based on the value of the features we are developing, and on how much the design gets in the way of future work.&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;
&lt;p&gt;There is alot of subtlety here, and getting good at this comes with mistakes and experience.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-8051993694994071337?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/8051993694994071337/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/05/good-enough-software.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8051993694994071337'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8051993694994071337'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/05/good-enough-software.html' title='Good enough software'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-7507353742999964537</id><published>2010-04-28T23:26:00.004-05:00</published><updated>2010-04-29T00:03:23.963-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><category scheme='http://www.blogger.com/atom/ns#' term='unit-testing'/><title type='text'>Unit testing and your level of focus</title><content type='html'>&lt;p&gt;I ran across this &lt;a href="http://programmingtour.blogspot.com/2009/08/testing-techniques-with-jb-rainsberger.html"&gt;little gem&lt;/a&gt; recently. It's about 40 minutes long, and full of great insights into unit testing.&lt;/p&gt;
&lt;p&gt;To unjustly summarize, there are several points along the spectrum of unit testing:
&lt;ul&gt;
&lt;li&gt;No testing&lt;/li&gt;
&lt;li&gt;Manual testing&lt;/li&gt;
&lt;li&gt;Test-after unit testing&lt;/li&gt;
&lt;li&gt;Test-first unit testing&lt;/li&gt;
&lt;li&gt;TDD &lt;em&gt;Test-driven-development&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;TDD &lt;em&gt;Test-driven-design&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;The sweet spot seems to be in going back and forth between TDD and TDD. However, it takes a good amount of time and effort to be able to recognize where you are on this spectrum, or that there even is a spectrum of testing.&lt;/p&gt;
&lt;p&gt;Test-driven-design is a tool to help you work out the classes involved in your solution, and how they will work together. This can be likened to the old school technique of designing your interface.&lt;/p&gt;
&lt;p&gt;Test-driven-development is a tool to bullet-proof your code; to test the edge-cases; to test for boundary values; and generally to make sure that your code works in as many situations as possible. This can be likened to the old school technique of fleshing out your implementation.&lt;/p&gt;
&lt;p&gt;It takes great skill to work back and forth between these two flavors of of TDD. Yet by getting to that point, in addition to a solid design and a solid implementation, you'll have the safety net in place to be aggressive, make changes, and respond to your clients needs. &lt;/p&gt;
&lt;p&gt;You may even quickly deliver valuable features. What could be better than that?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-7507353742999964537?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/7507353742999964537/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/04/unit-testing-and-your-level-of-focus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7507353742999964537'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7507353742999964537'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/04/unit-testing-and-your-level-of-focus.html' title='Unit testing and your level of focus'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-3408008804939016616</id><published>2010-04-17T00:07:00.000-05:00</published><updated>2010-04-22T16:25:29.737-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>Focus</title><content type='html'>&lt;p&gt;I'm working on an application that plays video, and displays some widgets and graphics on top of that, depending on what actions the user makes. Some of the widgets have a degree of transparency to them, others do not, and cover up the entire area of video behind them.&lt;/p&gt;
&lt;p&gt;I was working on getting the widgets to display the right information, and didn't pay as much attention to how each layer was interacting with those below. When I demoed my work to my colleagues, one immediately noticed that when the widgets overlapped, the transparency of the top was was being passed on to the one below, making the overlapping areas transparent and displaying the video below.&lt;/p&gt;
&lt;p&gt;I was focused on displaying the correct information, and didn't even notice the transparency problem. My colleague, a graphics expert, immediately noticed the problem, and started thinking of ways to solve the issue. That's when our other colleague, also a graphics expert, chimed in with a very pragmatic idea: &lt;blockquote&gt;Let's move the widgets around, and put off fixing the problem until we have to.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;Takeaways: &lt;strong&gt;While focusing on a specific task, continue to keep the entire application (project) in mind. &lt;/strong&gt;
&lt;ol&gt;
&lt;li&gt;In my case, while I was working on presenting the correct data, I should have paid attention to other details in the application.&lt;/li&gt;
&lt;li&gt;As graphics experts, my colleagues could have jumped at the chance to fix the transparency problem. Instead, they stepped back to consider this problem in regards to other priorities within our project, and decided to delay the fix.&lt;/li&gt;
&lt;/ol&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-3408008804939016616?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/3408008804939016616/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/04/focus.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/3408008804939016616'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/3408008804939016616'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/04/focus.html' title='Focus'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-1764446837913907017</id><published>2010-04-13T10:39:00.000-05:00</published><updated>2010-04-22T16:25:59.553-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>Software Engineering?</title><content type='html'>&lt;p&gt;Tom DeMarco is "gradually coming to the conclusion that software engineering is an idea whose time has come and gone." He says so &lt;a href="http://www2.computer.org/cms/Computer.org/ComputingNow/homepage/2009/0709/rW_SO_Viewpoints.pdf"&gt;here&lt;/a&gt;. He concludes:&lt;blockquote&gt;Consistency and predictability are still desirable, but they haven’t ever been the most important things. For the past 40 years, for example, we’ve tortured ourselves over our inability to finish a software project on time and on budget. But as I hinted earlier, this never should have been the supreme goal. The more important goal is transformation, creating software that changes the world or that transforms a company or how it does business.&lt;/blockquote&gt;&lt;/p&gt;&lt;p&gt;Go out and build great software. You should take pride in doing it well -- so that others can enjoy reading and maintaining your code. But your most important focus should be on building great software for your users. Focus on rocking their world. Change the way they do things, and change it significantly.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-1764446837913907017?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/1764446837913907017/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/04/software-engineering.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/1764446837913907017'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/1764446837913907017'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/04/software-engineering.html' title='Software Engineering?'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-1122961565344826605</id><published>2010-04-06T11:53:00.000-05:00</published><updated>2010-04-22T16:26:26.236-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='agile'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><title type='text'>What Do We Know about Agile Software Development?</title><content type='html'>&lt;p&gt;Dybå, Tore and Dingsøyr, T.  "What Do We Know about Agile Software Development?" &lt;em&gt;IEEE Software&lt;/em&gt;, vol. 26, no. 5, 2009, pp. 6-9.&lt;/p&gt;&lt;p&gt;The authors surveyed the academic literature, to summarize what is known (academically, scientifically) about agile software development. Based on my experience in the field, there seems to be a disconnect between academic research and practices in the trenches. Below are some of the findings from this research, and my responses.&lt;/p&gt;&lt;blockquote&gt;Some studies saw pair programming as inefficient, and some studies claimed that XP works best with experienced development teams. One study reported the further limitation, which the literature repeatedly mentions, of lack of attention to design and architectural issues.&lt;/blockquote&gt;&lt;p&gt;Any development method or development process will work best with experienced development teams, particularly when compared against itself. What I have seen is that XP is great at taking a mixed team, and improving the abilities of everyone on the team. The practices of open communication and collaboration, collective code ownership, pair programming and emergent architecture all contribute. As the project progresses, each team member, no matter how junior, will have worked on many aspects of the system, each full of opportunities for learning.&lt;/p&gt;&lt;p&gt;Using a prescriptive development process could still lead to a lacking design and a lacking architecture. XP provides practices of refactoring, collective code ownership, test driven development and emerging architecture. These practices together allow the team to constantly improve the design, while building out only as much architecture as necessary. Diligence and attention to detail can be used or abused in any development process.&lt;/p&gt;&lt;blockquote&gt;However, the on-site customer’s role can be stressful and unsustainable for long periods.&lt;/blockquote&gt;&lt;p&gt;There is more than enough here for another full post. Without an on-site customer, we can regress to having long feedback cycles, waiting for emails or phone calls to be answered. We may even regress back to writing a requirements document, usually by a business analyst, and throwing it over the wall to development. The document is then ripe for mis-interpretation and other abuses by the readers. To have the right software developed, the right person needs to be fully involved and committed.&lt;/p&gt;&lt;blockquote&gt;The findings regarding pair programming’s effectiveness were mixed.
Several developers regarded it as an exhausting practice because it requires heavy
concentration.&lt;/blockquote&gt;&lt;p&gt;Pair programming provides many benefits: automatic code review, information exchange, focus, efficiency, learning. XP has another practice, &lt;a href="http://www.extremeprogramming.org/rules/overtime.html"&gt;sustainable pace&lt;/a&gt;, which offsets the intensity. The authors even note in their findings that agile team members believe they are more efficient.&lt;/p&gt;&lt;blockquote&gt;One limitation that came up was that team members are less interchangeable in agile teams, which has consequences for how projects are managed.&lt;/blockquote&gt;&lt;p&gt;By pairing and through collective code ownership, the team is spreading the knowledge around, so that more and more of the team members can work on each part of the system. Spreading this knowledge decreases your dependency on a particular developer for a particular area of the code.&lt;/p&gt;&lt;p&gt;Pair programming also makes it much smoother to introduce new developers to the team. The new developer will always be working with someone who is familiar with the code base, the design, and the entire project. This makes it easier to bring on new team members.&lt;/p&gt;&lt;p&gt;If the point of interchangeable developers is to maximize resource utilization, this seems like a case of sub-optimizing. The goal of a project manager should not be to make sure that each &lt;em&gt;resource&lt;/em&gt; is 100% efficient, but instead that the team (of people) is meeting its goal: delivering the right software.&lt;/p&gt;&lt;blockquote&gt;Our review identified 1,996 studies from literature searches, 36 of which we found to be research studies of acceptable rigor, credibility, and relevance to include in the review.&lt;/blockquote&gt;&lt;p&gt;I may be biased by successful agile projects in which I have participated over the last ten years. I may also be biased by all of the pairs I have worked with, who taught me new things and made each task much more fun.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-1122961565344826605?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/1122961565344826605/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/04/what-do-we-know-about-agile-software.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/1122961565344826605'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/1122961565344826605'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/04/what-do-we-know-about-agile-software.html' title='What Do We Know about Agile Software Development?'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-1432722171168312776</id><published>2010-04-05T11:16:00.000-05:00</published><updated>2010-04-22T16:27:10.603-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><title type='text'>Improving your team's code</title><content type='html'>&lt;p&gt;Peer code reviews are a great way to catch software defects early and often. This practice has been around since at least the mid-seventies [Fagan '76]. &lt;/p&gt;&lt;p&gt;Extreme programming (XP) has a couple of practices built-in to support reviews. &lt;a href="http://www.extremeprogramming.org/rules/collective.html"&gt;Collective Ownership&lt;/a&gt; encourages everyone to contribute new ideas to all segments of the project. &lt;a href="http://www.extremeprogramming.org/rules/pair.html"&gt;Pair programming&lt;/a&gt; increases software quality without impacting time to deliver. All code to be sent into production is created by two people working together at a single computer.&lt;/p&gt;&lt;p&gt;Having experienced both traditional code reviews, and full-blown pair-programming, I believe pairing to be a very effective and efficient step towards good, clean code.&lt;/p&gt;&lt;p&gt;Yet, I've had team-mates that didn't want to be part of the process, and I've had team leaders who didn't know how to constructively make it work. I have come across some good practices for &lt;a href="http://smartbear.com/docs/BestPracticesForPeerCodeReview.pdf"&gt;peer code review&lt;/a&gt; to pass on to them. Even though this is written from the point of view of traditional code reviews, I think that the principles can be applied to Agile environments as well. Below are some excerpts I particularly enjoyed:&lt;/p&gt;&lt;blockquote&gt;&lt;h4&gt;8. Managers must foster a good code review culture in which finding defects is viewed positively.&lt;/h4&gt;&lt;p&gt;Code review can do more for true team building than almost any other technique we’ve seen – but only if managers promote it at a means for learning, growing, and communication. It’s easy to see defects as a bad thing – after all they are mistakes in the code – but fostering a negative attitude towards defects found can sour a whole team, not to mention sabotage the bug-finding process.&lt;/p&gt;&lt;h4&gt;9. Beware the “Big Brother” effect.&lt;/h4&gt;&lt;p&gt;Managers must continue to foster the idea that finding defects is good, not evil, and that defect density is not correlated with developer ability. Remember to make sure it’s clear to the team that defects, particularly the number of defects introduced by a team member, shouldn’t be shunned and will never be used for performance evaluations.&lt;/p&gt;&lt;h4&gt;10. The Ego Effect: Do at least some code review, even if you don’t have time to review it all.&lt;/h4&gt;&lt;p&gt;The “Ego Effect” drives developers to write better code because they know that others will be looking at their code and their metrics. And no one wants to be known as the guy who makes all those junior-level mistakes. The Ego Effect drives developers to review their own work carefully before passing it on to others.&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-1432722171168312776?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/1432722171168312776/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/04/improving-your-teams-code.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/1432722171168312776'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/1432722171168312776'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/04/improving-your-teams-code.html' title='Improving your team&apos;s code'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-7363685550631915481</id><published>2010-02-07T22:16:00.000-06:00</published><updated>2010-04-22T16:27:43.407-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='teams'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>Managing ideas, ala Weinberg</title><content type='html'>&lt;p&gt;This is a list of ways to get ideas flowing when trying to solve a problem, particularly in a team, based on Jerry Weinberg's &lt;em&gt;Becoming a Technical Leader&lt;/em&gt;. Each of his ideas is great on its own, and they work well together, but there are also subtleties that you should be aware of.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Contribute a clever idea to the team.&lt;/em&gt;&lt;/strong&gt; When it works, and when it's really novel, this is really cool. Most of the time, there are no new ideas, but re-hashed ideas from other sources. Instead of trying to get the perfect solution right away, spend your energy creating an environment where ideas can be exchanged and the "right" ideas can be recognized when they come along.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Encourage copying of useful ideas.&lt;/em&gt;&lt;/strong&gt; Look for inspiration in your own branch, or in another knowledge area as well. And remember problems that you've already solved, in case this problem is similar.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Elaborate on an idea that a teammate contributed.&lt;/em&gt;&lt;/strong&gt; Iterate, and make it better. Keep following through. Follow up the inspiration with enough perspiration to see it through.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Drop one's own idea in favor of an idea the team wants to develop.&lt;/em&gt;&lt;/strong&gt; Strike a balance between stubbornly holding on to your ideas, and letting go of your ideas just for the sake of keeping the group happy and moving along.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Refuse to let an idea drop until everyone understands it.&lt;/em&gt;&lt;/strong&gt; Like the previous example; this will come with time and experience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Resist time pressure, and take the time to listen when other people explain their ideas.&lt;/em&gt;&lt;/strong&gt; Take extra care to know &lt;em&gt;why&lt;/em&gt; an idea is being dropped.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test ideas contributed by other people.&lt;/em&gt;&lt;/strong&gt;Look for the initial idea anywhere and everywhere, and then make it better.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Withhold quick criticism of teammates' ideas, in order to keep the ideas flowing.&lt;/em&gt;&lt;/strong&gt;This is particularly important at the beginning, such as in a brainstorming session. Make the tradeoff to accept more ideas, which will be dropped later, than to drop early and not generate enough ideas. This improves with experience.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;When you must criticize an idea, make clear that you are criticizing the idea, not the person who offered the idea.&lt;/em&gt;&lt;/strong&gt;In addition to maintaining a good relationship with your teammates, this let's you explain which parts of the idea work, and which ones don't. It also let's your teammates in on how you come to your conclusions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Test your own ideas before offering them.&lt;/em&gt;&lt;/strong&gt;Take the extra time to scrutinize your ideas the same way you would the ideas of your teammates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;When time and labor are running short, stop working on new ideas and just pitch in.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Encourage the team to drop ideas that had succeeded earlier, but cannot be extended to the new situation.&lt;/em&gt;&lt;/strong&gt; Make sure that the ideas fit in with what you are trying to accomplish.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Revive a dropped idea later, when it has value for another part of the problem.&lt;/em&gt;&lt;/strong&gt; Remember your old ideas and solutions, because they may become useful again.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-7363685550631915481?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/7363685550631915481/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2010/02/managing-ideas-ala-weinberg.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7363685550631915481'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7363685550631915481'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2010/02/managing-ideas-ala-weinberg.html' title='Managing ideas, ala Weinberg'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-2494046836756855145</id><published>2009-12-15T22:22:00.000-06:00</published><updated>2010-04-22T16:28:30.154-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='software design'/><title type='text'>Reusable classes</title><content type='html'>&lt;p&gt;Today, my pair commented on how we have gotten a lot of use from our test-&lt;em&gt;helper&lt;/em&gt; classes. How true, how true. Over the course of the last year, we have created the classes needed in by our application, and the tests to support those classes. But we didn't stop there. We also created many small utility classes to support our tests. These classes are barely worth writing, or so it would seem. They are actually priceless.&lt;/p&gt;
&lt;p&gt;We have gotten a lot of re-use from these classes because they are small and concise. They each address and encapsulate one sole responsibility. The classes usually consist of two or three methods, and are no longer than about twenty lines. It's in this precision that they find their utility. Being small and to the point, it is very easy to pick the right class when needed.&lt;/p&gt;
&lt;p&gt;We've developed classes to set and reset system properties; to set and reset logging levels; to read and write private fields; to set id's on our domain models; and many other small responsibilities. At first, when developing these helpers, we would wait for a duplicate need to appear, and then factor out a re-usable component. As we got better at this, we wouldn't wait for a duplicate need, but instead would factor out responsibilities as we saw them appear. This helped us get even more utility from these classes. As soon as the classes were created, uses for them would appear.&lt;/p&gt;
&lt;p&gt;By encapsulating concepts, keeping concepts small and concise, and identifying concepts early, you will increase your chances for re-use, and get a lot of mileage from your classes.&lt;/p&gt;
&lt;p&gt;My takeaways from this experience:
&lt;ul&gt;
&lt;li&gt;encapsulate responsibilities&lt;/li&gt;
&lt;li&gt;create small classes&lt;/li&gt;
&lt;li&gt;factor responsibility early&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-2494046836756855145?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/2494046836756855145/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2009/12/reusable-classes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2494046836756855145'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2494046836756855145'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2009/12/reusable-classes.html' title='Reusable classes'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-5954819318761446094</id><published>2009-12-05T00:31:00.000-06:00</published><updated>2010-04-22T16:28:56.950-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>Hindsight is 20-20, even several years later</title><content type='html'>&lt;p&gt;I ran into an old colleague, &lt;a href="http://www.linkedin.com/in/alexaquino"&gt;Alex&lt;/a&gt;, on the train today. We went through the usual catch up conversations, and got into talking about some of the old projects we had worked on together.&lt;/p&gt;&lt;p&gt;Alex mentioned that an old application that I had worked on along time ago was still being used, and the code still maintained. Our project was a banking web site, and this application was a supporting application that was used to verify and enroll users into the main application, which was a java web application. In typical &lt;em&gt;hindsight is 20-20&lt;/em&gt; fashion, we started to comment on how we might have approached that application differently.&lt;/p&gt;&lt;p&gt;To appreciate what we would have done differently, I guess I owe a little background on the application. The original enrollment application was a Lotus Notes application, and it verified the enrollee information against the account database. When lookups against the account database started having performance problems, we decided to "quickly" fix the problem by replacing the lookup with a &lt;a href="http://www.sybase.com/products/modelingdevelopment/powerbuilder"&gt;PowerBuilder&lt;/a&gt; application. After some modest success improving performance, we decided to fully re-write the enrollment application in PowerBuilder. The application was written along-side the main application, with little design, little visibility and little testing. Despite that, it was deployed on time, and it worked.&lt;/p&gt;&lt;p&gt;Looking back, I would have made this a full-fledged and visible project. The enrollment application, by its nature, has a lifespan that matches that of the main application. This alone should have been consideration enough to give the enrollment application more visibility.&lt;/p&gt;&lt;p&gt;Alex mentioned that maintenance of the application was passed around from team to team. In hindsight, I would have implemented the enrollment application using the same technologies as the main application. The enrollment application was written in PowerBuilder, by a couple of team members, while the rest of the team was working on a Java web application. This would bring the technical skill set in line with the main application, improving the chances of maintaining the application.&lt;/p&gt;&lt;p&gt;I mentioned increasing the visibility. To me this means two things: more project management visibility, and more testing. Over the years, I've seen that detailed visibility into the details of a project, and into the true status of tasks, leads to more successful projects. In part, because developers tell it like it is, and in part because managers can see the details for themselves. This outcome of the original project may not have changed, since the application worked, but the process of getting there would have been much smoother. The same goes with more testing; the outcome may not have changed, but the project would have gone smoother.&lt;/p&gt;&lt;p&gt;Finally, when the PowerBuilder application was first developed, it was thought that this would be a short-lived application, to help with performance for a short time, and then the application would be retired. Of course, it is still not retired. In hindsight, I would have approached even the smallest effort with the same rigor as an application planned for a long lifespan. You never know when an application will take on a life of its own, and outlive everyone's expectations.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-5954819318761446094?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/5954819318761446094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2009/12/hindsight-is-20-20-even-several-years.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/5954819318761446094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/5954819318761446094'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2009/12/hindsight-is-20-20-even-several-years.html' title='Hindsight is 20-20, even several years later'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-4459832776290562094</id><published>2009-12-02T23:59:00.000-06:00</published><updated>2010-04-22T16:29:51.693-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='software engineering'/><title type='text'>Where have I been?</title><content type='html'>&lt;p&gt;I need to thank my friend Tom for getting me back to writing. He's doing a &lt;a href="http://floorsweepings.blogspot.com/"&gt;craftsman spike&lt;/a&gt; to refresh his learning process. Talking to him got me back on track about documenting my own learning. I haven't been documenting lately because I've been studying. I'm 3 classes away from getting my &lt;a href="http://www.cdm.depaul.edu/academics/Pages/MSinSoftwareEngineering.aspx"&gt;Master's in Software Engineering&lt;/a&gt; at DePaul University.&lt;/p&gt;

&lt;p&gt;I started looking into this a couple of years ago while in a rut. I wasn't inspired by my work. The problems were interesting, but I wasn't. Instead of solving problems, I spent a lot of energy trying to muster up the inspiration to get into the problem. Up to that time, all of my programming experience had been on the job, so I thought that some formal study would jump-start me. A year and a half later, that was a good decision. I've learned things about the how software is developed, as well as how software can be developed. Best of all, I again look forward to getting up and going to work; to solving problems; and to learning a little more each day. &lt;/p&gt;

&lt;p&gt;To give myself a best chance to succeed, I will need to combine all of what I've learned on the job, everything I've read along the way, and what I've learned in my course work. There are some great SE practices that can help move your project forward, as there are some great practices and trends from the field, along the lines of agile methods. It's to cross-pollinate some of these ideas, to  mix and match practices and techniques, to upgrade our toolbox for development. I plan to share some of my ideas on this....soon.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-4459832776290562094?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/4459832776290562094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2009/12/where-have-i-been.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4459832776290562094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/4459832776290562094'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2009/12/where-have-i-been.html' title='Where have I been?'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-442880905257472583</id><published>2008-07-01T14:44:00.000-05:00</published><updated>2008-07-01T14:45:18.142-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><title type='text'>Keeping it simple</title><content type='html'>&lt;p&gt;A teammate asked for help on a problem he was having. He was using Hibernate to retrieve data from a table, and wanted to retrieve a character column (Y,N) as a Boolean. His first thought was to the &lt;code&gt;@Type&lt;/code&gt; annotation. He also considered setting the &lt;code&gt;hibernate.query.substitutions&lt;/code&gt; property. &lt;/p&gt;

&lt;p&gt;When he asked me for help, both of these solutions seemed quite complicated for his problem. I asked about retrieving the data as a String, but he said he tried and that it did not work. He was stumped. I was skeptical. I was sure there was a simple way to get this to work.&lt;/p&gt;

&lt;p&gt;He changed his model to represent the data as a string, reloaded the system, and showed me the error he was getting. When we followed the stacktrace back to the line that was causing an error, I noticed that the model being retrieved was not the one he as changing. He had two similarly-named models, and was changing one while testing the behavior of the other.&lt;/p&gt;

&lt;p&gt;These questions came to mind:
&lt;ol&gt;
&lt;li&gt;Why wasn't he pairing while working on this task?&lt;/li&gt;
&lt;li&gt;Why were the models similarly named?&lt;/li&gt;
&lt;li&gt;Why did he need to reboot the system? Why wasn't there a quick integration test written?&lt;/li&gt;
&lt;/ol&gt;
&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-442880905257472583?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/442880905257472583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2008/07/keeping-it-simple.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/442880905257472583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/442880905257472583'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2008/07/keeping-it-simple.html' title='Keeping it simple'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-6855041161726011461</id><published>2007-12-27T15:25:00.000-06:00</published><updated>2007-12-27T13:26:58.405-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><title type='text'>Respect your unit tests</title><content type='html'>&lt;p&gt;Our team just completed a major release of our software. It's been three months since the last release. This is a very long time based on our usual pace of 2 to 3 weeks, so we could expect to have some issues after deployment. Had we shown some respect for our unit tests, we would have fewer issues.&lt;/p&gt;
&lt;p&gt;One of the problems we had was related to some external libraries we were using, which required our models to use conform to the &lt;a href="http://java.sun.com/products/javabeans/docs/spec.html"&gt;JavaBeans spec&lt;/a&gt; ( having both a &lt;code&gt;getX()&lt;/code&gt; and a &lt;code&gt;setX(X x)&lt;/code&gt; method). In some cases, the &lt;code&gt;getX()&lt;/code&gt; was the only meaningful method, and the &lt;code&gt;setX(X x)&lt;/code&gt; was only put there as a placeholder to conform to the API. If the &lt;code&gt;setX(X x)&lt;/code&gt; had a nice comment explaining it's purpose in life, we were safe. But sometimes, we had the stub &lt;code&gt;setX(X x)&lt;/code&gt; method, without an explanation of why it was there. And upon doing some reference checks, we would quickly determine that it was not used by any code, and could be removed.&lt;/p&gt;
&lt;p&gt;That's just what happened in this case. A developer noticed the &lt;em&gt;dead&lt;/em&gt; code, asked around if it was used, got concensus that it wasn't and proceeded to remove it. He ran the unit tests, fixed a couple of broken tests, and checked in his changes.&lt;/p&gt;
&lt;p&gt;He removed un-used code, and then had to fix some unit tests.&lt;/p&gt;
&lt;p&gt;And when we released the code to production, we had problems.&lt;/p&gt;
&lt;p&gt;The fact that the unit tests failed and needed fixing should have been the indication that the code &lt;em&gt;was&lt;/em&gt; used, even if not explicitly referenced by any of our code. The fact that we had production problems confirmed it. The unit tests were in place to prevent this error. But the developer bypassed that warning.&lt;/p&gt;
&lt;p&gt;The unfortunate fact is that it is very easy to learn from a mistake. But it's these mistakes that we need to file away as experience, so that we get better at what we do. Take care in writing unit tests, so that they are meaningful and accurate. And then take greater care when modifying them. When in doubt, trust that the unit tests are right. Grab a pair; get a second opinion; get a third opinion. Let the unit tests serve as one of your safety nets when making changes to code. And respect your unit tests. They don't lie.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-6855041161726011461?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/6855041161726011461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/12/respect-your-unit-tests.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/6855041161726011461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/6855041161726011461'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/12/respect-your-unit-tests.html' title='Respect your unit tests'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-8720455001007540074</id><published>2007-12-04T13:25:00.000-06:00</published><updated>2009-12-04T23:36:58.454-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><title type='text'>Back to the basics of Refactoring</title><content type='html'>&lt;p&gt;I ran into a couple of separate bugs the last couple of days, that were caused because of some refactoring. How can that be, you ask? I asked myself the same thing! By definition, refactoring should change the structure of the code, without changing the behavior. Yet, in both cases, the behavior &lt;em&gt;did&lt;/em&gt; change. Let's see if there is a way to prevent this from happening, and keep with the true nature of refactoring.&lt;/p&gt;
&lt;h4&gt;Refactoring defined&lt;/h4&gt;
&lt;p&gt;Martin Fowler defines &lt;a href="http://www.refactoring.com/"&gt;refactoring&lt;/a&gt; like this: &lt;blockquote&gt;Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior. Its heart is a series of small behavior preserving transformations.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;The key point I see is "small behavior preserving transformation." A refactoring is a small change, and it does not change the behavior.&lt;/p&gt;
&lt;h4&gt;Preserving Behavior with Unit Tests&lt;/h4&gt;
&lt;p&gt;The best way to ensure that you are preserving the behavior, is to have a suite of fast and accurate unit tests. Yes, I am asking alot here. &lt;/p&gt;
&lt;p&gt;The unit tests need to be fast, so that developers do not feel bogged down by having to run them. When they are fast, developers can run all unit tests many times throughout their development cycles.&lt;/p&gt;
&lt;p&gt;The unit tests need to be &lt;em&gt;accurate&lt;/em&gt; so that they go so far as to specify the intended external behavior of a module (or class, or method, or whatever your "unit" is), yet they are flexible enough so that they do not specify the internal structure. This is part science and part art, and is well beyond the scope of this discussion. But the goal is to specify behavior, not implementation.&lt;/p&gt;
&lt;h4&gt;So why did these refactorings go south?&lt;/h4&gt;
&lt;p&gt;We all know the theories of modern development (everything is tested, pair programming, the simplest thing that works), yet it can be hard to put them into practice.&lt;/p&gt;
&lt;p&gt;One of the refactorings I encountered was very subtle in how it broke down. The developer ran all units tests, they passed. Then he made the refactoring. Then he ran all tests again, and they passed again. So he was done, and went on to the next task. However, the tests passed because the code in question was not covered by tests.&lt;/p&gt;
&lt;p&gt;So let me restate my thesis. The best way to ensure that you are preserving the behavior, is to have a suite of fast, accurate, and complete unit tests. There, that should do it.&lt;/p&gt;
&lt;h4&gt;When unit tests are not enough&lt;/h4&gt;
&lt;p&gt;The other refactoring was a bigger change. The goal was to put the &lt;em&gt;soft&lt;/em&gt; into the software. We wanted to take some data that was hardcoded into the application, and move it to the database, so that changes became configurable. The problem was that we had three scenarios, but two of them shared the same hardcoded implementation. So when we went to a configurable implementation, we lost one of the scenarios.&lt;/p&gt;
&lt;p&gt;This problem could also have been avoided by tests, though maybe not what is considered a "unit" tests. To catch this problem as soon as it happened, a broader suite of test would be needed: integration tests, functional tests. The key, though, is that these tests should be broad enough to cover the scope of the refactoring, fast enough to be able to be run by the developer, and complete enough to have tested (and exposed) all scenarios.&lt;/p&gt;
&lt;p&gt;One last time. The best way to ensure that you are preserving the behavior of your code while refactoring, is to have a fast, accurate, complete and broad suite of tests. Fast enough to run often, accurate enough to specify the behavior, complete enough to test what you are changing, and broad enough to cover your code base at different levels of granularity.&lt;/p&gt;
&lt;h4&gt;Conclusion&lt;/h4&gt;
&lt;p&gt;Refactoring improves the code base. Refactoring simplifies the code, makes it easier to comprehend, and easier to change. No arguments there. The key, however, is that refactoring preserves behavior, and the only way to ensure that behavior &lt;em&gt;is&lt;/em&gt; preserved is to have a broad and accurate suite of tests around the code.&lt;/p&gt;
&lt;p&gt;Stated another way, the end user should not be able to tell immediately that you have completed a refactoring. Instead, they should be somewhat impressed when you quickly deliver the next feature that they request.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-8720455001007540074?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/8720455001007540074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/12/back-to-basics-of-refactoring.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8720455001007540074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8720455001007540074'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/12/back-to-basics-of-refactoring.html' title='Back to the basics of Refactoring'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-2787803929818978079</id><published>2007-11-29T08:31:00.000-06:00</published><updated>2007-11-29T08:41:32.441-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='process'/><category scheme='http://www.blogger.com/atom/ns#' term='struts'/><title type='text'>A quick review of debugging Struts applications</title><content type='html'>&lt;p&gt;I had worked on a Struts web application a couple of years ago, and within our team I am still considered the &lt;em&gt;"expert"&lt;/em&gt; on that application. So yesterday, when something wasn't working correctly, a teammate approached me and asked for help. As I walked her through what was going on, I made it a point NOT to rely on any knowledge of the application (after all, it has been two years and several maintenance programmers since I have worked on the application.) Here's what we did:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Based on the URL, track down the action mapping&lt;/li&gt;
&lt;li&gt;Look in the &lt;code&gt;struts-config.xml&lt;/code&gt; file and find the JSP that is rendered&lt;/li&gt;
&lt;li&gt;Examine the JSP and see where the data is coming from; identify the form object that holds the data&lt;/li&gt;
&lt;li&gt;Back in &lt;code&gt;struts-config.xml&lt;/code&gt;, find the action that does the work&lt;/li&gt;
&lt;li&gt;In the action, look at how the form is populated&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In finding and resolving the problem, I didn't have to use any tacit knowledge of application. Instead, we just ran the application, identified the problem, and tracked it back to the code that was causing the problem.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-2787803929818978079?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/2787803929818978079/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/11/quick-review-of-debugging-struts.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2787803929818978079'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2787803929818978079'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/11/quick-review-of-debugging-struts.html' title='A quick review of debugging Struts applications'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-7467606807375364253</id><published>2007-11-20T17:51:00.000-06:00</published><updated>2007-11-20T16:13:52.890-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><title type='text'>A quick and easy way to minimize java.lang.NullPointerExceptions</title><content type='html'>&lt;p&gt;In Java, we often see code that compares a particular value to some know constant. Often this is written like this:&lt;/p&gt;&lt;p&gt;&lt;code&gt;someObject.getSomeValue().equals("SomeConstant");&lt;/code&gt;&lt;/p&gt;&lt;p&gt;This works ok, assuming that &lt;code&gt;someObject&lt;/code&gt; is not null, and as long as you are sure that &lt;code&gt;getSomeValue()&lt;/code&gt; will never be &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;If you aren't so sure, or if you just want to develop a good habits that will minimize the number of &lt;code&gt;NullPointerExceptions&lt;/code&gt; you run into, you may try to write the same comparison this way:&lt;/p&gt;&lt;p&gt;&lt;code&gt;"SomeConstant".equals(someObject.getSomeValue());&lt;/code&gt;&lt;/p&gt;&lt;p&gt;You are ensuring that you will not run into the dreaded &lt;code&gt;java.lang.NullPointerException&lt;/code&gt;, because your constant value will never be &lt;code&gt;null&lt;/code&gt;. And you are improving your own productivity, because you and your teammates will spend less time tracking down and fixing &lt;code&gt;NullPointerExceptions.&lt;/code&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-7467606807375364253?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/7467606807375364253/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/11/quick-and-easy-way-to-avoid.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7467606807375364253'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/7467606807375364253'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/11/quick-and-easy-way-to-avoid.html' title='A quick and easy way to minimize java.lang.NullPointerExceptions'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-2184021123327257864</id><published>2007-11-16T12:00:00.000-06:00</published><updated>2007-11-16T10:04:05.592-06:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='productivity'/><category scheme='http://www.blogger.com/atom/ns#' term='SWT'/><title type='text'>Glimmer to ECLIPSE RubyOnRails?</title><content type='html'>When I hear about &lt;a href="http://www.ruby-lang.org"&gt;Ruby&lt;/a&gt;, the first thought that comes to mind is &lt;a href="http://www.rubyonrails.org"&gt;Ruby on Rails&lt;/a&gt; and Web 2.0 applications. I would have never made the association from Ruby to desktop application. Until now.

About a year ago, it was suggested that &lt;a href="http://www.rubyinside.com/jruby-swt-future-cross-platform-ruby-desktop-app-development-298.html"&gt;JRuby and SWT&lt;/a&gt; might be a viable combination for Ruby on the desktop. After all, &lt;a href="http://www.eclipse.org/swt/"&gt;SWT&lt;/a&gt; is the performant, native desktop library available from &lt;a href="http://www.eclipse.org"&gt;Eclipse&lt;/a&gt;, and Ruby gives you many &lt;a href="http://www.linux-mag.com/2002-04/ruby_01.html"&gt;productivity advantages&lt;/a&gt;. There was even a &lt;a href="http://rubyforge.org/projects/sweetgui/"&gt;SWeeTgui&lt;/a&gt; project at the time, though it doesn't seem like there was much traction.

Fast-forward one year, and we now have &lt;a href="http://rubyforge.org/projects/glimmer/"&gt;Glimmer&lt;/a&gt;: "a JRuby DSL that enables easy and efficient authoring of user-interfaces". What advantages are there with Glimmer? Here's what I see:
&lt;ul&gt;&lt;li&gt;A compact api that allows Ruby developers to write native destop applications&lt;/li&gt;&lt;li&gt;A clean wrapper around the SWT libraries, that takes a minimalist approach by exposing the most important features and applying smart defaults everywhere&lt;/li&gt;&lt;li&gt;An API that is based on Ruby's programming paradigms, not Java's.&lt;/li&gt;&lt;li&gt;The ability to implement complex SWT desktop applications with only 25% of the code.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;That last point is what brought me over. Being able to write the same functionality with just a quarter of the code (and time). I've been developing Java applications for nearly a decade now, and using SWT for two years, and I feel very comfortable. .&lt;/p&gt;&lt;p&gt;When I first saw Glimmer, I didn't believe that I needed it for my Java SWT applications, because I know Java, and I know SWT. But as we discussed the merits of this API, and I saw a demonstration of some complicated user interfaces, I got a "glimmer" in my eye. I could see alot of productivity benefits here.&lt;/p&gt;&lt;p&gt;Take a look for yourself, and consider it for your next desktop project.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-2184021123327257864?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/2184021123327257864/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/11/glimmer-to-eclipse-rubyonrails.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2184021123327257864'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/2184021123327257864'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/11/glimmer-to-eclipse-rubyonrails.html' title='Glimmer to ECLIPSE RubyOnRails?'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-6405454545945809799</id><published>2007-11-02T00:40:00.000-05:00</published><updated>2010-04-17T00:38:30.657-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='process'/><title type='text'>A REAL Onsite Customer</title><content type='html'>&lt;p&gt;I'm currently working on a project that is using an agile process to manage development. We use most of the XP practices, but are mising what I would consider the most important one: an onsite customer. Though our customer is a manager, and the final decision-maker, she doesn't participate directly in the daily development activities. Instead, she sends a proxy.&lt;/p&gt;
&lt;p&gt;This works out great about 75% of the time, but doesn't work so well the other 25%, when we need a tough question answered quickly. And that often introduces some long waiting. Here are a couple of examples.&lt;/p&gt;
&lt;p&gt;Last Friday, the manager had her proxy call a meeting with the developers to discuss a featuer we had just completed. She wanted to improve the flow of the feature, and make sure that it was as easy as possible for the users. We got together with the proxy, brainstormed, offered ideas and estimated the different steps. He then went back to her, she had some other ideas, and some questions. So he came back to us and .....&lt;/p&gt;
&lt;p&gt;All this going back and forth was costing precious time. We are still answering questions and going over ideas, though we never really meet with our customer. There are several problems with this approach. Information is lost, intent is misunderstood with each link in the chain, and delays are introduced. And this happens both ways. The proxy is an intelligent guy, but all the intelligence in the world doesn't help here. Its the nature of communication, similar to the game we played in grade school, where we each whispered something to the next person, and what came out of the chain is not what went in. Extra energy is expended going back and forth. It would be much more convenient, and direct, to be talking directly to the decision-maker.&lt;/p&gt;
&lt;p&gt;Contrast this to what happened yesterday. We were discussing a feature that the developers thought must be included, but the manager thought wasn't necessary. Of course, she sent the proxy to discuss this with us. However, we didn't feel she had a strong argument, and she didn't think we had a strong argument. By chance, one of our teammates saw her walking by, and we asked her to explain her point. Then we explained our. We were quickly able to come up with some options that would meet her requirements and our own. I walked out of this meeting energized and excited about our application. We were going to deliver a valuable feature that met the needs of our users, and our developers, and we were able to get to that point very quickly.&lt;/p&gt;
&lt;p&gt;All modern books preach the need for an onsite customer. This experience of two extremes solidified the idea in my mind. Your team can definitely work more effectively with an onsite customer. Not a proxy, nor a proxy to the proxy, but the real decision-maker, in the trenches with your team, day in and day out.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-6405454545945809799?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/6405454545945809799/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/11/real-onsite-customer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/6405454545945809799'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/6405454545945809799'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/11/real-onsite-customer.html' title='A REAL Onsite Customer'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3653104956070157954.post-8664686432650251288</id><published>2007-10-31T00:45:00.000-05:00</published><updated>2007-11-02T16:37:05.320-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='consulting'/><title type='text'>RTFM</title><content type='html'>&lt;p&gt;Yesterday, a colleague sent out an email to the group, asking for help on a certain topic. Over IM, I asked if he was doing this for a particular scenario, which he was. So I suggested he use a feature of the tool we are using. He said he wasn't aware of that feature, so I said "RTFM" (read the frickin' manual).&lt;/p&gt;
&lt;p&gt;This didn't go over very well with him. His first reaction was to lecture me, never to do something like this again. I didn't need a lecture, but I apologized, trying to quell an escalating situation. Later, after he calmed down, he explained that this triggered memories of bad relationships with past colleagues, and that he didn't want our rapport to get out of hand. Fine, I can accept that. But this situation got me to thinking about two things: why I said RTFM to begin with, and how I could have said the same thing in a more gentle manner.&lt;/p&gt;
&lt;p&gt;As a consultant, I know alot is expected of me by the client. There is a reason they are paying more for my services than they pay their employees, and I have an obligation to keep up my end of the deal. I expect the same of the other consultants on the project. In this case, I expected my colleague to know the tools that we are working with, and to have at least gone through the manuals and have been familiar with the concepts. Staff employees often expect to be sent to training. As consultants, we need to go out of our way to quickly learn as much as we can about the tools and technologies we are using. We also need to be able to pass that knowledge on to our teammates, whether they are consultants or employees. It's by this transfer of knowledge that the entire team gets better, and the entire project can go smoother.&lt;/p&gt;
&lt;p&gt;Which brings me to my next thought: how could I have been more effective in that communication. After thinking about it, I should have said something along these lines: &lt;blockquote&gt;You can use this feature. You should be able to find information about this in the manual. Take a look, and let me know if you have any questions.&lt;/blockquote&gt;It would have gotten the point across much better. It also would have been in line with the kind of response my colleague expected. Even though I don't have any particular title, I am often perceived as a leader on our team. To fulfill my part of being a leader, I should have used the gentler statement to get my point across. &lt;p&gt;&lt;/p&gt;
&lt;p&gt;The work we do executing projects and developing software is difficult enough. We don't need to make it any more difficult by creating problems among our colleagues. As a team leader, whether by title or by perception, we need to excel at increasing the knowledge of our entire team (and organization), and working towards project success.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3653104956070157954-8664686432650251288?l=blog.milotodorovich.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://blog.milotodorovich.com/feeds/8664686432650251288/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://blog.milotodorovich.com/2007/10/rtfm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8664686432650251288'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3653104956070157954/posts/default/8664686432650251288'/><link rel='alternate' type='text/html' href='http://blog.milotodorovich.com/2007/10/rtfm.html' title='RTFM'/><author><name>Milo Todorovich</name><uri>http://www.blogger.com/profile/02278592929556461837</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/_DjXZItwZSe8/SxbAKDDNnKI/AAAAAAAAAAM/_Gf7xVtjYoI/S220/P1012033.JPG'/></author><thr:total>0</thr:total></entry></feed>
