<?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-8424060401701893376</id><updated>2012-02-10T09:57:40.062Z</updated><category term='&quot;sofware craftsmanship&quot; craftsmanship &quot;software engineering&quot;'/><category term='Cohesion OOP &quot;Object-Oriented Programming&quot; &quot;Software Craftsmanship&quot;'/><category term='OOP DDD Software Craftsmanship'/><category term='TDD DSL &quot;Software Craftsmanship&quot; LSCC Fluent'/><title type='text'>Crafted Software</title><subtitle type='html'>Where how it is done is as important as having it done.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-7585146466489739275</id><published>2012-02-06T22:11:00.000Z</published><updated>2012-02-06T22:11:27.232Z</updated><title type='text'>Code coverage is a side effect and not an end goal</title><content type='html'>&lt;br /&gt;&lt;div class="p1"&gt;In my previous life as a consultant, one of our clients hired us to "increase the code coverage" of their code base. We would not develop any new features or make any changes. They just wanted us to write tests. Basically they wanted us to bring the coverage up to 70%. Why 70% you may ask. Probably because someone pulled a finger out of his or her back orifice, sniffed it and thought: Hmm.. this definitely smells like 70%.&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;Regardless the stupid and random number, as consultants we actually did our best to actually write proper and meaningful tests. They did not want us to refactoring. Just tests. The developers themselves (client employees) would not be writing tests. Probably too busy doing proper work, breaking the tests after each commit. Thanks for them, they had the monkeys here fixing the tests. The reason for that was that the same person with the smelly finger decided that everyone would have a higher bonus if they reached 70% test coverage.&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;More recently, I've seen a similar behaviour.&amp;nbsp;Keeping a close eye on the metrics provided by&amp;nbsp;&lt;a href="http://www.sonarsource.org/"&gt;Sonar&lt;/a&gt;,&amp;nbsp;that does a great job by the way, managers and senior developers are constantly pushing the teams to improve the quality of the code. Time is allocated in every&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Scrum_(development)#Sprint"&gt;sprint&lt;/a&gt;&amp;nbsp;and developers are asked to increase the code coverage.&amp;nbsp;The intention behind it is good, right? Bit by bit the application get better. Awesome.&amp;nbsp;&lt;/div&gt;&lt;div class="p1"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;The idea was to improve the quality and reliability of the application. Unfortunately, developers with the urge to finish the task, just focused on the "increase code coverage" part of the task. They then started writing "tests" that were not asserting anything. Basically what they were doing was writing some code inside a test method that would invoke public methods in classes but would not test the outcomes or side effects of those method invocations.&amp;nbsp;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p1"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;What does code coverage measure?&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;It measures the percentage of the code &lt;i&gt;exercised&lt;/i&gt;&amp;nbsp;by code written inside test methods. It does not measure the percentage of code &lt;i&gt;tested&lt;/i&gt; by testing code. Having a test method that just invokes a public method in a class and &lt;i&gt;does not&lt;/i&gt; test (assert/verify) anything, will make the code coverage go up but &lt;i&gt;will not&lt;/i&gt; test the system. This, of course, is totally pointless since it does not test if the public method invoked actually does what it is supposed to do or if it does anything at all.&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Why do we invest time in writing tests?&lt;/span&gt; &lt;/b&gt;(In no particular order)&lt;/div&gt;&lt;div class="p3"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Make sure we understand what the application does, according to the executable requirements (tests);&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure that the application still does the right thing after we make changes to it or indicates possible areas of conflicts (failing tests);&lt;/li&gt;&lt;li&gt;Make sure we have regression test;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure that in a click of a button we can know if the application is working correctly;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure that we have a quick and small feedback loop in terms of quality and correctness of our application;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure the application is simplified and easily maintainable, via testing and refactoring;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure the complexity of the application is spread thin instead of having localised big balls of mud that we are scared to touch;&lt;/li&gt;&lt;li&gt;Make sure that we can easily add new features quickly;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure that we extend the ROI in our software, extending its lifespan;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure that our software does not rot, impeding and/or slowing down business progress;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Make sure that our clients are happy with the software;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="p3"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;By the way, when I mention test, I mean all types/levels of tests, not just unit.&lt;/div&gt;&lt;div class="p3"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;What should we focus on?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;blockquote class="tr_bq"&gt;&lt;span style="background-color: white; color: #333333; font-family: HelveticaNeue, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 18px;"&gt;&lt;i&gt;Focus on what the metrics are telling you and not on improving the numbers. Focusing on numbers may give you a false impression of quality.&lt;/i&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;div class="p2"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="p3"&gt;My point here is that the focus should be on TESTING the application and not in increasing its code coverage metric. We need to make sure we capture the behaviour of our application via tests, expressing its intent, refactoring to make it better. Tests (at all levels) should tell you a story about the behaviour of your application. And guess what? In writing tests for your application, besides all the benefits mentioned above, your code coverage metric will still go up as a side effect.&amp;nbsp;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-7585146466489739275?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/7585146466489739275/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2012/02/code-coverage-is-side-effect-and-not.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7585146466489739275'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7585146466489739275'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2012/02/code-coverage-is-side-effect-and-not.html' title='Code coverage is a side effect and not an end goal'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-3639547021722957573</id><published>2011-10-28T00:19:00.000+01:00</published><updated>2011-10-28T00:37:15.310+01:00</updated><title type='text'>Mentorship in Software Craftsmanship - part 3</title><content type='html'>In previous posts I covered:&lt;br /&gt;Part 1: &lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html"&gt;Mentor and mentee roles, gains and sacrifices, mutual respect&lt;/a&gt;&lt;br /&gt;Part 2: &lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html"&gt;How to choose mentors and mentees and mentorship misconceptions&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Walking the long road together (or at least part of it)&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Once the relationship between mentor and mentee is established, it is fair to say that they will be in a journey together. Every software craftsman is on a personal journey towards mastery. They are all walking the &lt;a href="http://ofps.oreilly.com/titles/9780596518387/walking_the_long_road.html"&gt;long road&lt;/a&gt;. Both mentor and mentees will be learning while they share part of their journey with each other.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;What mentors and mentees should do during the mentorship?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Well, this may vary a lot depending of the type of mentorship. In general, they are expected to write code, loads of code. Ideally they should build something together, where the mentee should be the most active in terms of writing the code. The mentor is expected to pair-program with the mentee whenever possible and to be reviewing his code.&lt;br /&gt;&lt;br /&gt;Agreeing on creating an application would probably be the best option since that would involve not just writing the code but also thinking about requirements, being able to prioritize, defining a development process, deployment strategies, production environment and everything else that is related to a software project in the real life.&lt;br /&gt;&lt;br /&gt;Working on katas is also a valid. It's a simpler and quicker approach for the mentee to learn basic skills. This could be used when the mentees are interested in the basics of TDD, naming, refactoring, programming languages paradigms, etc. However, after learning a few basic skills using katas, they should aim to do something larger that really can mimic the sort of applications they would be working on in their professional environments.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Establishing goals and tracking progress&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Establishing goals is definitely a good practice in a mentorship. It keeps mentor and mentees focused in whatever they want to achieve. Working towards an objective is always the best way to study and learn something. Goals should be achievable and used to motivate and direct the menteed and not to be treated as a hard deadline. However, they should be as concrete as they can be, for example, writing an application with features X, Yand Z and have it deployed into production or doing a number of katas using TDD, write blog posts, read books, submit patches to open source projects, or whatever the pair agrees on.&lt;br /&gt;&lt;br /&gt;It's important that progress is tracked so both mentor and mentees can see how they are getting on and how much the mentee is evolving. Tracking progress is all about feedback. The quicker and shorter the feedback loop is, the better. It's also a good tool to trigger conversation about improvements and refinements.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;How long a mentorship should last?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately that's another question that does not have an exact answer. This will depend a lot on the type of mentorship, how much the mentee wants to learn from the mentor and also how much the mentor has to offer.&lt;br /&gt;&lt;br /&gt;Some say that this should be a lifetime commitment, some say that it should last between 2 to 5 years and some say that it could be as short as a few months. Some mentorships start with very technical and specific things like learning the basics of a language or test disciplines. However they can evolve to an entire project lifecycle or even to a longer term career advice, networking, help with books and conferences, etc.&lt;br /&gt;&lt;br /&gt;I, personally, would never try to define that upfront. Just enjoy the journey and let time tell when the mentorship should terminate.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;How and when does it terminate?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;For the majority of the relationships, both mentor and mentees at some point need to continue their journey in separate ways. This does not mean that they will never talk to each other again or that they don't like each other. This just means that they need to move on, teach or learn from other people. Also, we all change our minds in terms of what our next steps would be and we need to react to that.&lt;br /&gt;&lt;br /&gt;One important thing is that regardless who wants to terminate the relationship, this termination should be explicit. It should be clear to both parts that the mentorship is over. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Professionalism, Reputation and Public recognition&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Software craftsmanship is &lt;a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html"&gt;all about professionalism&lt;/a&gt;&amp;nbsp;and it is almost impossible to talk about professionalism without talking about reputation.&lt;br /&gt;&lt;br /&gt;Throughout the mentorship, it is important that the mentor advertises the progress of her mentee. Mentors should public recognise all the skills acquired by the mentee, what would help the mentee to start building her own reputation. However, mentors also need to be aware that every time they vouch for someone, they are also putting their reputations on the line. Mentees are also expected to be recognising their mentors for all the things they've been learning. This mutual recognition is one of the things that may help both to build their reputations.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Raising the bar&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Mentorship is at the heart of software craftsmanship and this is probably one of the most efficient ways for us, developers, to help raising the bar of our industry. Sharing our knowledge and experiences with each other is what will help us learn from our mistakes and successes.&lt;br /&gt;&lt;br /&gt;We probably can teach many things to someone in a fraction of the time that took us to learn them. With this, mentees could absorb a lot of knowledge in a much shorter space of time, making them, overtime, a much more complete professional than any of the mentors she had in her career.&lt;br /&gt;&lt;br /&gt;Regardless of our level of seniority or if we are being mentored by someone else, if we all take the responsibility to mentor someone, we will all be helping to raise the bar of our industry.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;For previous parts of this blog post, please check:&lt;br /&gt;&lt;br /&gt;Part 1:&amp;nbsp;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html"&gt;Mentor and mentee roles, gains and sacrifices, mutual respect&lt;/a&gt;&lt;br /&gt;Part 2:&amp;nbsp;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html"&gt;How to choose mentors and mentees and mentorship misconceptions&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-3639547021722957573?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/3639547021722957573/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/10/mentorship-in-software-craftsmanship.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/3639547021722957573'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/3639547021722957573'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/10/mentorship-in-software-craftsmanship.html' title='Mentorship in Software Craftsmanship - part 3'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-1110350989491211272</id><published>2011-10-23T02:15:00.000+01:00</published><updated>2011-10-23T02:18:02.014+01:00</updated><title type='text'>Installing Io language on Ubuntu</title><content type='html'>Since I'm new to Ubuntu and I had a hard time installing &lt;a href="http://iolanguage.com/"&gt;Io language&lt;/a&gt;, I've decided to record my steps. Hopefully I'll remember all of them and other people won't struggle as much as I did. I'm running Ubuntu 11.10.&lt;br /&gt;&lt;br /&gt;The main problem I had was that I did not have all the dependencies needed to install Io and the installation was failing. The dependencies are&amp;nbsp;&lt;a href="https://github.com/lloyd/yajl"&gt;yajl&lt;/a&gt;&amp;nbsp;and &lt;a href="http://libevent.org/"&gt;libevent&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;If you've got then installed, you can skip the next steps.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;NOTE&lt;/b&gt;: You will need to have cmake and make. You can install them running the following commands from the terminal:&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo apt-get install cmake&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo apt-get install make&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Installing yajl&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download yajl from here:&amp;nbsp;&lt;a href="https://github.com/lloyd/yajl/downloads"&gt;https://github.com/lloyd/yajl/downloads&lt;/a&gt;&lt;/li&gt;&lt;ol&gt;&lt;li&gt;In my case it was:&amp;nbsp;lloyd-yajl-2.0.1-0-gf4b2b1a.zip&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;Extract it into a folder.&lt;/li&gt;&lt;li&gt;Open the terminal and go to the folder you extracted yajl&lt;/li&gt;&lt;li&gt;Run the following commands&lt;/li&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mkdir build&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cd build&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cmake ..&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo make install&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;br /&gt;For more information, please check:&lt;br /&gt;&lt;a href="https://github.com/lloyd/yajl"&gt;https://github.com/lloyd/yajl&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/lloyd/yajl/blob/master/BUILDING"&gt;https://github.com/lloyd/yajl/blob/master/BUILDING&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Installing libevent&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download libevent from here:&amp;nbsp;&lt;a href="http://libevent.org/"&gt;http://libevent.org/&lt;/a&gt;&lt;/li&gt;&lt;ol&gt;&lt;li&gt;In my case it was:&amp;nbsp;libevent-2.0.15-stable.tar.gz&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;Extract it into a folder&lt;/li&gt;&lt;li&gt;Open the terminal and go to the folder you extracted libevent&lt;/li&gt;&lt;li&gt;Run the following commands&lt;/li&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;./configure&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;make&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo make install&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;br /&gt;For more information please check:&lt;br /&gt;&lt;a href="http://libevent.org/"&gt;http://libevent.org/&lt;/a&gt;&lt;br /&gt;Also check the README file inside the .tar.gz for your version&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Installing Io language&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;You can go to the &lt;a href="http://iolanguage.com/"&gt;Io language website&lt;/a&gt; and download the language&amp;nbsp;or click &lt;a href="http://github.com/stevedekorte/io/zipball/master"&gt;here&lt;/a&gt; to go start downloading it. As there is no Ubuntu package for that, you will be downloading the Io's source code. This will point to &lt;a href="https://github.com/stevedekorte/io"&gt;Steve Dekorte's version&lt;/a&gt;.&amp;nbsp;I ended up downloading &lt;a href="https://github.com/jeremytregunna/io"&gt;Jeremy Tregunna's version&lt;/a&gt;. It should work the same. Check each one is the most up-to-date.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download the Io version here:&amp;nbsp;&lt;a href="https://github.com/jeremytregunna/io/zipball/master"&gt;https://github.com/jeremytregunna/io/zipball/master&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Extract it into a folder.&lt;/li&gt;&lt;li&gt;Open the terminal and go to the folder you extracted Io&lt;/li&gt;&lt;li&gt;Run the following commands:&lt;/li&gt;&lt;ol&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;mkdir build&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cd buil&lt;/span&gt;d&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cmake ..&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo make install&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/ol&gt;&lt;br /&gt;&lt;b&gt;IMPORTANT&lt;/b&gt;: When running '&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;cmake ..&lt;/span&gt;', you may get a few errors. Even then, try to run '&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo make install&lt;/span&gt;'. Some libraries may fail to compile because they are OS specific.&lt;br /&gt;&lt;br /&gt;For mode information please check:&lt;br /&gt;&lt;a href="http://iolanguage.com/"&gt;http://iolanguage.com/&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/stevedekorte/io"&gt;https://github.com/stevedekorte/io&lt;/a&gt;&lt;br /&gt;&lt;a href="https://github.com/jeremytregunna/io"&gt;https://github.com/jeremytregunna/io&lt;/a&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Updating ld.so.conf&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Now we just need to update ld.so.conf so Io can be accessed from anywhere in your computer.&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;From the terminal, type the following command: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo gedit /etc/ld.so.conf&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Add the following line to the file:&amp;nbsp;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;include /usr/local/lib&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Save and close the file&lt;/li&gt;&lt;li&gt;From the terminal run the following command: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;sudo&amp;nbsp;ldconfig&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Running Io&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;That's it. Hopefully now you will be able to open a terminal window and type: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;io&lt;/span&gt;&lt;br /&gt;You should see the Io runtime environment: &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;Io&amp;gt; _&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-1110350989491211272?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/1110350989491211272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/10/installing-io-language-on-ubuntu.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1110350989491211272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1110350989491211272'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/10/installing-io-language-on-ubuntu.html' title='Installing Io language on Ubuntu'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-3971827391397710312</id><published>2011-10-10T02:14:00.000+01:00</published><updated>2011-10-30T17:00:50.757Z</updated><title type='text'>Mentorship in Software Craftsmanship - part 2</title><content type='html'>&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In&amp;nbsp;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html"&gt;part one&lt;/a&gt;&amp;nbsp;I gave a bit of background history and also described the roles and responsibilities of mentors and mentees according to the Software Craftsmanship principles. In this second post I'll be convering a few other areas related to the relationship itself. Remember that the focus here is on mentorships outside work. Let's start from the beginning.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;How do we find mentors or mentees?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;That's probably the most difficult question to answer. I can think in three possibilities (in no particular order):&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Try to find someone that works with you in a daily basis. It will make the approach easier.&lt;/li&gt;&lt;li&gt;Via user groups and communities. If you are an active member of a user group or community you will have the opportunity to meet a lot of people and maybe find the mentor or mentee you are looking for.&lt;/li&gt;&lt;li&gt;Via indication: A friend could recommend/introduce you to someone.&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Choosing a mentor&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;Although not a rule, normally, in Software Craftsmanship, it is the mentee that chooses the mentor or, at least, start the conversation. The mentee needs to have an idea of the path he wants to take. For example, he may want to learn more about mobile development, work as a consultant, work in high-performance low-latency&amp;nbsp;systems, learn about gaming development, improve his automated testing techniques or, in the best case, just learn how to become a better developer. Whatever the mentee's ambitions are, the mentee needs to make sure that his future mentor is a person that can provide the knowledge he or she is looking for.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Unfortunately, this may be easier said than done. Depending where the mentee is in his career, he may not know exactly what he wants. He may not even know what options he has. Although good developers are good developers and the foundation and priciples of software development always apply, we all know that the skills set used in different types of systems can vary a lot. A well experienced developer that spent the majority of his career doing web-development and became an expert in user experience may take a while to perform well in a completely server-side, asynchronous application with no GUI. Working on an application that heavily rely on algorithms and that don't use any database can be totally different from developing a mobile client application. The same way that working for a consultancy company can be very different from working for a bank or a startup.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Those are some of the things that developers at early stages of their careers may not even have a clue. If you are at this stage in your career, the best suggestion is that you focus purely on being a great developer and learn the basics. Things like Test-Driven Development, clean code, refactoring, Object-Oriented principles, different languages and paradigms. Once you have that, it will be easier for you to choose your next move.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Choosing a mentor involves is not an easy task. Maybe a single mentor won't be able to teach everything a mentee wants to know. Mentees should focus on their very next step(s) instead of focusing in everything they want to learn throughout their entire career. Mentees may change their minds quite often as soon as new opportunities and options are presented to them. They should keep their options open and choose a different mentors as time goes by. &amp;nbsp; &lt;/div&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Choosing a mentee&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Mentors, before accepting a mentee, should ask themselves: Would I be able to dedicate time to this person? Can I really help his or her career? If the answer is yes, fantastic.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The first thing to look for in a mentee is &lt;i&gt;passion&lt;/i&gt;. Since a mentor will be allocating time to help someone, they should make sure that this person deserves their help. Make sure that the mentee is committed to be better.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Another thing mentors need to decide is what sort of seniority level their future mentee should have. Some mentors will prefer to take graduates, others prefer juniors with one or two years of experience and others prefer to get seniors or mentees on the verge of becoming seniors.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Choosing a mentee is a very personal thing and different mentors will have completely different criteria. &amp;nbsp;If the mentor already knows the mentee, than it is easier. When the mentor doesn't know the mentee I could suggest a few options that could either be combined or used independently:&lt;/div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li style="text-align: justify;"&gt;Introduction letter: The mentor could ask the mentee for a summary of his career so far (not a CV). In this summary, the mentee would describe what he has done, where he thinks he are in his career, the things he learnt, provide (if any) links to his public profile like github account, twitter, blog, web/mobile applications and most importantly, what he expect from the mentor.&lt;/li&gt;&lt;li style="text-align: justify;"&gt;Coding challenge: The mentor can set up a challenge before considering to speak and accept a mentee. E.g. the mentee, using his preferred language, needs to write a simple blog or wiki application, have it deployed in somewhere (heroku, cloudbees, Google App Engine, Amazon Beanstalk, etc) and code should be public (github, for example). Or it could be simpler like solving a few katas using two different languages or anything along these lines.&lt;/li&gt;&lt;li style="text-align: justify;"&gt;Blog: Mentee should create a blog, if he or she does not have one, and publish a few posts related to things he has been learning on his own.&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The mentor, if going down this route, should set the challenges according to the level of seniority he is expecting from the mentee.&amp;nbsp;Once the mentor is satisfied with the initial effort by the potential mentee, he could decide if he is going to accept or not the mentee.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Mentorship common misconceptions&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b style="font-weight: bold;"&gt;&lt;i&gt;The mentor is not better than the mentee.&lt;/i&gt;&lt;/b&gt; In general the mentor will have more knowledge and experience in the areas where the mentee has chosen to be mentored. However, the mentee can easily have more knowledge than the mentor in other areas. Mentees should not expect the mentor to have all the answers to all the problems and mentors should not be naive to think that the mentee doesn't know anything. Both mentors and mentees have skills and limitations and this needs to be understood by both parts.&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;i style="font-weight: bold;"&gt;&lt;b&gt;Mentors should not be looking for themselves a few years younger.&lt;/b&gt;&lt;/i&gt;&lt;b&gt; &lt;/b&gt;This can be frustrating for the mentor. People are different and the mentor will be missing out when not being more open to the type of mentee he or she is prepared to take on board. There is no reason to be so restrictive. Mentoring someone with different personality, possibly slightly different ambitions can be extremelly enriching for both mentors and mentees. However it is important that both have same values and principles.&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b style="font-weight: bold;"&gt;&lt;i&gt;Mentees should not expect that mentors will change their lives.&lt;/i&gt;&lt;/b&gt;&lt;b&gt; &lt;/b&gt;The mentors will be there for the mentees, giving them advices and teaching what they know but it is up to the mentee to decide what to do with it. Mentees should do their part to improve and not think they are going to be spoon-fed by mentors. It's up to the mentee to look after his or her own career.&amp;nbsp;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;In the next posts I'll be covering things like different types of mentorship, activities that could be performed by mentors and mentees, public recognition, professional reputation, graduation, mentorship duration, how this could change our industry and a few other points. Watch this space.&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;i&gt;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentorship-in-software-craftsmanship.html"&gt;Part 3: What mentors and mentees should do, how long it should last, how does it end public recognition and reputation&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html"&gt;Part 1: A bit of history, roles of the mentors and mentees, gains and sacrifices and mutual respect&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/div&gt;&lt;b&gt;&lt;/b&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-3971827391397710312?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/3971827391397710312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/3971827391397710312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/3971827391397710312'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html' title='Mentorship in Software Craftsmanship - part 2'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-5703527884114885147</id><published>2011-10-05T00:45:00.000+01:00</published><updated>2011-10-30T16:57:26.788Z</updated><title type='text'>Mentorship in Software Craftsmanship - part 1</title><content type='html'>&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: x-large;"&gt;&lt;b&gt;How's mentorship seen in Software Craftsmanship?&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;First, a little bit of background and&amp;nbsp;metaphor&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In the medieval times, apprentices would work in workshops an would be mentored by senior craftsmen (journeymen) or by the master craftsman himself. The apprentice had the responsibility to learn, observing the master's and everyone else's work, questioning everything and practising as much as he could. This was different from the teacher/student relationship where the teacher had the responsibility to teach. Here it was the apprentice that had to push his own development.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The apprentice, mentored by the master, would learn and refine his skills on a daily basis. Over time, the master would reach his limit as in what he could teach the apprentice and the knowledge and skills gap between both would not be that big any more. The master would then publicly recognise the apprentice as a professional that could take on work on his own and would deliver it with the same quality that the he would deliver himself. The master, at this point, would be putting his own reputation on the line since he was the one that trained the apprentice and was now vouching for his ability.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This would be the graduation point. Now the apprentice was ready to start his own journey, as a journeyman. As a journeyman, he would then go from town to town, work for and learn from different masters up to a point that he would be recognised by all of these masters and other craftsmen as a master himself. He would then be ready to have his own shop and start mentoring other journeymen and apprentices.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Back to the present&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;From now on, instead of master/apprentice, I'll be using mentor/mentee. The main reason is that you don't need to be a master craftsman to mentor someone. You also don't need to be an apprentice to have a mentor. Besides that, each developer has different areas of expertise. They can be very senior in certain areas and completely ignorant in other areas. As we all know, software development is not as limited as a blacksmith's workshop in the medieval times.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;The role of the mentor&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Deciding to mentor someone is a big responsibility. The role of a mentor is more than just be available on the phone and answer a few questions here and there. Although this can be very helpful, the role of a mentor goes way beyond than that. The mentor has the responsibility to make the mentee a good professional and that includes the technical and the personal side. More than just teaching the mentee a specific framework or technique, the mentor will also be teaching the mentee how to become a professional software developer, including ethics and code of conduct. From the technical perspective, the mentor will do his best to teach everything he knows. If they don't work together, the mentor is expected to reserve formal time to work with the mentee. From the personal perspective, a mentor should help the mentee in his career (journey), giving some guidance, advices, opening doors or showing the doors he has already opened himself, introducing the mentee to his own professional circle and whatever else the mentor judges that can be important for the mentees. &amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;The role of the mentee&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The mentee is expected to do whatever he or she can to learn from the mentor. The mentee must be open-minded, be able to take criticism on board, be able to listen and also be very proactive in terms of perpetuating the knowledge. Practice is key. The mentee is expected to practice as much as possible, making him or herself better everyday. Mentees are also expected to produce something. Something where the mentor can measure their progress and possibly identify areas of improvement. Besides the direct benefits to the mentee, this is also the best way to keep mentors excited to be helping. Mentees must show passion and a clear desire to learn otherwise mentors will probably loose interest and find it a waste of time. &amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Gains and sacrifices&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Mentors have the opportunity to&amp;nbsp;perpetuate&amp;nbsp;their knowledge since they need to organise their ideas to teach someone. Mentors will also need to be studying and&amp;nbsp;practising hard to keep feeding his mentee, what obviously is a good thing. They will get the satisfaction of helping developers to progress in their careers, with good foundation, ethics and professionalism. They will be doing their part in rasing the bar of our industry, training the next generation, and this, on its own, is a very noble cause. But there are sacrifices and the main one is time. Mentors are expected to dedicate time to their mentees. If mentor and mentee work together in a daily basis, they won't need much time outside work. However, if they don't, mentors need to be clear they will need to find and reserve time for their mentees, ideally in a regular basis.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Mentees have the opportunity to speed up their development as professional software developers. They benefit from the mentor's experience acquired over the years, shortening the time they would take to learn something and avoiding to commit the same mistakes. They also have someone they trust that could offer a different perspective on the things they are going through (technical issue, problem with a manager, process, bureaucracy, deadlines, estimation, etc).&amp;nbsp;Without any scientific evidence to back me up, I would dare to say that with the right attitude from both parts and a good amount of time together, the mentee could learn in two years what the mentor learned in ten. That gives the mentees a massive head-start in their careers. Time should never be called a sacrifice from the mentees perspective. When someone is getting a lot of knowledge and help for free, possibly saving years of their careers, complaining about time (or lack of it) would be very short-sighted, to say the least.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;&lt;b&gt;Mutual Respect&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Both mentors and mentees should respect each other. In order to have a healthy and prosperous relationship, there must be a&amp;nbsp;commitment from both parts. This commitment is the mutual respect. The mentor shows respect with regular interactions with the mentee and time commitment.&amp;nbsp;The mentee shows respect with his commitment to excel and demonstration of progress. That's the minimum a mentee could do for someone that is sacrificing time with family and friends in order to help him.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;In following posts I'll be exploring things like different types of mentorship, activities that could be performed by mentors and mentees, criteria for choosing a mentor and a mentee, public recognition, professional reputation, graduation, mentorship duration, how this could change our industry and a few other points. Watch this space.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html"&gt;Part 2: Choosing a mentor and a mentee and also common mentorship misconceptions&amp;nbsp;&lt;/a&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;a href="http://craftedsw.blogspot.com/2011/10/mentorship-in-software-craftsmanship.html"&gt;Part 3: What mentors and mentees should do, how long it should last, how does it end public recognition and reputation&lt;/a&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-5703527884114885147?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/5703527884114885147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/5703527884114885147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/5703527884114885147'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html' title='Mentorship in Software Craftsmanship - part 1'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-633549822802551223</id><published>2011-09-20T09:59:00.000+01:00</published><updated>2011-09-23T01:40:28.036+01:00</updated><title type='text'>LSCC's First Code Retreat</title><content type='html'>On September 10th we had the London Software Craftsmanship Community's &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/27600561/"&gt;First Code Retreat&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Lsl8mfpVWMQ/TnvUSzkbV8I/AAAAAAAAAMY/l-KZrJMJhyw/s1600/coderetreat01.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://4.bp.blogspot.com/-Lsl8mfpVWMQ/TnvUSzkbV8I/AAAAAAAAAMY/l-KZrJMJhyw/s320/coderetreat01.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;We had 22 passionate and talented developers working in Java, C#, Ruby, Python and JavaScript. Some of them travelled two hours, waking up as early as 5am, to come to the code retreat and many others travelled at least one hour to be there.&lt;br /&gt;We started at 8am, with breakfast and informal discussions. Then we had a quick introduction, where I explained the purpose of the day and used some of Corey Haines wise words. Here's a quick summary:&lt;br /&gt;&lt;br /&gt;"In our day-to-day job, we need to get things done. We need to achieve something and deliver something. And we want and are committed to it. In order to do so, we end up cutting corners. So that's how we code. We sacrifice quality in order to deliver "faster". &lt;br /&gt;&lt;br /&gt;But now imagine you have all the time in the world and all the knowledge in the world. Imagine what would be your idea of perfect code. Now compare it to what you do and how you code in your day-to-day job.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-cY1fqDBVpk8/TnhRPsHkJSI/AAAAAAAAAMI/sYlqzPRGwHs/s1600/PerfectCode_Gap.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="217" src="http://4.bp.blogspot.com/-cY1fqDBVpk8/TnhRPsHkJSI/AAAAAAAAAMI/sYlqzPRGwHs/s320/PerfectCode_Gap.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;This gap is the measure of how much you suck. The bigger the gap is, the more you suck. The smaller the gap is, the less you suck. :)&lt;br /&gt;&lt;br /&gt;But today, during the code retreat, is the day that we will practice perfect code. Today we don't need to deliver. Today we have no pressure, besides writing perfect code. That means the objective of a hands-on session like that, is not to finish the exercise, but to practice new approaches, expand our horizons and learn from others. Today we will reduce the gap from what we do in our day-to-day job and the perfect code, providing better value for our customers and being better professionals. "&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;It's not practice that leads to perfection, it's perfect practice that leads to it. &lt;/blockquote&gt;&lt;br /&gt;I also explained the four rules of simple design:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - All tests need to pass;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - No duplication;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Reveals intention (good naming)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - Small&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;blockquote&gt;I have made this letter longer than usual, only because I have no time to make it shorter. &lt;br /&gt;&lt;div style="text-align: right;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;Blaise Pascal (sometimes also attributed to &lt;/i&gt;&lt;i&gt;Mark Twain&lt;/i&gt;&lt;i&gt;)&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Format of the day&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-YXd0AQq2ink/TnvSe1Rp8BI/AAAAAAAAAMQ/PDDfXXsYCx8/s1600/coderetreat04.jpg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-YXd0AQq2ink/TnvSe1Rp8BI/AAAAAAAAAMQ/PDDfXXsYCx8/s320/coderetreat04.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;After a good breakfast, developers formed pairs and worked on the &lt;a href="http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life"&gt;Conway's Game of Life&lt;/a&gt;. We had three sessions in the morning, then lunch and another three sessions in the afternoon. Each session lasted 45 minutes and had a retrospective afterwards where developers discussed their approaches and problems they faced. Then developers deleted the code from their machines. In each session new pairs were formed and worked on the same problem. &lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;First session&lt;/b&gt;: It was free. Basically the pairs worked with no constraints just to make themselves familiar with the problem.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Second session&lt;/b&gt;: As a challenge, they were asked to use different data structure other than arrays and we introduced the concept of "primitive obsession".&lt;/li&gt;&lt;li&gt;&lt;b&gt;Third session&lt;/b&gt;: Developers were asked not to use flags and use polymorphism instead. This was to promote the exploration of abstractions.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Lunch&lt;/b&gt;: We had nice sandwiches and deserts from a good delicatesse. We had 1.5 hours for lunch. During lunch time, some more senior developers said they haven't been challenged enough so I changed the strategy.&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Fourth session&lt;/b&gt;: In order to satisfy developers from different levels, I asked them to come up with a list of challenges and each pair would then decide which challenge they would take on, according to their level of expertise. The list they came up with was;&lt;ul&gt;&lt;li&gt;Maximum 3 lines of code per method;&lt;/li&gt;&lt;li&gt;Object-Oriented Programming to extreme.&lt;/li&gt;&lt;li&gt;No getters / setters / properties&lt;/li&gt;&lt;li&gt;Every line must start with "return" or "final" (Java/C# - functional style)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Fifth session&lt;/b&gt;: TDD as if you meant it, that means, all code needs to be written inside the test method and then refactored out.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Sixth session&lt;/b&gt;: Developers were free to do whatever they wanted again but many decided to use some of the challenges from sesson four.&amp;nbsp;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Pub&lt;/b&gt;&lt;/li&gt;&lt;/ul&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-WEJi5aGYe5Y/TnvSgI0WjUI/AAAAAAAAAMU/lTwLG1JckgE/s1600/coderetreat11.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-WEJi5aGYe5Y/TnvSgI0WjUI/AAAAAAAAAMU/lTwLG1JckgE/s320/coderetreat11.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;During the sessions, I also asked them to try different testing approaches: outside-in and inside-out. The reason was to compare how different the design would turn up. They were also encouraged to pair-program with developers from other languages, what is an amazing experience and broadens our mind.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The experiment with each pair choosing the challenge on session four had a mixed feedback. Some developers enjoyed it because they could push themselves. Others said that the retrospective was not so good since pairs were working with different challenges and could not relate to the problems and solutions exposed by other pairs. This is something I'll need to think about for future code retreats. How can I balance the challenges so everyone feels, well, challenged.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-SWijxD3WSjE/TnvUT2_5kTI/AAAAAAAAAMc/5pkN-iFn3-U/s1600/coderetreat15.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" height="240" src="http://2.bp.blogspot.com/-SWijxD3WSjE/TnvUT2_5kTI/AAAAAAAAAMc/5pkN-iFn3-U/s320/coderetreat15.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;Overall, we all had a fantastic day. There were many very interesting discussions during the retrospectives and, according to the feedback, everyone learnt something. I definitely learnt a lot myself and facilitating my first code retreat was an amazing experience that I want to repeat. &lt;br /&gt;&lt;br /&gt;I would like to thank &lt;a href="http://valtech.co.uk/"&gt;Valtech&lt;/a&gt; for providing the venue and for the full sponsorship. They provided us everything we needed for this event and were key for its success. &lt;br /&gt;&lt;br /&gt;For the full list of attendees, details about the event and more photos, please check &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/27600561/"&gt;http://www.meetup.com/london-software-craftsmanship/events/27600561/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-633549822802551223?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/633549822802551223/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/09/lsccs-first-code-retreat.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/633549822802551223'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/633549822802551223'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/09/lsccs-first-code-retreat.html' title='LSCC&apos;s First Code Retreat'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-Lsl8mfpVWMQ/TnvUSzkbV8I/AAAAAAAAAMY/l-KZrJMJhyw/s72-c/coderetreat01.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-4456837571825244858</id><published>2011-08-20T01:03:00.000+01:00</published><updated>2011-08-20T01:11:44.725+01:00</updated><title type='text'>One year of London Software Craftsmanship Community (LSCC)</title><content type='html'>&lt;blockquote&gt;&lt;span class="indquote_link"&gt; &lt;i&gt;Without a sense of caring, there can be no sense of community.&lt;/i&gt;&lt;/span&gt;&lt;i&gt;&lt;span class="author_text"&gt; - Anthony Burgess&lt;/span&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Happy Birthday, LSCC!!!! &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;On 18th of August 2011, the &lt;a href="http://www.londonswcraft.com/"&gt;London Software Craftsmanship Community&lt;/a&gt; completed one year. And what a great year we had! &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;How did it all start?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://twitter.com/activelylazy"&gt;David Green&lt;/a&gt; and I had worked together in the past and we kept in touch since. Over one year ago, we were talking to each other about our jobs, pet projects, technologies, etc and we both realised that we couldn't discuss everything we wanted just with the people we knew. We were also aware of our own limitations. So we thought that it would be awesome if there was a group of people that we could meet regularly and share ideas about software development in general.&lt;br /&gt;&lt;br /&gt;By then, I was very into the whole &lt;a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html"&gt;Software Craftsmanship&lt;/a&gt; thing. David was also very aware of everything that was going on, but we had slightly different views of craftsmanship as a movement. I remember having quite a few interesting conversations with him about that. However, we both always believed in the same principles and values regardless of the labels people were using.&lt;br /&gt;&lt;br /&gt;I had been involved with the &lt;a href="http://www.meetup.com/Londonjavacommunity/"&gt;London Java Community&lt;/a&gt; (LJC) even before its existence. At some point I managed to bring David along to one of the &lt;a href="http://www.meetup.com/Londonjavacommunity/"&gt;LJC&lt;/a&gt;'s social events. On that evening, David and I had a chat with &lt;a href="http://twitter.com/barryclearview/"&gt;Barry Cranford&lt;/a&gt;, founder of the LJC, and with &lt;a href="http://twitter.com/karianna/"&gt;Martijn Verburg&lt;/a&gt; and &lt;a href="http://twitter.com/JR0cket/"&gt;John Stevenson&lt;/a&gt;, LJC organisers and also involved with other user groups and open source communities. We mentioned to them our idea of having a regular meeting where any topic related to software development could be discussed. Maybe show and write some code, discuss design, compare approaches. Completely language agnostic. We also mentioned to them one thing or two about the &lt;a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html"&gt;Software Craftsmanship&lt;/a&gt; movement. They all said that we should go ahead and found our own community instead and offered us LJC's support and blessings. I don't think that any of us was really thinking about founding a community. We just wanted to attend this sort of meetings. &lt;br /&gt;&lt;br /&gt;David was always a bit more organised than me. But me, I could barely organise a bbq for my own birthday, let alone run a community. We left the pub that night and while walking to the station we though that actually it could be a good idea. Maybe we should give it a go. Why not?&lt;br /&gt;&lt;br /&gt;When I got home that night, I went to the &lt;a href="http://www.meetup.com/"&gt;meetup.com&lt;/a&gt; website and created the &lt;a href="http://www.meetup.com/london-software-craftsmanship/"&gt;London Software Craftsmanship Community&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Summary of our first year&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We had our &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/14862535/"&gt;first meeting&lt;/a&gt; on 6th of October, 2010 (&lt;a href="http://skillsmatter.com/podcast/design-architecture/what-is-software-craftsmanship"&gt;video&lt;/a&gt;). David and I gave a introductory talk on software craftsmanship and for our surprise we had over 100 people subscribed. That was the first sign that our community would take off. Right after we decided to have a monthly meeting called Software Craftsmanship Round-table&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;The Round-table meetings&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This is the meeting that we always wanted to have and that triggered the whole thing. In general they are limited to 25 people. We get together and attendees write the topics they want to discuss on the whiteboard. Any thing related to software development is valid. Then we take a vote. The most voted topics are discussed. Sometimes we discuss just one or two topics, sometimes we discuss up to five topics. No one needs to be an expert on the topic. It's not a presentation. It's just a friendly group discussion.&lt;br /&gt;&lt;br /&gt;During the round-table meetings over the year, we had people showing code they were working on, pieces of design and architecture, testing frameworks, and had discussions about a huge amount of other topics. We had discussions about hiring good developers, distributed agile teams, mentors and apprentices, TDD, legacy code, patterns, PaaS comparisons, programming languages, android testing frameworks, the future of web applications, literate programming, DSLs, BDD frameworks, DDD, anti-patterns, specific technologies like Hamcrest, JUnit theories and Spring Roo and many many others that it would be impossible to describe all.&lt;br /&gt;&lt;br /&gt;I absolutely love the roundtables and learned a lot from them. Our latest addition to it is a series of lightning talks at the beginning of the night, when people fancy giving one. Another cool thing is that every meeting is different, depending of who is attending, the topics proposed and the ones people voted on.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Other meetings&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;During the year we also had a few other great meetings. One was the Software Craftsmanship Panel Discussion - &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/16879836/"&gt;How can craftsmanship move the industry forwards?&lt;/a&gt; | &lt;a href="http://skillsmatter.com/podcast/agile-testing/how-can-craftsmanship-move-the-industry-forwards"&gt;video&lt;/a&gt; - when we had the pleasure to have &lt;a href="http://twitter.com/ade_oshineye"&gt;Ade Oshineye&lt;/a&gt;, &lt;a href="http://twitter.com/chrismdp"&gt;Chris Parsons&lt;/a&gt;, &lt;a href="http://twitter.com/tastapod"&gt;Dan North&lt;/a&gt; and &lt;a href="http://twitter.com/redsquirrel"&gt;Dave Hoover&lt;/a&gt; in the panel. It was great to see them giving their views about many topics relevant to the future of our industry. We had &lt;a href="http://twitter.com/hugs"&gt;Jason Huggins&lt;/a&gt;, creator of &lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt;, giving a talk to us about "&lt;a href="http://www.meetup.com/london-software-craftsmanship/events/15118493/"&gt;how to test 'untestable' applications&lt;/a&gt;" | &lt;a href="http://skillsmatter.com/podcast/home/painless-product-demos-how-to-test-untestableapplications"&gt;video&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;We also cross-promoted the &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/16695974/"&gt;Code Retreat Winchester&lt;/a&gt;, organised by &lt;a href="http://twitter.com/despo"&gt;Despo&lt;/a&gt; and &lt;a href="http://twitter.com/sermoa"&gt;Aimee&lt;/a&gt;, and the first &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/21919121/"&gt;Cambridge Dojo Day&lt;/a&gt;, organised by &lt;a href="http://twitter.com/alastairs"&gt;Alastair Smith&lt;/a&gt;, organiser of the &lt;a href="http://www.camdug.com/"&gt;Cambridge User Group - CAMDUG&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Future meetings&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We will be keeping the monthly Software Craftsmanship Round-table meetings on every second week of the month. From this month onwards, we will have a monthly hands-on session on the last week of the month. Our first one is the &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/28321981/"&gt;Crafting Object-Oriented Code&lt;/a&gt;, on the 30th of August. We will be opening the space to our members to submit proposals for any hands-on session they want run in the following months. &lt;br /&gt;&lt;br /&gt;We are also very happy to be having &lt;a href="http://www.meetup.com/london-software-craftsmanship/events/27600561/"&gt;LSCC's First Code Retreat&lt;/a&gt; on 10th of September. &lt;br /&gt;&lt;br /&gt;Our meetings tend to be fully subscribed, on average, in 24 hours after they are announced. We had round-table meetings being booked up in just 5 hours in the past. So, if you want to attend our meetings, make sure you register as soon as you get the email notification. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Community&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Throughout the year, we met many extremely passionate and talented people. I learned things that I was not even aware they existed. And that's what this is all about. That's exactly what we always wanted. We met people from all levels of expertise, different backgrounds, working in different industries and with different technologies. All kind enough to share what they know and humble enough to want to learn from others. &lt;br /&gt;&lt;br /&gt;LSCC had a lot of support from LJC and we are committed to support other communities as well. With that in mind, we would like to offer our support to any person or group of people thinking to found a software craftsmanship community in the UK or even abroad. We are more than happy to cross-promote any event to our members - if we judge they are relevant to our community and to the software craftsmanship moment as a whole.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The future of LSCC&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We have quite a few things in our heads but I don't want to spoil the surprise and neither make promises I may not live up to. But there are a few things I can say. Besides all the regular meetings (round-tables and hands-on sessions), we want to focus more on the Software Craftsmanship movement itself. There are quite a few principles and values that we need to start focusing on. We are already having discussions about some of them so watch this space.&lt;br /&gt;&lt;br /&gt;Another thing I personally would like to see is more software craftsmanship communities around the UK and Europe. We will do the best we can to help and support new communities.&lt;br /&gt;&lt;br /&gt;As we grow, we will need to do more but one thing is for sure. We will not compromise the quality of our meetings or things we want to do just to bring more people in. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;A big thanks&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I would like to thank our sponsors - &lt;a href="http://www.youdevise.com/"&gt;YouDevise&lt;/a&gt;, &lt;a href="http://twitter.com/skillsmatter"&gt;SkillsMatter&lt;/a&gt; and &lt;a href="http://twitter.com/valtech"&gt;Valtech&lt;/a&gt; - for their support, for offering their premisses so we can run our events for free and for helping us get fat with all the pizzas and drinks.&lt;br /&gt;&lt;br /&gt;A big thanks to all the &lt;a href="http://ofps.oreilly.com/titles/9780596518387/accurate_self_assessment.html#kindred_spirits"&gt;kindred spirits&lt;/a&gt; that support and promote LSCC and, last but not least, a massive thanks to all LSCC members for their dedication to their craft and for making LSCC a great community. You guys rock!&lt;br /&gt;&lt;br /&gt;I'm really proud to be a software craftsman and I'm happy to be able to give something back to this amazing community of developers that gave me so much and that helped me to become the professional I am today. Thank you all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-4456837571825244858?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/4456837571825244858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/08/one-year-of-london-software.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/4456837571825244858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/4456837571825244858'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/08/one-year-of-london-software.html' title='One year of London Software Craftsmanship Community (LSCC)'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-9105971434272863542</id><published>2011-07-26T02:47:00.000+01:00</published><updated>2011-07-26T02:58:56.892+01:00</updated><title type='text'>SRP: Simplicity and Complexity</title><content type='html'>&lt;blockquote&gt;&lt;span class="body"&gt;Simplicity does not precede complexity, but follows it.&lt;/span&gt; &lt;span class="bodybold"&gt;- Alan Perlis&lt;/span&gt; &lt;/blockquote&gt;&lt;br /&gt;The Single Responsibility Principle (SRP) - one of the &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;SOLID&lt;/a&gt; principles - is definitely one of my favourites principles in Object-Oriented Design. I find its simplicity and, at the same time, its complexity fascinating. I have known this principle for years and &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;wrote about it&lt;/a&gt; for the first time over one year ago. Still, I can't stop thinking about how hard it is to apply it. Speaking to and pairing with many developers over the years, I noticed that every single one of them understands what the principle is about but when it comes to write code, either they forget it or they simply can't find a way to adhere to it. I'll give you my view about the problem and what I've seen happening in many occasions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;The outside view&lt;/span&gt;&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;i&gt;&lt;span style="font-size: small;"&gt;Every class and method should have just one responsibility&lt;/span&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;This is what I call &lt;i&gt;outside view&lt;/i&gt; and naming plays a big role here.&lt;br /&gt;&lt;br /&gt;This view is generally used when we need to add some totally new code. We think what the new code is about, create a class and/or a method, give it an appropriate name that represents what the new code does and we are done. We also use this &lt;i&gt;outside view&lt;/i&gt; when reading code. When looking at a class or method name, it should be clear to us what they do.&lt;br /&gt;&lt;br /&gt;I don't think anyone ever had a problem understanding this principle. &lt;br /&gt;&lt;br /&gt;However, if it is so simple to understand, why don't we all follow it? Why do we still find classes and methods with hundreds, if not thousands of lines? A few things come to my mind to explain that. Maybe we are just bad at naming classes and methods. Maybe the names we give are too generic or too broad, allowing us to write loads of code in there. Maybe some of us just don't care. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;The inside view&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;&lt;span style="font-size: small;"&gt;Classes and methods should have one, and only one, reason to change&lt;/span&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;This is what I call &lt;i&gt;inside view&lt;/i&gt; and it is the other (often forgotten) side of the Single Responsibility Principle.&lt;br /&gt;&lt;br /&gt;This view is generally used when we need to change some existing code or add more code to it. That's when we look inside each class and method to see exactly what they do. More often than not, we get frustrated because they do much more than they should do and we need to go through many lines of frustration and WTFs to understand the bloody thing. &lt;br /&gt;&lt;br /&gt;However, it is much easier to adhere to the SRP when we keep the &lt;i&gt;inside view&lt;/i&gt; in mind instead of the &lt;i&gt;outside view&lt;/i&gt;. That means, always think about the number of reasons to change a class or method instead of thinking purely in their responsibilities. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;So, when and where do things go wrong?&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;NOTE: In general I find more SRP violations in systems where developers are not doing TDD and refactoring. &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Here is some food for thought. I'm risking to say that the majority of SRP violations are found in the classes and methods that are closer to the interface of the system. For example, in a web application, it's very common to find large controllers, actions or backing bean classes. For swing applications, we tend to find large event handlers. For systems where the entry point is a queue, we tend to find large methods that are responsible for processing the messages.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;In general, this happens because the classes and methods closer to the interface of the system have a more generic and broader responsibility. Quite often, these methods are responsible to trigger loads of business rules and/or complex workflows. &lt;br /&gt;&lt;br /&gt;Imaging that the input to our system is a huge XML file representing a trade. Also imagine that the first method invoked to handle that is called "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;processTrade(tradeXML)&lt;/span&gt;", located in a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;TradeService&lt;/span&gt; class. What is the responsibility of this method? It is to process a trade, right? Should it have a different name? Our system is expected to "process" all trades received so it is fair to say that the first method handling the request (or reading from a queue) should be called &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;processTrade&lt;/span&gt;. &lt;br /&gt;&lt;br /&gt;In another example, imagine that an user added a few items to her shopping basket (web application), provided some payment details and clicked on the "place order" button. In our back end, we will have a method handling this request that probably will be called something like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;placeOrder(order)&lt;/span&gt;. Fair, right?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Developing an idea&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;In general, the closer the code is to the system's interface, the broader and more generic its responsibility will be. The further away the code is from the system's interface, the narrower and more specific its responsibility will be.&amp;nbsp; &lt;/blockquote&gt;&lt;br /&gt;In both examples above, by their names, you can argue that the methods &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;processTrade&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;placeOrder&lt;/span&gt; have a single responsibility. One processes the incoming trade and the other places a customer order. So, when developers take into account &lt;b&gt;just&lt;/b&gt; the &lt;i&gt;outside view&lt;/i&gt; of the SRP, they feel comfortable to add as much code as they need to satisfy these responsibilities. &lt;br /&gt;&lt;br /&gt;The problem is that processing a trade or placing an order may be extremely complicated tasks, where a huge workflow will be triggered, many business rules and requirements need to be satisfied and we will need to write hundreds, if not thousands, of lines for that. So clearly, adding all these lines to a single method doesn't just simply violates the SRP. It's also plain stupid.&lt;br /&gt;&lt;br /&gt;So, in order to make our code compliant to the SRP, we need to have just a single reason to change it. This leads to a complementary idea.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;In general, the closer the class is to the system's interface, the more delegation the class will do. The further way the class is from the system's interface, less delegation the class will do.&lt;/blockquote&gt;&lt;br /&gt;A general example would be, in a traditional Java web application, the controllers, that are closer to the UI, have a broad responsibility and tend to delegate all the business logic to other objects. They just control the flow. At the other end, we have the DAOs that have a very specific and narrow responsibility, almost never delegating anything to another class. In the middle, we have services, that do some business logic of their own but also delegate work to other collaborator classes. Services tend to have a narrower responsibility when compared to a controller but a broader responsibility when compared to DAOs. Still, each class and method have a single responsibility. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Asking a different question&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When mentoring and/or pair-programming with other developers, quite often we end up discussing about the amount of code in a method or methods in a class. Just using the SRP's &lt;i&gt;outside view&lt;/i&gt; as an argument sometimes is not enough to convince some developers that the code is doing too much. That's why I find the &lt;i&gt;inside view&lt;/i&gt; more useful. Instead of asking how many responsibilities a method or class have, I now ask how many reasons we would have to change them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-9105971434272863542?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/9105971434272863542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/07/srp-simplicity-and-complexity.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/9105971434272863542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/9105971434272863542'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/07/srp-simplicity-and-complexity.html' title='SRP: Simplicity and Complexity'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-1928470713879025372</id><published>2011-07-18T02:12:00.000+01:00</published><updated>2011-07-18T02:12:08.747+01:00</updated><title type='text'>Testing legacy: Hard-wired dependencies (part 2)</title><content type='html'>In &lt;a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html"&gt;part one&lt;/a&gt;, I showed how to unit test a method that uses a Singleton and makes static calls. So now, let's have a look at common code problems we find in legacy code, using the same example:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1087417.js?file=TripService.java"&gt;&lt;/script&gt;&lt;br /&gt;How many problems can you see? Take your time before reading the ones I found.. :-)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Refactoring&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;i&gt;&lt;span style="font-size: small;"&gt;NOTE&lt;/span&gt;&lt;b&gt;&lt;span style="font-size: small;"&gt;: &lt;/span&gt;&lt;/b&gt;&lt;span style="font-size: small;"&gt;When I've done it, I've done it step by step running the tests after every step. Here I'll just summarise my decisions&lt;/span&gt;&lt;/i&gt;.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;The first thing I noticed is that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;tripList &lt;/span&gt;variable does not need to be created when the logged user is null, since an exception is thrown and nothing else happens. I've decided to invert the outer if and extract the &lt;a href="http://c2.com/cgi/wiki?GuardClause"&gt;guard clause&lt;/a&gt;.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt; &lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1087435.js?file=TripService_refactor1.java"&gt;&lt;/script&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Feature Envy&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When a class gets data from another class in order to do some calculation or comparison on that data, quite often it means that the client class &lt;i&gt;envies &lt;/i&gt;the other class. This is called &lt;a href="http://c2.com/cgi/wiki?FeatureEnvySmell"&gt;Feature Envy (code smell)&lt;/a&gt; and it is a very common occurrence in long methods and is everywhere in legacy code. In OO, data and the operations on that data should be on the same object.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;So, looking at the code above, clearly the whole thing about determining if an user is friends with another doesn't belong to the TripService class. Let's move it to the User class. First the unit test:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1087914.js?file=UserTest.java"&gt;&lt;/script&gt;&lt;br /&gt;Now, let's move the code to the User class. Here we can use the Java collections API a bit better and remove the whole for loop and the isFriend flag all together.&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1088245.js?file=gistfile1.txt"&gt;&lt;/script&gt;&lt;br /&gt;After a few refactoring steps, here is the new code in the TripService&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1088251.js?file=gistfile1.java"&gt;&lt;/script&gt;&lt;br /&gt;Right. This is already much better but it is still not good enough.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Layers and dependencies&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Some of you may still be annoyed by the protected methods we created in &lt;a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html"&gt;part one&lt;/a&gt; in order to isolate dependencies and test the class. Changes like that are meant to be temporary, that means, they are done so we can unit test the whole method. Once we have tests covering the method, we can start doing our refactoring and thinking about the dependencies we could inject.&lt;br /&gt;&lt;br /&gt;Many times we would think that we should just inject the dependency into the class. That sounds obvious. TripService should receive an instance of UserSession. Really?&lt;br /&gt;&lt;br /&gt;TripService is a service. That means, it dwells in the service layer. UserSession knows about logged users and sessions. It probably talks to the MVC framework and/or HttpSession, etc. Should the TripService be dependant on this class (even if it was an interface instead of being a Singleton)? Probably the whole check if the user is logged in should be done by the controller or whatever the client class may be. In order NOT to change that much (for now) I'll make the TripService receive the logged user as a parameter and remove the dependency on the UserSession completely. I'll need to do some minor changes and clean up in the tests as well.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Naming&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;No, unfortunately we are not done yet. What does this code do anyway? Return trips from a friend. Looking at the name of the method and parameters, or even the class name, there is no way to know that. The word "friend" is no where to be seen in the TripService's public interface. We need to change that as well.&lt;br /&gt;&lt;br /&gt;So here is the final code:&lt;br /&gt;&lt;br /&gt;&lt;script src="https://gist.github.com/1088277.js?file=TripServiceFinal.java"&gt;&lt;/script&gt;&lt;br /&gt;Better, isn't it? We still have the issue with the other protected method, with the TripDAO static call, etc. But I'll leave this last bit for another post on how to remove dependencies on static methods. I'll park my refactoring for now. We can't refactoring the entire system in one day, right? We still need to deliver some features. :-)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This was just a toy example and may not even make sense. However, it represents many of the problems we find when working with legacy (existing) code. It's amazing how many problems we can find in such a tiny piece of code. Now imagine all those classes and methods with hundreds, if not thousands of lines.&lt;br /&gt;&lt;br /&gt;We need to keep refactoring our code mercilessly so we never get to a position where we don't understand it any more and the whole &lt;a href="http://craftedsw.blogspot.com/2010/09/bad-code-invisible-threat.html"&gt;business starts slowing down&lt;/a&gt; because we cannot adjust the software quick enough.&lt;br /&gt;&lt;br /&gt;Refactoring is not just about extracting methods or making a few tweaks in the logic. We need to think about the dependencies, the responsibilities that each class and method should have, the architectural layers, the design of our application and also the names we give to every class, method, parameter and variable. We should try to have the business domain expressed in the code.&lt;br /&gt;&lt;br /&gt;We should treat our code base as if it was a &lt;a href="http://craftedsw.blogspot.com/2010/09/bad-code-invisible-threat.html"&gt;big garden&lt;/a&gt;. If we want it to be pleasant and maintainable, we need to be constantly looking after it .&lt;br /&gt;&lt;br /&gt;If you haven't read it yet, check the &lt;a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html"&gt;part one&lt;/a&gt; of this post. If you want to give this code a go or find more details about the implementation, check: &lt;a href="https://github.com/sandromancuso/testing_legacy_code"&gt;https://github.com/sandromancuso/testing_legacy_code&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-1928470713879025372?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/1928470713879025372/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies_17.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1928470713879025372'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1928470713879025372'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies_17.html' title='Testing legacy: Hard-wired dependencies (part 2)'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-1794976814737868046</id><published>2011-07-17T00:42:00.000+01:00</published><updated>2011-07-18T02:14:08.580+01:00</updated><title type='text'>Testing legacy: Hard-wired dependencies (part 1)</title><content type='html'>When pairing with some developers, I've noticed that one of the reasons they are not unit testing existing code is because, quite often, they don't know how to overcome certain problems. The most common one is related to hard-wired dependencies - &lt;b&gt;Singletons&lt;/b&gt; and &lt;b&gt;static calls&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;Let's look at this piece of code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public List&amp;lt;Trip&amp;gt; getTripsByUser(User user) throws UserNotLoggedInException {&lt;br /&gt;    List&amp;lt;Trip&amp;gt; tripList = new ArrayList&amp;lt;Trip&amp;gt;();&lt;br /&gt;    User loggedUser = UserSession.getInstance().getLoggedUser();&lt;br /&gt;    boolean isFriend = false;&lt;br /&gt;    if (loggedUser != null) {&lt;br /&gt;        for (User friend : user.getFriends()) {&lt;br /&gt;            if (friend.equals(loggedUser)) {&lt;br /&gt;                isFriend = true;&lt;br /&gt;                break;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        if (isFriend) {&lt;br /&gt;            tripList = TripDAO.findTripsByUser(user);&lt;br /&gt;        }&lt;br /&gt;        return tripList;&lt;br /&gt;    } else {&lt;br /&gt;        throw new UserNotLoggedInException();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Horrendous, isn't it? The code above has loads of problems, but before we change it, we need to have it covered by tests.&lt;br /&gt;&lt;br /&gt;There are two challenges when unit testing the method above. They are:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;User loggedUser = UserSession.getInstance().getLoggedUser(); // Line 3  &lt;br /&gt;   &lt;br /&gt;tripList = TripDAO.findTripsByUser(user);                    // Line 13&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As we know, unit tests should test just one class and not its dependencies. That means that we need to find a way to mock the Singleton and the static call. In general we do that injecting the dependencies, but we have a &lt;a href="http://craftedsw.blogspot.com/2011/07/working-with-legacy-code.html"&gt;rule&lt;/a&gt;, remember? &lt;br /&gt;&lt;br /&gt;We can't change any existing code if not covered by tests. The only exception is if we need to change the code to add unit tests, but in this case, just automated refactorings (via IDE) are allowed. &lt;br /&gt;&lt;br /&gt;Besides that, many of the mocking frameworks are not be able to mock static methods anyway, so injecting the TripDAO would not solve the problem. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Overcoming the hard-dependencies problem&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;NOTE: In real life I would be writing tests first and making the change just when I needed but &lt;/i&gt;&lt;i&gt;in order to keep the post short and focused&lt;/i&gt;&lt;/span&gt;&lt;i&gt;&lt;span style="font-size: x-small;"&gt; I will not go step by step here &lt;/span&gt;.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;First of all, let's isolate the Singleton dependency on it's own method. Let's make it protected as well. But wait, this need to be done via automated "extract method" refactoring. Select just the following piece of code on TripService.java:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;UserSession.getInstance().getLoggedUser()&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Go to your IDE's refactoring menu, choose extract method and give it a name. After this step, the code will look like that:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class TripService {&lt;br /&gt;&lt;br /&gt;    public List&amp;lt;Trip&amp;gt; getTripsByUser(User user) throws UserNotLoggedInException {&lt;br /&gt;        ...&lt;br /&gt;        User loggedUser = loggedUser();&lt;br /&gt;        ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    protected User loggedUser() {&lt;br /&gt;        return UserSession.getInstance().getLoggedUser();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Doing the same thing for TripDAO.findTripsByUser(user), we will have: &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public List&amp;lt;Trip&amp;gt; getTripsByUser(User user) throws UserNotLoggedInException {&lt;br /&gt;    ...&lt;br /&gt;    User loggedUser = loggedUser();&lt;br /&gt;    ...&lt;br /&gt;        if (isFriend) {&lt;br /&gt;            tripList = findTripsByUser(user);&lt;br /&gt;        }&lt;br /&gt;    ...&lt;br /&gt;}  &lt;br /&gt; &lt;br /&gt;protected List&amp;lt;Trip&amp;gt; findTripsByUser(User user) {&lt;br /&gt;    return TripDAO.findTripsByUser(user);&lt;br /&gt;} &lt;br /&gt; &lt;br /&gt;protected User loggedUser() {&lt;br /&gt;    return UserSession.getInstance().getLoggedUser();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In our test class, we can now extend the TripService class and override the protected methods we created, making them return whatever we need for our unit tests:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;private TripService createTripService() {&lt;br /&gt;    return new TripService() {&lt;br /&gt;        @Override protected User loggedUser() {&lt;br /&gt;            return loggedUser;&lt;br /&gt;        }&lt;br /&gt;        @Override protected List&amp;lt;Trip&amp;gt; findTripsByUser(User user) {&lt;br /&gt;            return user.trips();&lt;br /&gt;        }&lt;br /&gt;    };&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;And this is it. Our TripService is now testable. &lt;br /&gt;&lt;br /&gt;First we write all the tests we need to make sure the class/method is fully tested and all code branches are exercised. I use Eclipse's &lt;a href="http://www.eclemma.org/"&gt;eclEmma plugin&lt;/a&gt; for that and I strongly recommend it. If you are not using Java and/or Eclipse, try to use a code coverage tool specific to your language/IDE while writing tests for existing code. It helps a lot.&lt;br /&gt;&lt;br /&gt;So here is the my final test class:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class TripServiceTest {&lt;br /&gt;        &lt;br /&gt;    private static final User UNUSED_USER = null;&lt;br /&gt;    private static final User NON_LOGGED_USER = null;&lt;br /&gt;    private User loggedUser = new User();&lt;br /&gt;    private User targetUser = new User();&lt;br /&gt;    private TripService tripService;&lt;br /&gt;&lt;br /&gt;    @Before&lt;br /&gt;    public void initialise() {&lt;br /&gt;        tripService  = createTripService();&lt;br /&gt;    } &lt;br /&gt;        &lt;br /&gt;    @Test(expected=UserNotLoggedInException.class) public void &lt;br /&gt;    shouldThrowExceptionWhenUserIsNotLoggedIn() throws Exception {&lt;br /&gt;        loggedUser = NON_LOGGED_USER;&lt;br /&gt;                 &lt;br /&gt;        tripService.getTripsByUser(UNUSED_USER);&lt;br /&gt;    }&lt;br /&gt;        &lt;br /&gt;    @Test public void &lt;br /&gt;    shouldNotReturnTripsWhenLoggedUserIsNotAFriend() throws Exception {             &lt;br /&gt;        List&amp;lt;Trip&amp;gt; trips = tripService.getTripsByUser(targetUser);&lt;br /&gt;                 &lt;br /&gt;        assertThat(trips.size(), is(equalTo(0)));&lt;br /&gt;    }&lt;br /&gt;        &lt;br /&gt;    @Test public void &lt;br /&gt;    shouldReturnTripsWhenLoggedUserIsAFriend() throws Exception {&lt;br /&gt;        User john = anUser().friendsWith(loggedUser)&lt;br /&gt;                            .withTrips(new Trip(), new Trip())&lt;br /&gt;                            .build();&lt;br /&gt;                 &lt;br /&gt;        List&amp;lt;Trip&amp;gt; trips = tripService.getTripsByUser(john);&lt;br /&gt;                 &lt;br /&gt;        assertThat(trips, is(equalTo(john.trips())));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private TripService createTripService() {&lt;br /&gt;        return new TripService() {&lt;br /&gt;            @Override protected User loggedUser() {&lt;br /&gt;                return loggedUser;&lt;br /&gt;            }&lt;br /&gt;            @Override protected List&amp;lt;Trip&amp;gt; findTripsByUser(User user) {&lt;br /&gt;                return user.trips();&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }        &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Are we done?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Of course not. We still need to refactor the TripService class. Check the &lt;a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies_17.html"&gt;part two&lt;/a&gt; of this post.&lt;br /&gt;&lt;br /&gt;If you want to give it a go, here is the full code: &lt;a href="https://github.com/sandromancuso/testing_legacy_code"&gt;https://github.com/sandromancuso/testing_legacy_code&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-1794976814737868046?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/1794976814737868046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1794976814737868046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1794976814737868046'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html' title='Testing legacy: Hard-wired dependencies (part 1)'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-4553685860220055257</id><published>2011-07-03T23:37:00.000+01:00</published><updated>2011-07-03T23:56:56.653+01:00</updated><title type='text'>Working with legacy code</title><content type='html'>&lt;span style="font-size: large;"&gt;&lt;b&gt;Context&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Large organisations' systems may have from tens of thousands to a few million lines of code and a good part of those lines is legacy code. By legacy code I mean code without tests. Many of these systems started being written many years ago, before the existence of cool things and frameworks we take for granted today. Due to how some systems are configured (database, properties file, proprietary xml) , we cannot simply change a class constructor or method signature to pass in the dependencies without undertaking a much larger refactoring. Changing one piece of code can break completely unknown parts of the system. Developers are not comfortable in making changes in certain areas of the system. Test-first and unit testing is not widely used by developers. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The Rule&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In our commitment to make the existing systems better, more reliable, easier to deal with (changing and adding more features), we established the following rule: We can not change existing code if it is not covered by tests. In case we need to change the existing code to be able to write the tests, we should do it only using the automated refactoring tools provided by our IDEs. Eclipse and IntelliJ are great for that, if you are a Java developer like me.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;That means, before we make any change, we need to have the current code under test, guaranteeing that we don't break its current behaviour. Once the existing code is under test, we then write a new test for the new feature (or change an existing test if it's a change in existing behaviour) and finally we are can change the code. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Problem&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There is an eternal discussion on forums, mailing lists and user groups about TDD being responsible for the increase or decrease of the team's velocity. I don't want to start this discussion here because we are not doing TDD for majority of the time. With legacy code, we spend the majority of our time trying to test existing code before we can do TDD to satisfy the new requirement. And this is slow. Very slow. It can be, in our experience, somewhere between 5 to 20 times slower than just making the change we need and manually test it.&lt;br /&gt;&lt;br /&gt;You may be asking, why does it take so much longer? My answer is: If you haven't, try unit testing all the possible execution paths in a 2000+ line class? Have you tried to do it with a 1000 line method, full of multiple return statements, hard-wired dependencies, loads of duplication, a big chain of nested IFs and loops, etc? Believe me, it will take you a bloody long time. Remember, you can't change the existing code before writing tests. Just automated re-factorings. Safety first. :-) &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Why are we "under-performing"?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Quite often, after start following this rule, management will enquire why the team is under-performing. Although it is a fact that the team is taking longer to implement a feature, this is also a very naive view of the problem. When management and development teams talk about team's velocity, they just take into consideration the amount of time taken to write the code related to a few specific requirements.&lt;br /&gt;&lt;br /&gt;Over the time, management and teams just forget how much time they spend in things that are caused by the lack of quality and tests in their code. They never take into consideration that there is absolutely no way that developers would be able to manually test the entire system and guarantee they didn't break anything. That would take days, for every piece of code they write or change.&amp;nbsp; So they leave that to QA.&lt;br /&gt;&lt;br /&gt;By not increasing the test coverage, the team will never have a regression test suite. Manually testing the system, as it grows in size and complexity, will start taking longer and longer by the QA team. It will also be more error prone, since testing scripts need to be kept in sync with the current behaviour of the system. This is also waste of time.&lt;br /&gt;&lt;br /&gt;Also, just hacking code all the time will make the system more fragile and way more complicated to understand, which will make developers to take longer to hack more code in.&lt;br /&gt;&lt;br /&gt;Because we can't press a button and just unit test a specific piece of code, the team is forced to spend a lot of time debugging the application, meaning that the team needs to spend time compiling and deploying it. In certain systems, in order to test a small piece of code, you need to rely on other systems to trigger something so your system can respond. Or you need to manually send messages to a queue so your piece of code is invoked. Sometimes, depending of the complexity of your system and it's dependencies, you can't even run it locally, meaning that you need to copy your application to another environment (smoke, UAT, or whatever name you use in your company) in order to test the small piece of code you wrote or changed. And when you finally manage to do all that to execute that line of code you just added, you realise that the code is wrong. Sigh. Let's start over.&lt;br /&gt;&lt;br /&gt;Since I started practising TDD, I realised that I very rarely use my  debugger and very rarely have to deploy and run my application in order to test it.&lt;br /&gt;&lt;br /&gt;So basically, when people think we are spending too much time to write a feature because we were writing tests for the existing code first, they are rarely considering the time spend elsewhere. I've seen it many times: "We don't have time to do it now. Let's just do a quick fix.". And then, contradicting the laws of physics, more time is created when bugs are found and the QA phase needs to be extended. Panic takes over: "Oh, we need to abort the release. We can't go live like that.". Exactly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-M27DSWj4Qd0/ThCw0dKhkUI/AAAAAAAAALs/GUf0d4JEJtg/s1600/Legacy_velocity.jpg" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="146" src="http://1.bp.blogspot.com/-M27DSWj4Qd0/ThCw0dKhkUI/AAAAAAAAALs/GUf0d4JEJtg/s400/Legacy_velocity.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The graphic above is not based in any formal research. It is purely based on my own experience during my career. I also believe that the decrease in the team's velocity is related to the state of the untested code. There are untested code out there that is very well written and writing tests to it is quite straightforward. However, in my experience, this would be an exception. &lt;br /&gt;&lt;br /&gt;In summary, if you are constantly applying the "Boy Scout Rule" and always keep improving the code you need to touch, over the time you will be making your code better and you will be going faster and easier. If you don't do that, you will have a false impression of good velocity at start but gradually and quite often without noticing, you will start to slow down. Things that used to take a few days, now take a few weeks. Because this lost of velocity happened slowly (over months or even years), no one really noticed until it was too late and everything now take months.&amp;nbsp; &amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Drifting away and losing focus&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One interesting side effect of constantly making legacy code better, writing tests and refactoring, is that it is too easy to be carried away. More than once I've seen pairs, while trying to clean a piece of code, drifting away from the task/story they were working on. That also happened to me quite a few times. We get carried away when making progress and making things better. &lt;br /&gt;&lt;br /&gt;Very recently I was asked by one of the developers: "When do we stop?". My answer was: "When we finish the task.". In that context, that meant that the focus is always on task at hand. We need to keep delivering what was agreed with our product owners (or whoever the person in charge of the requirements are). So, make the system better but always keep the focus on the task. Don't go crazy with the refactoring trying to re-write the whole system in a few days. Do enough to finish the task and try to isolate the parts that are still not good enough. Baby steps.&lt;span style="font-size: large;"&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;A more positive side effect&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Another very common problem in legacy systems is the lack of understanding about the system and also about the business. Quite often we find situations where the developers and business people are long gone and no one really knows how the system behave.&lt;br /&gt;&lt;br /&gt;Writing tests for the existing code force us to understand what it does. We try to mine some hidden business concepts in the middle of the procedural code and try to make them very explicit when naming our tests. That is a great way to drive our refactoring later own, using the business concepts captured by the tests. Quite often, we also get the business people involved, asking them questions and checking if certain assumptions make sense.&lt;br /&gt;&lt;br /&gt;In writing the tests and refactoring the code, the previously completely unknown behaviour of the system is now well documented by the tests and code. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Quality is a long term investment&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In a recent conversation, we were discussing how we could measure our "investment" in quality. A quick and simple answer would be that we could measure that by the number of bugs and the velocity that the teams are delivering new requirements. However, this is never too simple. The question is, why do you think you need quality? Which problems do you have today that makes you think they are quality related? What does quality mean anyway? &lt;br /&gt;&lt;br /&gt;When working with legacy, after many years, we tend to forget how things were in the past. We just "accept" that things take a long time to be done because they have been taking a long time to be done for a long time. We just accept a (long) QA phase. It's part of the process, isn't it? And this is just wrong.&lt;br /&gt;&lt;br /&gt;Constantly increasing the quality level in a legacy system can make a massive difference in the amount of time and money spend on that project. That's what we are pursuing. We want to deliver more, faster and with no bugs. &lt;br /&gt;&lt;br /&gt;It's up to us, professional software developers, to revert this situation showing a great attitude and respect for our customers. We should never allow ourselves to get into a situation where our velocity and quality of our work decreases because of our own incompetence.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-4553685860220055257?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/4553685860220055257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/07/working-with-legacy-code.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/4553685860220055257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/4553685860220055257'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/07/working-with-legacy-code.html' title='Working with legacy code'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-M27DSWj4Qd0/ThCw0dKhkUI/AAAAAAAAALs/GUf0d4JEJtg/s72-c/Legacy_velocity.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-7930062936973783858</id><published>2011-06-21T03:31:00.000+01:00</published><updated>2011-06-21T03:31:59.736+01:00</updated><title type='text'>A change in attitude - Legacy code</title><content type='html'>&lt;blockquote&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Attitude is a little thing that makes a big difference.&amp;nbsp; ~Winston Churchill&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt; &lt;br /&gt;&lt;span style="font-size: small;"&gt;  &lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Not long ago, I gave a &lt;a href="http://skillsmatter.com/podcast/design-architecture/what-is-software-craftsmanship/js-1956"&gt;talk&lt;/a&gt; about  Software Craftsmanship where I asked who liked to work on greenfield  projects. Almost everyone raised their hands. Then I asked who liked to  work with legacy code. Besides one or two friends that were there,  almost everyone kept their hands down. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;  &lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;It is always nice to start a project  from scratch, be able to choose the technology, use the latest  frameworks and have a lot of fun writing code without worrying about  breaking existing features or having to understand existing code.  Working on greenfield is great, mainly with an experienced and  disciplined team using TDD since day one. Progress  flows naturally and quickly.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;But as soon as we are working with code  written by people that are long gone, no tests, no documentation,  we go mental. We notice we are going mental by the number of WTF we say  during the day. We may get moody and start hating to work on a specific  system or in parts of it. Frustration becomes a constant. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;&lt;span style="font-family: Arial;"&gt;A change in attitude&lt;/span&gt;&lt;/b&gt;&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;  &lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;If you don't like something change it; if you can't change it, change the way you think about it.&amp;nbsp; ~Mary Engelbreit&lt;/span&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;  &lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Although I wrote "we" and "us", that was  really how I used to feel when working with legacy code. However, in  the past few years, I learned many things. An obvious one is that  moaning, complaining and cursing won't make my life easier or better. If  I want things to be better I need to do something about it. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;  &lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;  &lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Today, when I look at legacy code,  instead of moaning and getting frustrated, my attitude is to try to  understand it and make it better, constantly applying the Boy Scout  Rule. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;As my friend &lt;a href="http://twitter.com/activelylazy"&gt;David Green&lt;/a&gt; said in a twitter conversation, what I  agree 100%, improving and understanding legacy code can be massively  rewarding. The process of trying to make sense of a big ball of mud  seems daunting but if we just focus in small parts of it, one at a time, and start improving them (writing tests, extracting methods and classes, renaming variables, etc), bit by bit,  things become much easier and enjoyable.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Working with legacy code is almost like solving a big jigsaw  puzzle. We don't do that all at once. We start by separating the pieces  into groups, often starting with the edges and corners and then separating other small pieces by colour, pattern, etc. We now have a few (logical) groups and we start to form a higher level model in our head. What before was a bunch of random pieces (or a big ball of mud), now is a bunch of smaller groups of random pieces. Still not very helpful or encouraging, but &lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;nonetheless some &lt;/span&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;progress. Bit by bit, we start working on one of these groups (parts of the code) and we start putting some pieces together (writing tests for the existing code, which will help with our understanding of the code, and refactoring it).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Once we start putting some pieces together, we start seeing a small part of our jigsaw puzzle picture. We get excited because now it's getting real. It's starting to make sense and we are happy we are making progress. The more pieces we put together the more excited we are about finishing the jigsaw puzzle. The more pieces we put together, the easier it gets to put more pieces together. And that's exactly the feeling I've got when working with legacy code now. For every piece of code I make better, more I want to make the whole code better. The feeling of achievement is really rewarding. What before was something I could barely read and took ages to understand, now reads like a story and every developer can understand it with no effort at all. Maybe when a good part of the code is stable (covered by tests, loosely coupled, well defined responsibilities, etc), I could even introduce the cool and new frameworks that I always wanted to use. I could upgrade some library versions. I could even throw a lot of code away and replace it with a framework because now my code is clean and modularised and replacing one part of the system will not break another. I don't even need to envy my friends working on greenfield projects any more.&lt;/span&gt;&lt;b&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Different challenges&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Another cool thing about legacy code is that it forces you to think in a different way. In greenfield projects, when developing a new feature, we write a test and start implementing stuff. In legacy, sometimes you can't even instantiate a class in order to test it due to all its dependencies. A change in one place can cause an impact in obscure parts of the system. We have an option here. We can see these challenges as a pain in the ass or can be see them as very interesting problems to solve. I prefer the latter.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;The professional side&lt;/span&gt;&lt;/b&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;Although it is OK to have fun and enjoy what we are doing, we always need to remember that we are professionals and being paid to write software. Software is an asset and a lot of money and time is invested on it. As every investment, clients want to maximise the return of their investment. The more we improve and keep the software clean, the longer the client will be able to benefit from it. Stretching the lifespan of a software also maximises the client's return of investment.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Arial; font-size: small;"&gt;At the end of the day, it does not matter if you are working on a green or brownfield project. It's your attitude towards your job that will make it more or less enjoyable. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-7930062936973783858?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/7930062936973783858/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/06/change-in-attitude-legacy-code.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7930062936973783858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7930062936973783858'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/06/change-in-attitude-legacy-code.html' title='A change in attitude - Legacy code'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-1099002307899451851</id><published>2011-05-17T04:38:00.000+01:00</published><updated>2011-05-17T17:48:10.603+01:00</updated><title type='text'>Re-drawing my own map: A new milestone</title><content type='html'>&lt;blockquote&gt;&lt;div class="epigraph"&gt;&lt;div id="ch03_id2376911"&gt;For every step you take towards mastery, your destination moves         two steps further away. Embrace mastery as a lifelong endeavour. Learn         to love the journey.&lt;/div&gt;&lt;div class="attribution" style="text-align: right;"&gt;--&lt;span class="attribution"&gt;George Leonard, &lt;a class="link" href="http://www.amazon.co.uk/Mastery-Plume-George-Leonard/dp/0452267560/ref=sr_1_1?ie=UTF8&amp;amp;qid=1305590628&amp;amp;sr=8-1" title="Mastery: The Keys to Success and Long-Term Fulfillment"&gt;&lt;span class="emphasis"&gt;&lt;i&gt;Mastery&lt;/i&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;It is with a mixture of sadness and excitement that I would like to announce that, after over five years, I'm leaving &lt;a href="http://valtech.co.uk/"&gt;Valtech&lt;/a&gt; on the 18th of May. The decision was not an easy one and took me months to figure out what the next step in my &lt;a href="http://apprenticeship-patterns.labs.oreilly.com/ch03.html#the_long_road"&gt;long road&lt;/a&gt; would be. As I said in a &lt;a href="http://craftedsw.blogspot.com/2011/04/working-for-consultancy-companies.html"&gt;recent interview&lt;/a&gt;, I love working for consultancy companies and that's the main reason I spent over ten years (two-thirds of my career) working as a consultant.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Working for Valtech&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Valtech is a fantastic company to work for and had a huge impact in my personal and professional life. During my time there I had the opportunity to work on a great variety of projects, different companies, different industries and different technologies. Most importantly, I had the opportunity to meet and work with a lot of great people that helped me to become a much better professional.&lt;br /&gt;&lt;br /&gt;If there is one thing that I will never complain about Valtech is that I did not have recognition for the work I've done. I have started at a Valtech in a relatively junior role, according to Valtech's grade scheme, and bit by bit, with a lot of support and trust from my colleagues I was given more and more responsibility and gradually climbed my way up to one of the most senior positions. &lt;br /&gt;&lt;br /&gt;There is no such a thing as a perfect company but if I had to point out the best thing about Valtech, I would say that, beyond the shadow of a doubt, it is its people. People that I learnt a lot from, that helped me to feel at home in the UK, that helped me with personal issues, people that challenged me, that pushed me to my limits, that gave me constructive criticism, that trusted me and empowered me to do my job, people that helped me to be better.&lt;br /&gt;&lt;br /&gt;I may not be in the office or in a client site full time any more but I will always be around. As it happened before (I took a year off to work on a startup idea and came back) I'll always be around for drinks and events. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Special thanks&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I would like to thank you everyone at Valtech that had to put up with me for all this time. I know I can be a pain in the neck &lt;strike&gt;quite often&lt;/strike&gt; sometimes. :-)&lt;br /&gt;&lt;br /&gt;It's always tricky to mention names since there is always the risk of people left out feeling a bit upset but I feel that I need to thank some people in a more personal level, so apologies for the ones I did not mention. In no particular order: &lt;a href="http://twitter.com/tobymckenzie"&gt;Toby Mckenzie&lt;/a&gt; for caring about me and every single consultant during tough times, all his herculean effort to keep every one happy, finding us good projects; &lt;a href="http://twitter.com/david_draper"&gt;David Draper&lt;/a&gt; for challenging many of my beliefs and opinions, for the many advices, for supporting my involvement with user groups and events and for the effort in making Valtech a place of excellence; &lt;a href="http://twitter.com/mashooq"&gt;Mashooq Badar&lt;/a&gt; for the fantastic time we had together in many projects, for all the things I learnt from him and for making me open my mind about so many things. Ah, and for all the &lt;i&gt;Blazing hot!&lt;/i&gt; moments; &lt;a href="http://twitter.com/philghall"&gt;Phil Hall&lt;/a&gt; for the support and keeping the doors open to me and &lt;a href="http://www.meetup.com/london-software-craftsmanship"&gt;LSCC&lt;/a&gt;; Kevin Harkin (I can't believe he does not use twitter) for the fun we had together, for his friendship, advices, ranting sessions and memorable nights at the pub; &lt;a href="http://twitter.com/anderew"&gt;Andrew Rendell&lt;/a&gt; for his professionalism, trust and for being a great role model for every Valtech consultant; And last but not least, &lt;a href="http://twitter.com/akbarzamir"&gt;Akbar Zamir&lt;/a&gt;, for pushing me and challenging me to be better, for all the advice, trust, knowledge and help, for being a great career manager and most important of all, for being a great friend.&lt;br /&gt;&lt;br /&gt;Thanks for the great five years that I spent there. It was an absolute pleasure to work with all of you and be part of this great company.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The future&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div class="epigraph"&gt;&lt;div id="ch03_id2378143"&gt;It’s not just a question of conquering a summit previously       unknown, but of tracing, step by step, a new pathway to it.&lt;/div&gt;&lt;div class="attribution" style="text-align: right;"&gt;--&lt;span class="attribution"&gt;Gustav Mahler, musician and composer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/blockquote&gt;I'm joining &lt;a href="http://www.ubs.com/"&gt;UBS&lt;/a&gt; as a senior developer at a director level, starting on the 23rd of May. Due to &lt;a href="http://www.londonswcraft.com/"&gt;my involvement&lt;/a&gt; with the software craftsmanship movement, this came as a surprise to many people, including myself, mainly because investment banks tend to be almost a hostile environment for agile and software craftsmanship initiatives. When I started &lt;a href="http://apprenticeship-patterns.labs.oreilly.com/ch03.html#draw_your_own_map"&gt;re-drawing my own map&lt;/a&gt;, investment banks were an avenue that I was not considering to explore. &lt;br /&gt;&lt;br /&gt;As I said before, choosing my next step was not easy. I had a few things in mind that were non-negotiable: I wanted different challenges, that means, things that I haven't done before, keep having fun and loving my job, a potential long term commitment where I would have time enough to put into practice many ideas and beliefs and most importantly, have a long term career as a software developer but with a lot of space to keep growing as a professional. &lt;br /&gt;&lt;br /&gt;I was fortunate to have had many opportunities during this time but the majority of them could not satisfy all the items above. I was determined to keep doing what I had been doing throughout my entire professional life that is just to work for companies that I really want to work for, I mean, companies that would be able to offer me what I was looking for at that point in time. For me, that's the best way to keep fuelling the passion that I have for what I do. Joining a company just because of money is and always has been totally out of question.&lt;br /&gt;&lt;br /&gt;UBS came along with a very interesting proposition. They want to improve the quality of their software and recognise that agile and software craftsmanship are a great way to get there. They were interested in people with no previous investment bank experience, what is very unusual for an investment bank. They want people that can think different, that are passionate and can help them drive this transformation. I had five interviews and was very pleased to see so many people striving to be and do better. &lt;br /&gt;&lt;br /&gt;As far as I understand, my main role will be to work as a hands-on developer, embedded in a team, helping to improve quality, leading by example and mentoring other developers. They also expect me to give internal talks, training, promote events, disseminate passion and promote the craftsmanship values and techniques. In the future I'll be working with other teams in the UK and in other offices around the world. But make no mistake. I'll have a hell of interesting and tough challenges ahead of me and I hope to live up to all their expectations. &amp;nbsp; &amp;nbsp; &lt;br /&gt;&lt;br /&gt;Besides that, I'll keep running the &lt;a href="http://www.londonswcraft.com/"&gt;London Software Craftsmanship Community (LSCC)&lt;/a&gt; alongside my friend &lt;a href="http://twitter.com/activelylazy"&gt;David Green&lt;/a&gt; and try my best to give something back to the wider and great community of software developers out there that some many times I benefited from.&lt;br /&gt;&lt;br /&gt;Thanks everyone for being part of &lt;a href="http://apprenticeship-patterns.labs.oreilly.com/ch03.html"&gt;long road&lt;/a&gt; journey.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-1099002307899451851?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/1099002307899451851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/05/re-drawing-my-own-map-new-milestone.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1099002307899451851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1099002307899451851'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/05/re-drawing-my-own-map-new-milestone.html' title='Re-drawing my own map: A new milestone'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-3246270725507300054</id><published>2011-05-05T01:52:00.000+01:00</published><updated>2011-05-05T01:52:20.343+01:00</updated><title type='text'>Open-source developers deserve respect</title><content type='html'>I was recently reading Gojko Adzic's blog post called &lt;a href="http://gojko.net/2011/04/05/how-is-it-even-possible-code-to-be-this-bad/"&gt;How is it even possible for code to be this bad?&lt;/a&gt; I must admit that I was very sad to see tremendous lack of respect towards the Hudson/Jenkins community and towards open source software developers in general.&lt;br /&gt;&lt;br /&gt;Firstly I would like to say that any person out there that is working on an open source project deserves a lot of respect, mainly the ones working on projects that bring so many benefits to so many companies and developers around the world. The velocity that our industry moves forward and evolves is, in general, because of many open source initiatives. It's because of thousands of developers that work on the their spare time, for free, to create software that will make the lives of many other developers, companies and users much easier. These people are kind enough to offer their work to all of us and are humble enough to ask and accept help from many other developers around the globe. &lt;br /&gt;&lt;br /&gt;One thing we need to understand is that every project has a history and many things, throughout the lifespan of a project, can be responsible for the success or failure of a project. It's always easier to criticise something instead of trying to help and make it better. As far as I'm aware, I don't think that anyone in the Hudson/Jenkins community ever claimed that their code base is the best example of quality software ever written and we all should learn from them. If that was the case, probably it would justify such harsh words written in the original &lt;a href="http://gojko.net/2011/04/05/how-is-it-even-possible-code-to-be-this-bad/"&gt;blog post&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The only acceptable form of criticism towards any open source project or developer is constructive criticism.&amp;nbsp;&lt;/blockquote&gt;&lt;br /&gt;If we think that a open source project is below standard and/or not good enough, we should either not use it or we should contribute to make it better. &lt;br /&gt;&lt;br /&gt;However, I do understand the point Gojko is trying to make. Yes, I agree that good code is not the only thing that makes a project be successful. I think we all could name a few projects that we delivered where clients and/or users were relatively happy but the code base was a bit messy. There are always exceptions to the rules. Trying to get our code as perfect and as clean as possible does not guarantee that our projects will be successful and having a messy code does not always mean that our project will fail either. We all know that. Even my 5 month-old baby girl knows that. &lt;br /&gt;&lt;br /&gt;However, I totally disagree with Gojko's statement that "&lt;i&gt;[Hudson's success with "bad" code] is close to the final proof that God doesn't exist for the whole craftsmanship debate&lt;/i&gt;". It is almost like saying that Agile is rubbish and everyone should forget about it just because some waterfall projects succeeded. It is like saying that we all should forget about good principles of software development just because some projects succeeded with messy code. In summary, is like trying to get some exceptions and transform them into rules. There are many ways and many things that can contribute to the success of a project. Software craftsmanship is one of them and a very important one. In a software project, the most important thing is the software itself and looking after its quality is an obligation of every developer involved in it.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Although software craftsmanship on its own may not be enough to guarantee the success of a project, the lack of it can be reason for its failure. Single-handed.&lt;/blockquote&gt;&lt;br /&gt;Another important point we should ask is the definition of a "successful project" and in which context or environment but I'll leave that for another post.&lt;br /&gt;&lt;br /&gt;If exceptions invalidate rules and that is the way we should look at things, does God exist for anything in software development?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-3246270725507300054?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/3246270725507300054/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/05/open-source-developers-deserve-respect.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/3246270725507300054'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/3246270725507300054'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/05/open-source-developers-deserve-respect.html' title='Open-source developers deserve respect'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-2802659874925068063</id><published>2011-04-17T23:32:00.000+01:00</published><updated>2011-04-17T23:54:08.344+01:00</updated><title type='text'>Working for consultancy companies</title><content type='html'>Recently I was approached by the guys from the &lt;a href="http://www.meetup.com/grad-dc/"&gt;Graduate Developer Community&lt;/a&gt; (GDC) where they asked me for an interview about life in a consultancy company. Their idea, that came out from an email I sent to the &lt;a href="http://www.meetup.com/Londonjavacommunity/"&gt;London Java Community (LJC)&lt;/a&gt; ages ago about different career paths, was to interview professionals that followed different career paths and publish these interviews on a website called &lt;a href="http://gdccareers.wordpress.com/"&gt;GDC Careers&lt;/a&gt; so that graduates and people starting in our industry could have an idea about what is available out there in terms of jobs and career paths.&lt;br /&gt;&lt;br /&gt;The interview was originally published on the &lt;a href="http://gdccareers.wordpress.com/2011/03/06/sandro-mancuso-senior-consultant/"&gt;GDC Careers&lt;/a&gt; but I'll also be publishing it here in full. I hope it helps any professional that would like to know more about life on consultancy companies.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;NOTE&lt;/b&gt;: Throughout my career I've worked for three consultancy companies and this is just my general view of all of them. Each project is a different project and different consultants, working for the same consultancy company but in different projects, can have a completely different view of their employers.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sandro Mancuso has been working as a  software developer  since 1996 but started writing code for pure  enjoyment way before that.  Although he has worked for software houses  and startups, he spent the  majority of his career working for  international consultancy companies  where he had the opportunity to work  on a great variety of projects and  across many different industries. He  has a BSc in Computer Science and  a MSc in Distributed Objects.  He is a Co-founder of the London  Software Craftsmanship Community (LSCC).&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Title – What is your job title? &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Senior Consultant.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is your role about?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;My role is to work with clients, helping them to identify what they &lt;i&gt;really&lt;/i&gt; need, advise them, provide options, and help them to achieve whatever they want to achieve in the most efficient way.&lt;br /&gt;&lt;br /&gt;OK, I know. That was not very specific or helpful. This is because  the role of a consultant can vary quite a lot. Different consultants may  choose different career paths. Some follow a more business oriented  career, advising clients on strategy, marketing, investment, finance,  etc. Some follow a more process oriented career, emphasising project  management, Agile Coaching, training, business analysis, requirements,  etc. Others prefer a more technical career path, working more often as  developers, technical architects and team leaders, mentoring, etc. In my  case, I took the more technical path so normally I do what I like  doing, that is writing code, regardless of my position in the project.  Although I was a hands-on developer on all my assignments, many of them  had elements of mentoring. Some times I also got involved in customised  training courses for clients, like TDD, Agile, etc.&lt;br /&gt;&lt;br /&gt;I work mainly in Agile Java projects. Technologies vary quite a lot  since every now and again we are working for different clients,  different industries and completely different systems. Sometimes clients  already have something in place and the technology stack is already  defined. In this case, we often use whatever they are using to start  with but we always try to make suggestions if we see that other  technologies or frameworks should be used instead. Some other projects,  mainly greenfield ones, we generally have freedom to choose the  technology stack we judge is the best for the problem.&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What are the best/most positive parts of the job/industry?&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;In my view, the best thing about being a consultant is the amount of  technologies and business domains that you are exposed to during your  career. Because of the frequency that we change projects, we end up  being exposed to a lot of interesting problems quite early in our  careers, giving us a great understanding of many different software  projects.&lt;br /&gt;&lt;br /&gt;Networking is definitely another very positive aspect of being a  consultant. As we move from project to project, client to client, we end  up meeting a lot of people, in different organisations, what can be  very useful as you progress in your career. The more people you work  with or for, the more options you will have in the future.&lt;br /&gt;&lt;br /&gt;Another important point is that, as a consultant, you need to be &lt;i&gt;sellable&lt;/i&gt;.  This may sound a bit negative, but if fact, what it means is that you  need to be at the top of your game, knowing the latest technologies,  methodologies and trends. The more you know, the easier it will be for a  consultancy to place you in a project (sell you to a client). As the  consultancy companies recognise that, in general they have different  mechanisms (training, conferences, internal talks, events, etc) that you  can take advantage of to improve your skills.&lt;br /&gt;&lt;br /&gt;Because your peers are also moving from project to project and using  different technologies in each project, it is amazing what you can learn  from them. The variety of information shared among consultants about  projects, businesses, methodologies, technologies, etc, is absolutely  priceless. There is always someone doing something different somewhere.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What are the negative parts to the job/industry?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The main complain that consultants have is that in general you don’t  have much saying on where you are going to be sent to. Once you decide  you want to work for a consultancy company, you need to be aware that  travelling is always a possibility. A few &lt;i&gt;lucky&lt;/i&gt; consultants get  to stay for a long time on projects close to their homes but in general  this is not the case. If travelling or long commute is not an option  for you, you really need to think hard before becoming a consultant. For  those living in big cities, like London for example, in general this is  not a big problem since the majority of the clients will be there  anyway.&lt;br /&gt;&lt;br /&gt;According to your level of seniority, years in the company and  history of projects you delivered, you can refuse to go to some  projects, in case you don’t like the project (less often) or if the  commute is bad (more often). However, this is a card that needs to be  played very wisely since you don’t get to play it more than once in a  short period of time.&lt;br /&gt;&lt;br /&gt;In some projects, you may be seen as an outsider by a few permanent  employees. Some feel threatened by the presence of a “consultant”, since you may be “exposing” problems in the current process and  software. It’s part of our job to deal with that and do whatever we can  to be seen as another team member, a person that shares the same goals,  and not an outsider.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Career Path&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What is the standard career path/qualifications?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This varies quite a lot since consultancies may offer different type  of services and they will need people that are more specialised in some  areas than in others. Services offered may include software development,  project management, training, coaching, business advice (strategy,  finance, investment, etc), auditing, etc. Some consultancies tend to  work more on the “consulting” side of things and tend to engage with clients  at a more senior level (CEOs, CTOs, Directors, etc). Other  consultancies are more focused on software delivery and tend to engage  with clients at lower levels (directors, project managers, head of  departments, etc). And, of course, some consultancies do a bit of both.&lt;br /&gt;&lt;br /&gt;I’ll just talk about consultancies that focus more on software delivery since that’s my background.&lt;br /&gt;&lt;br /&gt;My title is Senior Consultant but this is a reasonably vague title.  Many consultancies, internally, distinguish their consultants by grades.  Each grade has different ranges of salaries and responsibilities and we  take on responsibilities on projects, in general, according to our  grade.&lt;br /&gt;&lt;br /&gt;For people aspiring a more technical career, in the entry levels you  are expected to have a good knowledge of a programming language (in our  case Java or .Net), most common frameworks, good understanding of  Object-Oriented Programming and you would be working as a team member  (developer). As you move up through the grades, you may take roles where  you will be leading teams, be the technical architect, enterprise  architect, Agile coach, etc. At the higher grades, besides all the  technical knowledge you will also have some extra responsibilities like  writing technical proposals, pre-sales, project inceptions, project  management, manage clients expectation, etc. However, some consultants  manage to reach the higher grades and remain totally hands on. That’s  the path I’m following.&lt;br /&gt;&lt;br /&gt;To be successful as a consultant, you need to be a well-rounded  professional. Just knowing a programming language well is far from being  enough to be a good consultant. You are expected to have knowledge in  many different areas since you never know in which project you will end  up and which position in the project you will have. And regardless what  the project is, you need to be ready. Of course that we all know that  is simply impossible to know everything that is out there but at least  you need to show that you have the motivation and drive to learn  whatever is thrown at you.&lt;br /&gt;&lt;br /&gt;Besides the technical skills, another thing that is very important  for a good consultant is soft skills, due to the amount of iteration  with clients. I’m still working to improve mine. :)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What are the prospects?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Over the years, after many different projects, a consultant will have  a good understanding of different types of software projects,  technologies and also will have met a lot of people working for many  different companies. This gives the consultant a good variety of options  for the future.&lt;i&gt;&lt;/i&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;In your experience are you aware of any differences your role has between industries/sectors?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In terms of clients we work for, yes, there are huge differences.  Working for clients where software is not their core business (a big  supermarket chain, a media company, etc) is totally different from  working for clients where software is their core business or is an  extremely important part of it (software products, internet companies,  telcos, etc). There’s also the investment banks, financial companies,  government, gambling, etc. Each client will demand a different type of  service and a different type of expertise. Some clients will ask a  consultancy to help creating the process, roles and responsibilities,  requirements, definite the technology stack, etc. Full freedom. Other  clients, which have a more mature software capability, may ask a  consultancy to provide help with a very specific problem. Sometimes they  just need some good developers for a limited period of time. They may  want someone in there to coach and mentor their own developers. That  means, the role can vary quite a lot, depending on the client.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Reflection and The Future&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What was it like coming into the industry?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Before joining my first consultancy company, I had worked for two  small software houses and I didn’t know much about it. Job was announced  in one of the main Brazilian newspapers. 800+ developers applied and  just 34 were hired after a month long selection process, 4 phases,  including a two week training and group dynamics. My two previous  companies combined had in total 10 people. This consultancy company had  more than one thousand employees just in Sao Paulo. Many thousands  around the world. I was completely lost and a bit scared by the size of  the projects. Before I was writing software for local shops and  businesses and there I was working in projects for multinational  companies and governments. Complete shock. New technologies, new people,  massive projects, multiple teams involved, clients speaking different  languages, etc. After a few months, I was quite comfortable there and  knew that I had made the right choice. I guess that I was very lucky  there, firstly because I was assigned to work on a very technical and  capable team and secondly because for two and a half years I had the  best mentor (my boss) that I could ever have asked for. &lt;br /&gt;&lt;br /&gt;However, joining a modern and more agile consultancy company today is  totally different, much easier and less traumatic, even when working on  big projects for big clients. In general you will be working in smaller  teams (even on long term projects) and following agile methodologies.  The technologies used are accessible to every one. When I started, back  in the 90ies, we couldn’t just go to a website, download certain  technologies and install on our PCs. Many of the technologies were  proprietary. There’s absolutely nothing to fear about joining a  consultancy company today and the world is a much better place now. &lt;img alt=":-)" class="wp-smiley" src="http://s2.wp.com/wp-includes/images/smilies/icon_smile.gif?m=1235673275g" /&gt; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Do you have any thoughts on the future of your role/industry?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I think that while there is a need for software development,  consultancies and consultants will always have a place. However, the  time where consultants were the only or the best specialists in the  market are over. Due to the internet, open source projects, social  networking, user groups, conferences, shared videos, podcasts, etc, any  one, anywhere in the world, has access to the latest technology at the  minute it is released. Consultants now, more than ever, need to be at  the top of their game. Consultancy companies will need to do their best  to get the best professionals in the market in order to survive. They  will need, more than ever, to show to clients that they have the best  people to work on their projects.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;What advice would you give someone entering your industry?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The following advices are valid for any developer starting his or her  career, regardless if he wants to be a consultant, the industry or  career path he will choose:&lt;br /&gt;&lt;br /&gt;- Firstly and most importantly, enjoy and be proud of what you do.  Software development is a very cool profession. During your career,  there will be many people out there that will be using and benefiting  from stuff you created. And this is definitely really cool.&lt;br /&gt;&lt;br /&gt;- If you think you studied hard during university, think again. You  haven’t even started studying hard yet. Software development IS NOT a 9  to 5 profession. Be prepared to study hard, outside working hours, for  the rest of your life.&lt;br /&gt;&lt;br /&gt;- Always aim for jobs where you are going to learn more and not earn  more. Preferably a place where you could have a good mentor. Be patient  because money will come. If you are good and keep learning, you will  have a very decent life throughout your career. If you just aim for the  money instead of learning, you may get a good money now and be  unemployable and out of the market in a few years time.&lt;br /&gt;&lt;br /&gt;- Put a lot of effort on learning the fundamentals of software  development instead of just learning the latest framework. If you have a  good foundation, you will be able to learn any new technology much  faster.&lt;br /&gt;&lt;br /&gt;- Contribute to open source projects, learn from their code base and  take the opportunity to communicate with other contributors.&lt;br /&gt;&lt;br /&gt;- Always have a pet project (you may be excused if you are actively  contributing to an open source project). Pet projects are great for you  to try different technologies, techniques and methodologies. The cool  thing about a pet project is that you have the power to do whatever you  want, whenever you want, making it quite fun to work on. You don’t need  to finish a pet project, in fact, you never will.&lt;br /&gt;&lt;br /&gt;- Join you local user groups. The amount of stuff you learn and people you meet is just priceless.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Have you come across anything or anyone that has helped you move forward in the industry?&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Definitely the mentor I had early on in my career. He was an  exceptional developer and like a father for all of us in the team. He  could hit us as hard as he wanted but no one else was allowed to do it.  He shielded his team (us) from all the external heat and pressure.  Quality was non-negotiable. He was a true believer that “&lt;i&gt;how it’s done is as important as having it done&lt;/i&gt;“,  phrase that I use as my blog’s subtitle. He believed in the  apprenticeship model, although we’ve never used the term. It was there  and then that I learned the true values of what today is called software  craftsmanship. I worked for him and on that team for two and a half  years and by far it was, if not the best, one of the best teams that I've been part of. My mentor gave me everything I needed to become the  professional I am today.&lt;br /&gt;&lt;br /&gt;Twitter: &lt;a href="http://www.twitter.com/sandromancuso"&gt;@sandromancuso&lt;/a&gt;&lt;br /&gt;blog: &lt;a href="http://craftedsw.blogspot.com/"&gt;http://craftedsw.blogspot.com&lt;/a&gt;&lt;br /&gt;LSCC: &lt;a href="http://www.londonswcraft.com/"&gt;http://www.londonswcraft.com&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-2802659874925068063?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/2802659874925068063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/04/working-for-consultancy-companies.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2802659874925068063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2802659874925068063'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/04/working-for-consultancy-companies.html' title='Working for consultancy companies'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-7338101254804050349</id><published>2011-04-02T20:27:00.000+01:00</published><updated>2011-04-02T20:27:36.841+01:00</updated><title type='text'>Frustrations and aspirations of a software craftsman</title><content type='html'>For a while I've been thinking about what makes me like or dislike a project. Having spent a very big part of my career working for consultancy companies, I was exposed to many different environments, industries, team sizes, processes and technologies. There were projects that I absolutely loved, some projects were OK and some were a real pain.&lt;br /&gt;&amp;nbsp; &lt;br /&gt;There were even a couple of times in my career where I questioned myself if the choice of being a software craftsman and keep walking the &lt;a href="http://apprenticeship-patterns.labs.oreilly.com/ch03.html#the_long_road"&gt;long road&lt;/a&gt; would be the best thing for my sanity. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;What makes me dislike a project?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Well, there are many factors. Here are just a few but is far from being a complete list:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Bureaucracy is something that can be really frustrating. That includes process for the sake of process, innumerable cycles of approvals, tortuous and long test and deployment cycles, pointless documentation, and all that anti-agile stuff.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Old technologies or the "wrong" technology for the job is always demotivating. We love new toys. There is nothing more annoying when the technology stack is imposed on the team. "&lt;i&gt;You must use these tools from Oracle or IBM. But, hey, don't look like that. You have support if you need it.&lt;/i&gt;" &lt;/li&gt;&lt;li&gt;Lack of autonomy and credibility. "&lt;i&gt;You are just the developers here. You don't make decisions. You do what you are told to do. There are much smarter people here to worry about the _real_ problems. And by the way, you don't have admin rights to your PC and you can't access a few websites either.&lt;/i&gt;"&lt;/li&gt;&lt;li&gt;Uninteresting domain. It's always difficult to find motivation to build a great software if you don't like what the software does or don't really believe in the business idea.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Demotivated people. How can we find motivation and have team spirit when your colleagues attitude is: "&lt;i&gt;Oh, I just turn up to work, keep my head down and do what I'm told. If something goes wrong, it's not my fault.&lt;/i&gt;"&amp;nbsp;&lt;/li&gt;&lt;li&gt;Finger pointing and highly competitive environment, where no one plays as a team. This is an environment where everyone wants to be the boss, they are always looking for a scapegoat and the less work they do, the more they delegate, the better. If something goes wrong, it would never be their fault. If something goes well, they take all the credit.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Arrogant and unskilled people. Arrogance many times is used as a self-defence mechanism in order to hide the lack of skills a person may have. "&lt;i&gt;I don't need to read any books. I think all these new technologies and methodologies are crap. I've been doing this for years. I know what it is best.&lt;/i&gt;" &lt;/li&gt;&lt;li&gt;Software factory concept. "&lt;i&gt;We need to go faster. Let's throw more developers here. Which ones? Doesn't matter. Just hire some monkeys.&lt;/i&gt;"&lt;/li&gt;&lt;li&gt;&lt;a href="http://parlezuml.com/blog/?postid=147"&gt;Mortgage-Driven Development&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Project managers that think they are the most important member of the team&lt;/li&gt;&lt;li&gt;Very deep hierarchy&lt;/li&gt;&lt;li&gt;You can't help those who don't want to be helped. &lt;/li&gt;&lt;li&gt;I really could go on forever here....&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;So what is really the problem here?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When I first mentally thought about all these items, I realised that almost all the things that make me dislike a project are related to people. Yes, people. One of the few exceptions are &lt;i&gt;uninteresting domain&lt;/i&gt; and &lt;i&gt;old technologies&lt;/i&gt;. So even if I make sure that I don't work on projects related to subjects I have no interest and that use the latest technologies, the people involved may make it very frustrating. Have you ever been on a project where you thought that the project had everything to be a great project but for some reason it was a pain? &lt;br /&gt;&lt;br /&gt;After this analysis, things were not looking good, so I decided to look at all the projects I really enjoyed. It was when I realised that in some of them we didn't use the latest technologies and in a few of them I was not exactly passionate about the domain either. One or two were even quite bureaucratic. So, why did I enjoy them? What was in there that made me put them among the projects I liked the most? Once again, the answer was "people". &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The good projects and what I always would like to find&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;My favourite projects had quite a few things in common but the most important ones were &lt;i&gt;passion&lt;/i&gt;, &lt;i&gt;craftsmanship&lt;/i&gt;, &lt;i&gt;friendship&lt;/i&gt; and &lt;i&gt;trust&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Passion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;It's not because you like something that you are going to be good at it. However, to be really good at something, you must have a passion for it. &lt;/blockquote&gt;&lt;br /&gt;The best people for a job are the ones that love the job. This in the essential quality that drives people to be successful in whatever they decide to do. A passionate person will do whatever is in his or her power to keep acquiring skills and do the best they can. Passionate people bring innovation, they question what they are doing, they want to contribute, they want to get involved, they want to learn. They want to succeed. &lt;b&gt;Passionate people CARE&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Craftsmanship&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;The only way to go fast is to go well - Uncle Bob Martin&lt;/blockquote&gt;&lt;br /&gt;In all my favourite projects, the focus on quality and the willingness to see users satisfied and using the system was always a big thing. The whole team was focused in delivering the best project we could, taking into consideration all the constraints we were under. It was clear to all of us that to be successful we had to be pragmatic. We also always believed that &lt;i&gt;how it is done is as important as having it done&lt;/i&gt;. &lt;br /&gt;Software craftsmen use the right tools for the job, are skilful, are pragmatic, care about the quality of their work, care about their reputation and want to delight every single one of their customers and users. &lt;b&gt;Software craftsmen CARE&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Friendship&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So far I've been talking about passionate people and care. However we know that people have different opinions and there are many ways to do the same thing. Now imagine a room full of very passionate people that don't really get along. In the best scenario, there will be some memorable arguments. In the worst, they will kill each other.&lt;br /&gt;&lt;br /&gt;Friendship is the answer to that. The importance of social events for a team is enormous, even if it is just a few drinks once or twice a month. Like it or not, we spend more time with our colleagues than with our own family, so it is important that we have the friendliest environment possible. Having lunch together at least a few times per week is another thing that can help improve this friendship. Team members need some time together where they are not always just talking about work. Team members need time to know each other.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Among friends people feel comfortable to speak their minds. Working with friends helps to improve the quality of the discussions and no one is worried to &lt;a href="http://apprenticeship-patterns.labs.oreilly.com/ch02.html#expose_your_ignorance"&gt;expose ignorance&lt;/a&gt; or give suggestions. Friends help each other, friends learn from each other, &lt;b&gt;friends CARE&lt;/b&gt; for each other.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Trust&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Once people can demonstrate their commitment and passion, can demonstrate competence, willingness to learn and contribute and are able to deliver the best software possible, trust is easily established. With trust you gain autonomy and are free to decide what it is best for the project and to do your job well. With trust you can be more effective when delegating or sharing tasks. With trust we can remove all the bureaucracy that impedes that we do our job efficiently.&amp;nbsp; &amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Aspirations&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I just wish I could find the things I described above in all projects. Companies should aim to hire passionate and skilful people. People that can contribute to their projects and organisation. People that are willing to share and learn.&lt;br /&gt;&lt;br /&gt;Unfortunately not always we will find all that. In those cases, the only thing we can do is to try our best to change the environment around us. We can try motivate people and share our passion. We can be nice to everyone, respect our colleagues and promote an environment where everyone feels comfortable to ask for help, to help each other and share knowledge. &lt;br /&gt;&lt;br /&gt;With great people we can overcome any obstacle and have an environment where every morning, when we wake up, we would think: "Yay! Today I'll have another great day at work."&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-7338101254804050349?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/7338101254804050349/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/04/frustrations-and-aspirations-of.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7338101254804050349'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7338101254804050349'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/04/frustrations-and-aspirations-of.html' title='Frustrations and aspirations of a software craftsman'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-5847214767365788617</id><published>2011-03-14T00:46:00.000Z</published><updated>2011-03-14T00:46:31.829Z</updated><title type='text'>My first code retreat</title><content type='html'>Yesterday I went to my first &lt;a href="http://coderetreat.com/how-it-works.html"&gt;code retreat&lt;/a&gt;, in Winchester UK. In the past I had been sceptical about code retreats since I had doubts if I would really learn something. However, after speaking to a few developers that had been to one before, I was totally convinced that I should give it a go. I thought, even if I don't learn much, at least I'll have a whole day of fun writing code, catching up with some friends and meeting other developers. That was more than enough for me to be convinced that it would be a great day. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Summary of the day&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There were around 20+ developers. After introductions and explanation of the problem (&lt;a href="http://en.wikipedia.org/wiki/Conway%27s_game_of_life"&gt;Conway's game of life&lt;/a&gt;), we started our first session. Throughout the day, we had 6 or 7 sessions. I can't even remember exactly because it was so enjoyable, intense and fun that even if it had been 20 I wouldn't have noticed.&amp;nbsp; I've paired with some people that I knew before (although never worked with) and some people that I had just met. After each session, we shared what we have learned, approaches we took, problems we faced, etc. If I recollect well, different languages were used and tried including Java, C#, JavaScript, Ruby, Scala and I think Python as well (I'm sure I'm forgetting something).&lt;br /&gt;&lt;br /&gt;The first two sessions we just sat down and tried to solve it, without any constraints, besides TDD, that was mandatory for all sessions. This was good so everyone could get familiar with the problem. From the third session onwards, we were asked to try different approaches, like not using if statements, &lt;a href="http://gojko.net/2009/02/27/thought-provoking-tdd-exercise-at-the-software-craftsmanship-conference/"&gt;TDD as if you meant it&lt;/a&gt;, OOP to the extreme and the best code we could possibly write. At the end of each session, the code is deleted.&lt;br /&gt;&lt;br /&gt;We had a good break for lunch and went to the local pub in the evening.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Things I learned and experienced&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;No matter how much you &lt;i&gt;think&lt;/i&gt; you know, it is still not much and not enough.&lt;/li&gt;&lt;li&gt; Pair-programming with other developers exposes you to different ways of thinking and opens your mind for new ideas.&lt;/li&gt;&lt;li&gt;Seeing and using different languages, makes you see software development with different eyes, giving you a much broader understanding and helps clearing up misconceptions you may have.&lt;/li&gt;&lt;li&gt;You are not alone. Like yourself, there more talented and passionate developers out there willing to share ideas and learn from each other.&lt;/li&gt;&lt;li&gt;I definitely learned a lot and feel I got back from there a better developer.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Besides all the technical learning, it was really great to meet so many talented developers. &lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Thank you&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Firstly I would like to thank &lt;a href="http://twitter.com/despo"&gt;Despo&lt;/a&gt; and &lt;a href="http://twitter.com/sermoa"&gt;Aimee&lt;/a&gt; for organising it and &lt;a href="http://twitter.com/ecomba"&gt;Enrique&lt;/a&gt; for running it (and the great chat in the pub). I also would like to thank all the developers that I paired with for helping to make me a better developer. Finally, I would like to thank all the developers that were there for reinforcing my belief that software development is a great profession, full of talented, bright and passionate people and that we can really make a difference in moving our industry forward.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;I wish you all have a great &lt;a href="http://blog.nexwerk.com/2011/02/16/the-long-road/"&gt;long road&lt;/a&gt; ahead of you and I'm looking forward to meeting you again any time soon.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Links&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://coderetreat.ning.com/events/coderetreat-winchester-uk-1"&gt;Official site for the Winchester Code Retreat&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.meetup.com/london-software-craftsmanship/"&gt;London Software Craftsmanship Community - LSCC&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-5847214767365788617?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/5847214767365788617/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2011/03/my-first-code-retreat.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/5847214767365788617'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/5847214767365788617'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2011/03/my-first-code-retreat.html' title='My first code retreat'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-6729909628427981355</id><published>2010-12-10T00:41:00.000Z</published><updated>2010-12-10T00:41:25.488Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='TDD DSL &quot;Software Craftsmanship&quot; LSCC Fluent'/><title type='text'>Readable Tests: Separating intent from implementation</title><content type='html'>Very recently, I was working on a test class like this:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class AnalyticsExpirationDateManagerTest extends TestCase {&lt;br /&gt;&lt;br /&gt; private static final long ONE_HOUR_TIMEOUT = 1000 * 60 * 60;&lt;br /&gt; private static final long TWO_HOUR_TIMEOUT = ONE_HOUR_TIMEOUT * 2;&lt;br /&gt; &lt;br /&gt; private Map&amp;lt;Parameter, Long&amp;gt; analyticsToTimeout;&lt;br /&gt; private long defaultTimeout;&lt;br /&gt; &lt;br /&gt; private Parameter minTimeoutParam;&lt;br /&gt; @Mock private CacheKeyImpl&amp;lt;Parameter&amp;gt; cacheKey;&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    protected void setUp() throws Exception {&lt;br /&gt;     MockitoAnnotations.initMocks(this);&lt;br /&gt;     &lt;br /&gt;     this.minTimeoutParam = new Parameter("minTimeout", "type");&lt;br /&gt;     &lt;br /&gt;     when(cacheKey.getFirstKey()).thenReturn(minTimeoutParam);&lt;br /&gt;     &lt;br /&gt;     this.analyticsToTimeout = new HashMap&amp;lt;Parameter, Long&amp;gt;();&lt;br /&gt;     this.defaultTimeout = 0;&lt;br /&gt;    }&lt;br /&gt; &lt;br /&gt; public void&lt;br /&gt; testGetExpirationDateWhenAnalyticsToTimeoutsAndCacheKeyAreEmpty() {&lt;br /&gt;  AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager = &lt;br /&gt;    new AnalyticsExpirationDateManager&amp;lt;Long&amp;gt;(analyticsToTimeout, defaultTimeout);&lt;br /&gt;  Date date = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  assertNotNull(date);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testGetExpirationDateWithMinimunTimeoutOfOneHour() {&lt;br /&gt;  this.analyticsToTimeout.put(this.minTimeoutParam, ONE_HOUR_TIMEOUT);&lt;br /&gt;  Collection&amp;lt;Parameter&amp;gt; cacheKeysWithMinTimeoutParam = new ArrayList&amp;lt;Parameter&amp;gt;();&lt;br /&gt;  cacheKeysWithMinTimeoutParam.add(this.minTimeoutParam);&lt;br /&gt;  when(this.cacheKey.getKeys()).thenReturn(cacheKeysWithMinTimeoutParam);&lt;br /&gt;  &lt;br /&gt;  AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager = &lt;br /&gt;   new AnalyticsExpirationDateManager&amp;lt;Long&amp;gt;(analyticsToTimeout, defaultTimeout);&lt;br /&gt;  Date date = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;&lt;br /&gt;  assertNotNull(date);&lt;br /&gt;  Calendar expirationDate = Calendar.getInstance();&lt;br /&gt;  expirationDate.setTime(date);&lt;br /&gt;  &lt;br /&gt;  Calendar currentDate = Calendar.getInstance();&lt;br /&gt;  &lt;br /&gt;  // Check if expiration date is one hour ahead current date. &lt;br /&gt;  int expirationDateHour = expirationDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  int currentDateHour = currentDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  assertTrue(expirationDateHour - currentDateHour == 1);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testGetExpirationDateWhenCacheKeyIsNullAndDefaultTimeoutIsOneHour() {&lt;br /&gt;  CacheKeyImpl&amp;lt;Parameter&amp;gt; NULL_CACHEKEY = null;&lt;br /&gt;  AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager = &lt;br /&gt;   new AnalyticsExpirationDateManager&amp;lt;Long&amp;gt;(analyticsToTimeout, ONE_HOUR_TIMEOUT);&lt;br /&gt;  Date date = manager.getExpirationDate(NULL_CACHEKEY, 0L);&lt;br /&gt;  &lt;br /&gt;  assertNotNull(date);&lt;br /&gt;  Calendar expirationDate = Calendar.getInstance();&lt;br /&gt;  expirationDate.setTime(date);&lt;br /&gt;  &lt;br /&gt;  Calendar currentDate = Calendar.getInstance();&lt;br /&gt;  &lt;br /&gt;  // Check if expiration date hour is the same of current date hour.&lt;br /&gt;  // When cache key is null, system date and time is returned and default timeout is not used.&lt;br /&gt;  int expirationDateHour = expirationDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  int currentDateHour = currentDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  assertTrue(expirationDateHour - currentDateHour == 0);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testGetExpirationDateWithDefaultTimeout() {&lt;br /&gt;  // Default timeout is used when no time out is specified.&lt;br /&gt;  Collection&amp;lt;Parameter&amp;gt; cacheKeysWithoutTimeoutParam = new ArrayList&amp;lt;Parameter&amp;gt;();&lt;br /&gt;  cacheKeysWithoutTimeoutParam.add(new Parameter("name", "type"));&lt;br /&gt;  when(this.cacheKey.getKeys()).thenReturn(cacheKeysWithoutTimeoutParam);&lt;br /&gt;&lt;br /&gt;  AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager = &lt;br /&gt;   new AnalyticsExpirationDateManager&amp;lt;Long&amp;gt;(analyticsToTimeout, ONE_HOUR_TIMEOUT);&lt;br /&gt;  Date date = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  &lt;br /&gt;  assertNotNull(date);&lt;br /&gt;  Calendar expirationDate = Calendar.getInstance();&lt;br /&gt;  expirationDate.setTime(date);&lt;br /&gt;  &lt;br /&gt;  Calendar currentDate = Calendar.getInstance();&lt;br /&gt;  &lt;br /&gt;  // Check if expiration date is one hour ahead current date. &lt;br /&gt;  int expirationDateHour = expirationDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  int currentDateHour = currentDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  assertTrue(expirationDateHour - currentDateHour == 1);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testGetExpirationDateWhenMinTimeoutIsSetAfterCreation() {&lt;br /&gt;  AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager = &lt;br /&gt;   new AnalyticsExpirationDateManager&amp;lt;Long&amp;gt;(analyticsToTimeout, ONE_HOUR_TIMEOUT);&lt;br /&gt;  manager.setExpirationTimeout(this.minTimeoutParam.getName(), TWO_HOUR_TIMEOUT);&lt;br /&gt;  &lt;br /&gt;  Date date = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  &lt;br /&gt;  assertNotNull(date);&lt;br /&gt;  Calendar expirationDate = Calendar.getInstance();&lt;br /&gt;  expirationDate.setTime(date);&lt;br /&gt;  &lt;br /&gt;  Calendar currentDate = Calendar.getInstance();&lt;br /&gt;  &lt;br /&gt;  // Check if expiration date is two hour ahead current date. &lt;br /&gt;  int expirationDateHour = expirationDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  int currentDateHour = currentDate.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;  assertTrue("Error", expirationDateHour - currentDateHour == 2);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Quite frightening, isn't it? Very difficult to understand what's going on there. &lt;br /&gt;&lt;br /&gt;The class above covers 100% of the class under test and all the tests are valid tests, in terms of what is being tested. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Problems&lt;/b&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;There are quite a few problems here:&lt;br /&gt;- The intent (what) and implementation (how) are mixed, making the tests very hard to read;&lt;br /&gt;- There is quite a lot of duplication among the test methods;&lt;br /&gt;- There is also a bug in the test methods when comparing dates, trying to figure out how many hours one date is ahead of the other. When running these tests in the middle of the day, they work fine. If running them between 22:00hs and 00:00hs, they break. The reason is that the hour calculation does not take into consideration the day. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Making the tests more readable&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Besides testing the software, tests should also be seen as documentation, where business rules are clearly specified. Since the tests here are quite messy, understanding the intention and detecting bugs can be quite difficult. &lt;br /&gt;&lt;br /&gt;I've done quite a few refactorings to this code in order to make it more readable, always working in small steps and constantly re-running the tests after each change. I'll try to summarise my steps for clarity and brevity. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Fixing the hour calculation bug&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;One of the first things that I had to do was to fix the hour calculation bug. In order to fix the bug across all test methods, I decided to extract the hour calculation into a separate class, removing all the duplication from the test methods. Using small steps, I took the opportunity to construct this new class called &lt;i&gt;DateComparator&lt;/i&gt; (yes, I know I suck naming classes) using some internal Domain Specific Language (DSL) techniques. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class DateComparator {&lt;br /&gt; &lt;br /&gt; private Date origin;&lt;br /&gt; private Date target;&lt;br /&gt; private long milliseconds;&lt;br /&gt; private long unitsOfTime;&lt;br /&gt; &lt;br /&gt; private DateComparator(Date origin) {&lt;br /&gt;  this.origin = origin;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static DateComparator date(Date origin) {&lt;br /&gt;  return new DateComparator(origin);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public DateComparator is(long unitsOfTime) {&lt;br /&gt;  this.unitsOfTime = unitsOfTime;&lt;br /&gt;  return this;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public DateComparator hoursAhead() {&lt;br /&gt;  this.milliseconds = unitsOfTime * 60 * 60 * 1000;&lt;br /&gt;  return this;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static long hours(int hours) {&lt;br /&gt;  return hoursInMillis(hours);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; private static long hoursInMillis(int hours) {&lt;br /&gt;  return hours * 60 * 60 * 1000;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public boolean from(Date date) {&lt;br /&gt;  this.target = date;&lt;br /&gt;  return this.checkDifference();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; private boolean checkDifference() {&lt;br /&gt;  return (origin.getTime() - target.getTime() &amp;gt;= this.milliseconds);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now, I can use it to replace the test logic in the test methods. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. Extracting details into a super class&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;This step may seem a bit controversial at first, but can be an interesting approach for separating the &lt;i&gt;what&lt;/i&gt; from &lt;i&gt;how&lt;/i&gt;. The idea is to move tests set up, field declarations, initialisation logic, everything that is related to the test implementation (&lt;i&gt;how&lt;/i&gt;) to a super class, leaving the test class just with the test methods (&lt;i&gt;what&lt;/i&gt;). &lt;br /&gt;&lt;br /&gt;Although this many not be a good OO application of the IS-A rule, I think this is a good compromise in order to achieve better readability in the test class. &lt;br /&gt;&lt;br /&gt;NOTE: Logic can be moved to a super class, external classes (helpers, builders, etc) or both. &lt;br /&gt;&lt;br /&gt;Here is the super class code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public abstract class BaseTestForAnalyticsExperationDateManager extends TestCase {&lt;br /&gt;&lt;br /&gt; protected Parameter minTimeoutParam;&lt;br /&gt; @Mock protected CacheKeyImpl&amp;lt;Parameter&amp;gt; cacheKey;&lt;br /&gt; protected Date systemDate;&lt;br /&gt; protected CacheKeyImpl&amp;lt;Parameter&amp;gt; NULL_CACHEKEY = null;&lt;br /&gt; protected AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager;&lt;br /&gt;&lt;br /&gt; @Override&lt;br /&gt; protected void setUp() throws Exception {&lt;br /&gt;  MockitoAnnotations.initMocks(this);&lt;br /&gt;  this.minTimeoutParam = new Parameter("minTimeout", "type");&lt;br /&gt;  when(cacheKey.getFirstKey()).thenReturn(minTimeoutParam);&lt;br /&gt;  this.systemDate = new Date();&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; protected void assertThat(boolean condition) {&lt;br /&gt;  assertTrue(condition);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; protected void addMinimunTimeoutToCache() {&lt;br /&gt;  this.configureCacheResponse(this.minTimeoutParam);&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; protected void doNotIncludeMinimunTimeoutInCache() {&lt;br /&gt;  this.configureCacheResponse(new Parameter("name", "type"));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; private void configureCacheResponse(Parameter parameter) {&lt;br /&gt;  Collection&amp;lt;Parameter&amp;gt; cacheKeysWithMinTimeoutParam = new ArrayList&amp;lt;Parameter&amp;gt;();&lt;br /&gt;  cacheKeysWithMinTimeoutParam.add(parameter);&lt;br /&gt;  when(this.cacheKey.getKeys()).thenReturn(cacheKeysWithMinTimeoutParam);&lt;br /&gt; }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;3. Move creation and configuration of the object under test to a builder class&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The construction and configuration of the &lt;i&gt;AnalyticsExpirationDateManager&lt;/i&gt; is quite verbose and adds a lot of noise to the test. Once again I'll be using a builder class in order to make the code more readable and segregate responsibilities. Here is the builder class:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class AnalyticsExpirationDateManagerBuilder {&lt;br /&gt; &lt;br /&gt; protected static final long ONE_HOUR = 1000 * 60 * 60;&lt;br /&gt;&lt;br /&gt; protected Parameter minTimeoutParam;&lt;br /&gt; private AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; manager;&lt;br /&gt; private Map&amp;lt;Parameter, Long&amp;gt; analyticsToTimeouts = new HashMap&amp;lt;Parameter, Long&amp;gt;();&lt;br /&gt; protected long defaultTimeout = 0;&lt;br /&gt; private Long expirationTimeout;&lt;br /&gt; private Long minimunTimeout;&lt;br /&gt;&lt;br /&gt; private AnalyticsExpirationDateManagerBuilder() {&lt;br /&gt;  this.minTimeoutParam = new Parameter("minTimeout", "type");&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static AnalyticsExpirationDateManagerBuilder aExpirationDateManager() {&lt;br /&gt;  return new AnalyticsExpirationDateManagerBuilder();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public static long hours(int quantity) {&lt;br /&gt;  return quantity * ONE_HOUR;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public AnalyticsExpirationDateManagerBuilder withDefaultTimeout(long milliseconds) {&lt;br /&gt;  this.defaultTimeout = milliseconds;&lt;br /&gt;  return this;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public AnalyticsExpirationDateManagerBuilder withExpirationTimeout(long milliseconds) {&lt;br /&gt;  this.expirationTimeout = new Long(milliseconds);&lt;br /&gt;  return this;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public AnalyticsExpirationDateManagerBuilder withMinimunTimeout(long milliseconds) {&lt;br /&gt;  this.minimunTimeout = new Long(milliseconds);&lt;br /&gt;  return this;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public AnalyticsExpirationDateManager&amp;lt;Long&amp;gt; build() {&lt;br /&gt;  if (this.minimunTimeout != null) {&lt;br /&gt;   analyticsToTimeouts.put(minTimeoutParam, minimunTimeout);&lt;br /&gt;  }&lt;br /&gt;  this.manager = new AnalyticsExpirationDateManager&lt;long&gt;(analyticsToTimeouts, defaultTimeout);&lt;br /&gt;  if (this.expirationTimeout != null) {&lt;br /&gt;   this.manager.setExpirationTimeout(minTimeoutParam.getName(), expirationTimeout);&lt;br /&gt;  }&lt;br /&gt;  return this.manager;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/long&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;The final version of the test class &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;After many small steps, that's how the test class looks like. I took the opportunity to rename the test methods as well. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;import static com.mycompany.AnalyticsExpirationDateManagerBuilder.*;&lt;br /&gt;import static com.mycompany.DateComparator.*;&lt;br /&gt;&lt;br /&gt;public class AnalyticsExpirationDateManagerTest extends BaseTestForAnalyticsExperationDateManager {&lt;br /&gt;&lt;br /&gt; public void&lt;br /&gt; testExpirationTimeWithJustDefaultValues() {&lt;br /&gt;  manager = aExpirationDateManager().build();&lt;br /&gt;  Date cacheExpiration = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  assertThat(dateOf(cacheExpiration).is(0).hoursAhead().from(systemDate));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testExpirationTimeWithMinimunTimeoutOfOneHour() {&lt;br /&gt;     addMinimunTimeoutToCache();  &lt;br /&gt;  manager = aExpirationDateManager()&lt;br /&gt;      .withMinimunTimeout(hours(1))&lt;br /&gt;      .build();&lt;br /&gt;  Date cacheExpiration = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  assertThat(dateOf(cacheExpiration).is(1).hoursAhead().from(systemDate));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testExpirationTimeWhenCacheKeyIsNullAndDefaultTimeoutIsOneHour() {&lt;br /&gt;  manager = aExpirationDateManager()&lt;br /&gt;      .withDefaultTimeout(hours(1))&lt;br /&gt;      .build();&lt;br /&gt;  Date cacheExpiration = manager.getExpirationDate(NULL_CACHEKEY, 0L);&lt;br /&gt;  // When cache key is null, system date and time is returned and default timeout is not used.&lt;br /&gt;  assertThat(dateOf(cacheExpiration).is(0).hoursAhead().from(systemDate));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testExpirationTimeWithDefaultTimeout() {&lt;br /&gt;  doNotIncludeMinimunTimeoutInCache();&lt;br /&gt;  manager = aExpirationDateManager()&lt;br /&gt;      .withDefaultTimeout(hours(1))&lt;br /&gt;      .build();&lt;br /&gt;  Date cacheExpiration = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  assertThat(dateOf(cacheExpiration).is(1).hoursAhead().from(systemDate));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void &lt;br /&gt; testExpirationTimeWhenExpirationTimeoutIsSet() {&lt;br /&gt;  manager = aExpirationDateManager()&lt;br /&gt;      .withDefaultTimeout(hours(1))&lt;br /&gt;      .withExpirationTimeout(hours(2))&lt;br /&gt;      .build();&lt;br /&gt;  Date cacheExpiration = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;  // Expiration timeout has precedence over default timeout.&lt;br /&gt;  assertThat(dateOf(cacheExpiration).is(2).hoursAhead().from(systemDate));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-size: large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Test classes should be easy to read. They should express intention, system behaviour, business rules. Test classes should express how the system works. They are executable requirements and specifications and should be a great source of information for any developer joining the project. &lt;br /&gt;&lt;br /&gt;In order to achieve that, we need to try to keep our test methods divided in just 3 simple instructions. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;1. Context&lt;/b&gt;: The state of the object being tested. Here is where we set all the attributes and mock dependencies. Using variations of the Builder pattern can greatly enhance readability.&lt;br /&gt;&lt;pre class="brush: java"&gt;manager = aExpirationDateManager()&lt;br /&gt;                .withDefaultTimeout(hours(1))&lt;br /&gt;                .withExpirationTimeout(hours(2))&lt;br /&gt;                .build();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;2. Operation&lt;/b&gt;: The operation being tested. Here is where the operation is invoked.&lt;br /&gt;&lt;pre class="brush: java"&gt;Date cacheExpiration = manager.getExpirationDate(cacheKey, 0L);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;3. Assertion&lt;/b&gt;: Here is where you specify the behaviour expected. The more readable this part is, the better. Using DSL-style code is probably the best way to express the intent of the test. &lt;br /&gt;&lt;pre class="brush: java"&gt;assertThat(dateOf(cacheExpiration).is(2).hoursAhead().from(systemDate));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In this post I went backwards. I've started from a messy test class and refactored it to a more readable implementation. As many people now are doing TDD, I wanted to show how we can improve an existing test. For new tests, I would suggest that you start writing the tests following the &lt;i&gt;Context&lt;/i&gt; &amp;gt;&amp;gt; &lt;i&gt;Operation&lt;/i&gt; &amp;gt;&amp;gt; &lt;i&gt;Assertion&lt;/i&gt; approach. Try writing the test code in plain English. Once the test intent is clear, start replacing the plain English text with Java internal DSL code, keeping the implementation out of the test class.&lt;br /&gt;&lt;br /&gt;&lt;i&gt;PS: The ideas for this blog post came from a few discussions I had during the Software Craftsmanship Round-table meetings promoted by the &lt;a href="http://www.meetup.com/london-software-craftsmanship/"&gt;London Software Craftsmanship Community (LSCC).&lt;/a&gt; &lt;/i&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-6729909628427981355?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/6729909628427981355/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/12/readable-tests-separating-intent-from.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/6729909628427981355'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/6729909628427981355'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/12/readable-tests-separating-intent-from.html' title='Readable Tests: Separating intent from implementation'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-2732083154762428592</id><published>2010-12-07T21:25:00.000Z</published><updated>2010-12-07T21:25:22.740Z</updated><title type='text'>A basic ActiveRecord implementation in Java</title><content type='html'>Recently I was looking for different ways to develop applications in Java and thought that it would be interesting trying to use &lt;a href="http://en.wikipedia.org/wiki/Active_record_pattern"&gt;ActiveRecord&lt;/a&gt; in my persistence layer instead of implementing the traditional approach with a DAO. My idea is not to create my own ActiveRecord framework but use the existing ones as a support for this approach. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The scope:&lt;/b&gt; Write functional tests that could prove that the methods &lt;i&gt;save&lt;/i&gt; and &lt;i&gt;delete&lt;/i&gt; on an entity work. I'll use an entity called &lt;i&gt;Traveller&lt;/i&gt; for this example. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The technology:&lt;/b&gt; I chose to use the following frameworks: Spring 3.0.5, JPA 2.0, Hibernate 3.5.3, AspectJ 1.6.9, JUnit 4.8.2, Maven 2.2.1, Eclipse Helios and MySQL 5.x&lt;br /&gt;&lt;br /&gt;I'll be omitting things that are not too important. For all the details, please have a look at the whole source code at:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;a href="https://github.com/sandromancuso/cqrs-activerecord"&gt;https://github.com/sandromancuso/cqrs-activerecord&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;Let's start with the test class:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;@RunWith(SpringJUnit4ClassRunner.class)&lt;br /&gt;@ContextConfiguration(&lt;br /&gt;  locations={&lt;br /&gt;    "file:src/test/resources/applicationContext-test.xml",&lt;br /&gt;    "file:src/main/resources/applicationContext-services.xml"    &lt;br /&gt;  })&lt;br /&gt;@TransactionConfiguration(transactionManager = "myTransactionManager", defaultRollback = true)&lt;br /&gt;@Transactional&lt;br /&gt;public class TravellerActiveRecordIntegrationTest extends BaseTravellerIntegration {&lt;br /&gt; &lt;br /&gt; @Test public void &lt;br /&gt; testTravellerSelfCreation() {&lt;br /&gt;  assertThereAreNoTravellers(named("John"), from("England"));&lt;br /&gt;  &lt;br /&gt;  Traveller traveller = aTraveller().named("John").from("England").build();&lt;br /&gt;  traveller.save();&lt;br /&gt;  &lt;br /&gt;  assertThereIsASingleTraveller(named("John"), from("England"));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Test public void&lt;br /&gt; testTravellerEdition() {&lt;br /&gt;  Traveller traveller = aTraveller().named("John").from("England").build();&lt;br /&gt;  traveller.save();&lt;br /&gt;  &lt;br /&gt;  traveller.setName("Sandro");&lt;br /&gt;  traveller.setCountry("Brazil");&lt;br /&gt;  traveller.save();&lt;br /&gt;  &lt;br /&gt;  assertThereAreNoTravellers(named("John"), from("England"));&lt;br /&gt;  assertThereIsASingleTraveller(named("Sandro"), from("Brazil"));  &lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; @Test public void &lt;br /&gt; testDeleteTraveller() {&lt;br /&gt;  Traveller traveller = aTraveller().named("John").from("England").build();&lt;br /&gt;  traveller.save();&lt;br /&gt;&lt;br /&gt;  traveller.delete();&lt;br /&gt;  assertThereAreNoTravellers(named("John"), from("England"));&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A few things to notice about this test class:&lt;br /&gt;- As this test is meant to insert and delete from the database, I set it to always rollback the transaction after each test, meaning that nothing will be committed to the database permanently. This is important in order to execute the tests multiple times and get the same results.&lt;br /&gt;- The test class extends a base class, that has the methods &lt;i&gt;assertThereAreNoTravellers&lt;/i&gt; and &lt;i&gt;assertThereIsASingleTraveller&lt;/i&gt;. The advantage of doing that is that you separate what you want to test from how you want to test, making the test class clean and focused on the intention. &lt;br /&gt;- Note that I also used the Builder pattern to build the traveller instance instead of using the setter methods. This is a nice approach in order to make your tests more readable.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Traveller entity implementation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So now, let's have a look at the Traveller entity implementation. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;@Entity&lt;br /&gt;@Table(name="traveller")&lt;br /&gt;@EqualsAndHashCode(callSuper=false)&lt;br /&gt;@Configurable&lt;br /&gt;public @Data class Traveller extends BaseEntity {&lt;br /&gt;&lt;br /&gt; @Id @GeneratedValue(strategy=GenerationType.AUTO)&lt;br /&gt; private long id;&lt;br /&gt; private String name;&lt;br /&gt; private String country;&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The &lt;i&gt;Traveller&lt;/i&gt; class is a normal JPA entity as you can see by the &lt;i&gt;@Entity&lt;/i&gt;, &lt;i&gt;@Table&lt;/i&gt;, &lt;i&gt;@Id&lt;/i&gt; and &lt;i&gt;@GenereratedValue&lt;/i&gt; annotations. To reduce the boiler place code like getters, setters, toString() and hashCode(), I'm using &lt;a href="http://projectlombok.org/"&gt;Lombok&lt;/a&gt;, that is a small framework that generate all that for us. Just add a &lt;i&gt;@Data&lt;/i&gt; annotation. &lt;br /&gt;&lt;br /&gt;The real deal here is Traveller's super class &lt;i&gt;BaseEntity&lt;/i&gt; (for a lack of inspiration to find better name). Let's have a look:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;@Configurable&lt;br /&gt;public abstract class BaseEntity {&lt;br /&gt;&lt;br /&gt; @PersistenceContext&lt;br /&gt; protected EntityManager em;&lt;br /&gt;&lt;br /&gt; public abstract long getId();&lt;br /&gt;    &lt;br /&gt; public void save() {&lt;br /&gt;  if (getId() == 0) {&lt;br /&gt;   this.em.persist(this);&lt;br /&gt;  } else {&lt;br /&gt;   this.em.merge(this);&lt;br /&gt;  }&lt;br /&gt;  this.em.flush();&lt;br /&gt; } &lt;br /&gt; &lt;br /&gt; public void delete() {&lt;br /&gt;  this.em.remove(this);&lt;br /&gt;  this.em.flush();&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt; public void setEntityManager(EntityManager em) {&lt;br /&gt;  this.em = em;&lt;br /&gt; }&lt;br /&gt; &lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The BaseEntity class has quite a few things that can be discussed.  &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The save() method&lt;/b&gt;: I've chosen to have a single method that can either insert or update an entity, based on its &lt;i&gt;id&lt;/i&gt;. The problem with this approach is that, firstly, the method has more than one responsibility, making it a bit confusing to understand what it really does. Secondly it relies on the entities id, that needs to be a &lt;i&gt;long&lt;/i&gt;, making it a very specific and weak implementation. The advantage is that from the outside (client code), you don't need to worry about the details. Just simple call &lt;i&gt;save()&lt;/i&gt; and you are done. If you prefer a more generic and more cohesive implementation, make the &lt;i&gt;getId()&lt;/i&gt; method return a generic type and split the &lt;i&gt;save()&lt;/i&gt; method into a &lt;i&gt;create()&lt;/i&gt; and &lt;i&gt;update()&lt;/i&gt; methods. My idea here was just to make it simple to use.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;EntityManager dependency&lt;/b&gt;: Here is where the biggest problem lies. For it to work well, every time a new instance of a entity is created, either by using &lt;i&gt;new EntityXYZ() &lt;/i&gt;by hand or when it is created by a framework (e.g. as a result of a JPA / Hibernate query), we want the entity manager to be injected automatically. The only way I found to make it work is using aspects with AspectJ and Spring. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Configuring AspectJ and Spring&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;My idea here is not to give a full explanation about the whole AspectJ and Spring integration, mainly because I don't know it very well myself. I'll just give the basic steps to make this example work.&lt;br /&gt;&lt;br /&gt;First add &lt;i&gt;@Configurable&lt;/i&gt; to the Entity. This will tell that the entity will be managed by Spring. However, Spring is not aware of instances of the entity, in this case, &lt;i&gt;Traveller&lt;/i&gt;, being created. This is why we need AspectJ. The only thing we need to do is to add the following line to our Spring context xml file.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;&amp;lt;context:load-time-weaver /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This makes AspectJ intercept the creation of beans annotated with @Configurable and tells Spring to inject the dependencies. In order to the load-time weaver (LTW) work, we need to override JVM's class loading so that the first time our entity classes are loaded, AspectJ can kick in, the @Configurable annotation is discovered and all the dependencies are injected. For that we need to pass the following parameter to the JVM:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;-javaagent:&amp;lt;path-to-your-maven-repository&amp;gt;/.m2/repository/org/springframework/spring-instrument/3.0.5.RELEASE/spring-instrument-3.0.5.RELEASE.jar&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The snippet above is what we must use if using Spring 3.0.x. It works fine inside Eclipse but apparently it has some conflicts with Maven 2.2.1. If you run into any problems, you can use the old version below. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;-javaagent:&amp;lt;path-to-your-maven-repository&amp;gt;/.m2/repository/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Another thing that is a good idea is to add the &lt;i&gt;aop.xml&lt;/i&gt; file to your project, limiting the classes that will be affected by AspectJ. Add the &lt;i&gt;aop.xml&lt;/i&gt; to &lt;i&gt;src/main/resources/META-INF&lt;/i&gt; folder.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;aspectj&gt;&lt;br /&gt; &lt;weaver&gt;&lt;br /&gt;  &lt;br /&gt;  &amp;lt;include within="com.lscc.ddddemo.model.entity.*" /&amp;gt;&lt;br /&gt;  &amp;lt;include within="com.lscc.ddddemo.model.entity.builder.*" /&amp;gt;&lt;br /&gt;  &amp;lt;exclude within="*..*CGLIB*" /&amp;gt;&lt;br /&gt; &lt;/weaver&gt;&lt;br /&gt;&lt;br /&gt; &lt;aspects&gt;&lt;/aspects&gt;&lt;br /&gt;&lt;/aspectj&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;NOTE&lt;/b&gt;: The exclude clause is important to avoid some conflicts during the integration test. AspectJ sometimes tries to do some magic with the test classes as well causing a few problems and the exclude clause avoids that. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Making the integration test work&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I'll be using MySQL, so I'll need a database with the following table there:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: sql"&gt;CREATE TABLE `traveller` (&lt;br /&gt;`id` int(11) NOT NULL AUTO_INCREMENT,&lt;br /&gt;`name` varchar(45) NOT NULL,&lt;br /&gt;`country` varchar(45) NOT NULL,&lt;br /&gt;PRIMARY KEY (`id`)&lt;br /&gt;) ENGINE=InnoDB &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As I'm using JPA 2.0, we need a &lt;i&gt;persistence.xml&lt;/i&gt; that must be located at src/main/resources/META-INF&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;persistence version="2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/persistence" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"&gt;&lt;br /&gt; &lt;br /&gt;    &lt;persistence-unit name="testPU"&gt;&lt;br /&gt;        &lt;class&gt;com.lscc.ddddemo.model.entity.Traveller&lt;/class&gt;&lt;br /&gt; &lt;br /&gt;        &lt;properties&gt;&lt;br /&gt;            &amp;lt;property name="hibernate.show_sql" value="true" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.format_sql" value="true" /&amp;gt;&lt;br /&gt; &lt;br /&gt;            &amp;lt;property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/lscc-ddd" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.connection.username" value="root" /&amp;gt;&lt;br /&gt; &lt;br /&gt;            &amp;lt;property name="hibernate.c3p0.min_size" value="5" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.c3p0.max_size" value="20" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.c3p0.timeout" value="300" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.c3p0.max_statements"&lt;br /&gt;                    value="50" /&amp;gt;&lt;br /&gt;            &amp;lt;property name="hibernate.c3p0.idle_test_period"&lt;br /&gt;                    value="3000" /&amp;gt;&lt;br /&gt;        &lt;/properties&gt;&lt;br /&gt;    &lt;/persistence-unit&gt;&lt;br /&gt; &lt;br /&gt;&lt;/persistence&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In our Spring configuration, we also need to tell Spring how to create an EntityManager, providing the EntityManager Factory:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;beans xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemalocation="http://www.springframework.org/schema/beans&lt;br /&gt;        http://www.springframework.org/schema/beans/spring-beans.xsd&lt;br /&gt;        http://www.springframework.org/schema/aop&lt;br /&gt;        http://www.springframework.org/schema/aop/spring-aop.xsd&lt;br /&gt;        http://www.springframework.org/schema/tx&lt;br /&gt;        http://www.springframework.org/schema/tx/spring-tx.xsd&lt;br /&gt;        http://www.springframework.org/schema/context&lt;br /&gt;        http://www.springframework.org/schema/context/spring-context.xsd"&gt;&lt;br /&gt;        &lt;br /&gt;    &lt;bean class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" id="entityManagerFactory"&gt;&lt;br /&gt;        &amp;lt;property name="persistenceUnitName" value="testPU" /&amp;gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;tx:annotation-driven transaction-manager="myTransactionManager" /&amp;gt;&lt;br /&gt; &lt;br /&gt;    &lt;bean class="org.springframework.orm.jpa.JpaTransactionManager" id="myTransactionManager"&gt;&lt;br /&gt;        &amp;lt;property name="entityManagerFactory" ref="entityManagerFactory" /&amp;gt;&lt;br /&gt;    &lt;/bean&gt;&lt;br /&gt;       &lt;br /&gt;&lt;/beans&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In order to separate unit tests and integration tests in my Maven project, I've added a different profile for the integration tests in my &lt;i&gt;pom.xml&lt;/i&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: xml"&gt;&lt;profile&gt;&lt;br /&gt;   &lt;id&gt;with-integration-tests&lt;/id&gt;&lt;br /&gt;   &lt;build&gt;&lt;br /&gt;    &lt;plugins&gt;&lt;br /&gt;     &lt;plugin&gt;&lt;br /&gt;      &lt;groupid&gt;org.apache.maven.plugins&lt;/groupid&gt;&lt;br /&gt;      &lt;artifactid&gt;maven-surefire-plugin&lt;/artifactid&gt;&lt;br /&gt;      &lt;configuration&gt;&lt;br /&gt;       &lt;forkmode&gt;always&lt;/forkmode&gt;&lt;br /&gt;       &lt;argline&gt;-javaagent:/Users/sandro.mancuso/.m2/repository/org/springframework/spring-agent/2.5.6/spring-agent-2.5.6.jar&lt;/argline&gt;&lt;br /&gt;      &lt;/configuration&gt;&lt;br /&gt;      &lt;version&gt;2.5&lt;/version&gt;&lt;br /&gt;      &lt;inherited&gt;true&lt;/inherited&gt;&lt;br /&gt;      &lt;executions&gt;&lt;br /&gt;       &lt;execution&gt;&lt;br /&gt;        &lt;id&gt;integration-tests&lt;/id&gt;&lt;br /&gt;        &lt;phase&gt;integration-test&lt;/phase&gt;&lt;br /&gt;        &lt;goals&gt;&lt;br /&gt;         &lt;goal&gt;test&lt;/goal&gt;&lt;br /&gt;        &lt;/goals&gt;&lt;br /&gt;        &lt;configuration&gt;&lt;br /&gt;         &lt;excludes&gt;&lt;br /&gt;          &lt;exclude&gt;**/common/*&lt;/exclude&gt;&lt;br /&gt;         &lt;/excludes&gt;&lt;br /&gt;         &lt;includes&gt;&lt;br /&gt;          &lt;include&gt;**/*IntegrationTest.java&lt;/include&gt;&lt;br /&gt;         &lt;/includes&gt;&lt;br /&gt;        &lt;/configuration&gt;&lt;br /&gt;       &lt;/execution&gt;&lt;br /&gt;      &lt;/executions&gt;&lt;br /&gt;     &lt;/plugin&gt;&lt;br /&gt;    &lt;/plugins&gt;&lt;br /&gt;   &lt;/build&gt;&lt;br /&gt;  &lt;/profile&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So now, if you want to run the integration tests from the command line, just type:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;mvn clean install -Pwith-integration-tests&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If running the tests from inside Eclipse, don't forget to add the &lt;i&gt;-javaagent&lt;/i&gt; paramenter to the VM. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;So now, from anywhere in your application you can do some thing like:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;Traveller traveller = new Traveller();&lt;br /&gt;traveller.setName("John");&lt;br /&gt;traveller.setCountry("England");&lt;br /&gt;traveller.save();&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The advantage of using the ActiveRecord:&lt;br /&gt;- Code becomes much simpler;&lt;br /&gt;- There is almost no reason for a DAO layer any more;&lt;br /&gt;- Code is more explicit in its intent.&lt;br /&gt;&lt;br /&gt;The disadvantages: &lt;br /&gt;- Entities will need to inherit from a base class;&lt;br /&gt;- Entities would have more than one responsibility (against the &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;Single Responsibility Principle&lt;/a&gt;);&lt;br /&gt;- Infrastructure layer (EntityManager) would be bleeding into our domain objects. &lt;br /&gt;&lt;br /&gt;In my view, I like the simplicity of the ActiveRecord pattern. In the past 10 years we've been designing Java web applications where our entities are anaemic, having state (getters and setters) and no behaviour. So at the end, they are pure data structures. I feel that entities must be &lt;a href="http://craftedsw.blogspot.com/2010/05/empowering-your-entities_24.html"&gt;empowered&lt;/a&gt; and with techniques like that, we can do it, abstracting the persistence layer.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;I'm still not convinced that from now on I'll be using ActiveRecord instead of DAOs and POJOs but I'm glad that now there is a viable option. I'll need to try it in a real project, alongside with Command Query Responsibility Segregation (CQRS) pattern to see how I will feel about it. I'm really getting sick of the standard Action/Service/DAO way to develop web applications in Java instead of having a proper domain model. &lt;br /&gt;&lt;br /&gt;By the way, to make the whole thing work, I had loads of problems to find the right combination of libraries. Please have a look at my pom.xml file for details. I'll be evolving this code base to try different things so when you look at it, it may not be exactly as it is described here.&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;a href="https://github.com/sandromancuso/cqrs-activerecord"&gt;https://github.com/sandromancuso/cqrs-activerecord&lt;/a&gt;&lt;/blockquote&gt;&lt;br /&gt;Interesting links with more technical details:&lt;br /&gt;&lt;a href="http://nurkiewicz.blogspot.com/2009/10/ddd-in-spring-made-easy-with-aspectj.html"&gt;http://nurkiewicz.blogspot.com/2009/10/ddd-in-spring-made-easy-with-aspectj.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://blog.m1key.me/2010/06/integration-testing-your-spring-3-jpa.html"&gt;http://blog.m1key.me/2010/06/integration-testing-your-spring-3-jpa.html&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-2732083154762428592?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/2732083154762428592/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/12/basic-activerecord-implementation-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2732083154762428592'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2732083154762428592'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/12/basic-activerecord-implementation-in.html' title='A basic ActiveRecord implementation in Java'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-780338124898600545</id><published>2010-09-27T22:41:00.000+01:00</published><updated>2010-09-27T22:42:11.872+01:00</updated><title type='text'>Bad Code: The Invisible Threat</title><content type='html'>&lt;span class="value"&gt;One of the first things said by the non-believers of the &lt;a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html"&gt;software craftsmanship&lt;/a&gt; movement was that good and clean code is not enough to guarantee the success of a project. And yes, they are absolutely right. There are innumerable reasons which would make a project to fail ranging from business strategy to competitors, project management, cost, time to market, partnerships, technical limitations, integrations, etc. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;Due to the amount of important things a software project may have, organisations tend not to pay to much attention to things that are considered &lt;i&gt;less&lt;/i&gt; important, like the quality of the software being developed. It is believed that with a good management team, deep hierarchies, micro management, strict process and a large amount of &lt;i&gt;good&lt;/i&gt; documentation, the project will succeed. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="value"&gt;In a software project, the most important deliverable is the software itself. Anything else is secondary. &lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span class="value"&gt;Many organisations see software development as a production line where the workers (developers) are viewed as less skilled than their &lt;i&gt;high-qualified&lt;/i&gt; and much more well paid managers. Very rarely companies like that will be able to attract or retain good software developers, leaving their entire business on the hands of mediocre professionals.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;b&gt;&lt;span class="value"&gt;Look after your garden&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div style="text-align: right;"&gt;Rather than construction, programming is more like gardening. - &lt;a href="http://amzn.to/b0mtSQ"&gt;&lt;i&gt;&lt;span class="value"&gt;The Pragmatic Programmer&lt;/span&gt;&lt;/i&gt;&lt;/a&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span class="value"&gt;Code is organic, not mechanical. Like a garden, code needs constant maintenance. For a garden to look nice all year round, you need to look after its soil, constantly remove weeds, regularly water it, remove some dead plants, replant new ones, trim or re-arrange existing ones so they can stay healthy and look nice as whole. With basic regular maintenance, the garden will always look great but if you &lt;/span&gt;neglect it, even if for a short period, the effort to make it nice again will be much bigger. The longer you neglect it, the harder it will be to make it look nice again and you may even loose some or all of your plants.&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;Code is no different. If code quality is not constantly looked after, the code starts to deteriorate. Bad design choices, lack of tests and poor use of languages and tools will make parts of the code to rot. Bit by bit other parts of the code will also be contaminated up to the point that the whole code base is so ill that it becomes extremely painful to change it or add new features to it.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;b&gt;The Invisible Threat&lt;/b&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;When starting a greenfield project, everything is great. With a non-existent code base, developers can quickly start creating new features without the fear of breaking or changing any existing code. Testers are happy because everything they need to test is new, meaning that they don't need to worry about regression tests. Managers can see a quickly progress in terms of new features added and delivered. What a fantastic first month the team is having.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;However, this is not a team of &lt;a href="http://craftedsw.blogspot.com/2010/09/beyond-manifesto-software-craftsmanship.html"&gt;craftsmen&lt;/a&gt;. This is a team of average developers structured and treated like unskilled production line workers.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;As time goes by, things are getting messier, bugs start to appear (some with no apparent explanation) and features start taking longer and longer to be developed and tested. Very slowly, the time to deliver anything starts to stretch out. But this is a slow process. Slow enough that takes months, sometimes, over a year or two to be noticed by the management. &lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ONTWYUiOUvw/TJ_onxsne5I/AAAAAAAAAKQ/yxxarqwpMbE/s1600/Quality_vs_Time.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="152" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/TJ_onxsne5I/AAAAAAAAAKQ/yxxarqwpMbE/s320/Quality_vs_Time.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;span class="value"&gt;It's very common to see projects where, at the beginning of a project, a feature of size X takes N number of days to be implemented. Over the time, as more bad code is added to the application, the same feature X (or a feature of the same size) takes much longer to be implemented than it used to take at the beginning of the project. As the quality of the code decreases, the amount of time to implement a new feature, fix a bug or make a change increases. The lower the quality, the higher the number of bugs, the harder is to test and less robust and reliable the application becomes.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="value"&gt;Some people say that they just don't have time to do it properly but, in general, a lot more time and money is spent later on on tests and bug fixing. &amp;nbsp; &lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;b&gt;Hostage of your own software&lt;/b&gt;&lt;/span&gt;&lt;span class="value"&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;When the code base gets into the situation where changes or additional features take too long to be implemented or worse, developers and managers are scared to touch existing code, an action must be taken immediately. This is a very dangerous situation to be since business progress is being impeded or delayed by the software instead of being helped by it. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="value"&gt;To keep business progress, schedule and budget under control, high quality code needs to be maintained at all costs.&lt;/span&gt;&lt;b&gt;&lt;span class="value"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;&lt;span class="value"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;Organisations may need to cancel the implementation of some features or postpone changes just because of the amount of time and money that they may cost to be built. Having poor quality of code responsible for it is totally unacceptable.&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;The biggest problem here is that bad code is invisible to everyone besides developers. Other members of the team will just realise that something is wrong when it is too late. This means that it is the developers responsibility to look after the quality of the code. Some times, developers expose the problem to project managers but the request for having some time to "&lt;i&gt;re-factor&lt;/i&gt;" the code is often ignored for various reasons, including a lack of understand of the impacts of bad code and the inability of developers to explain it. On the other hand, when developers come to a point where they need to ask for some formal time to do refactoring, this means that for one reason or another, they neglected the code at some point in the past.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;b&gt;Hire craftsmen not average developers&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;With the amount of literature, tools, technologies, methodologies and the infinite source of information available on the web, it is just unacceptable to have a team of developers that let the code to rot.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;a href="http://craftedsw.blogspot.com/2010/09/beyond-manifesto-software-craftsmanship.html"&gt;Craftsmen&lt;/a&gt; are gardeners and are constantly looking after the code base, quickly refactoring it without fear since they are strongly backed by a good battery of tests that can test the entire application in just a few minutes. Time constraints or change in requirements will never be used as excuses for bad code or lack of tests due to the good design principles and techniques constantly used throughout the application.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;Having an empowered team of craftsmen can be the difference between success and failure of any software project.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="value"&gt;&lt;b&gt;Quality of code may not guarantee the success of a project but it can definitely be the main invisible cause of its failure.&amp;nbsp; &lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-780338124898600545?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/780338124898600545/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/09/bad-code-invisible-threat.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/780338124898600545'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/780338124898600545'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/09/bad-code-invisible-threat.html' title='Bad Code: The Invisible Threat'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_ONTWYUiOUvw/TJ_onxsne5I/AAAAAAAAAKQ/yxxarqwpMbE/s72-c/Quality_vs_Time.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-8346000483478607958</id><published>2010-09-14T23:19:00.000+01:00</published><updated>2010-09-14T23:20:10.972+01:00</updated><title type='text'>Beyond the manifesto: The Software Craftsmanship Attitude</title><content type='html'>&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;Being an aspiring software craftsman goes way beyond than just saying it. I'll quote my own definition of software craftsmanship from my &lt;a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html"&gt;previous post&lt;/a&gt;. &lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;blockquote&gt;Software craftsmanship is a long journey to mastery. It's a lifestyle  where developers choose to be responsible for their own careers and for  improving their craft, constantly learning new tools and techniques. &lt;span class="status-body"&gt;&lt;span class="entry-content"&gt;Software  Craftsmanship is all about putting responsibility, professionalism,  pragmatism and pride back into software development&lt;/span&gt;&lt;/span&gt;. &lt;/blockquote&gt;Software craftsmanship is all about attitude. The attitude of &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;raising the bar of professional software development&lt;/a&gt; starting with our own skills and professionalism. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The responsibility shift&lt;/b&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;Not long ago, I was speaking to a developer and he was complaining about his company, saying that they didn't have a good career plan, that he did not have any training, that he was not given the opportunity to learn new technologies and, of course, that he was not paid enough. Apparently, from his perspective, his employer was responsible for his career.&lt;br /&gt;&lt;br /&gt;Imagine that we need a doctor. Would we pay a doctor to learn while he cut us open or give us a diagnosis? Would we pay an engineer to learn while he draws the plan for our new house? Would we go to a concert and pay the musician to learn how to play the guitar during the show? What about a chef in a restaurant?&lt;br /&gt;&lt;br /&gt;So why is the employer's obligation to pay us training courses and pay us to learn new technologies and tools while we are working on a project? Should the employers be responsible for what we learn and what we don't learn.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Software development&lt;/b&gt;&lt;b&gt; is not a 9 to 5 profession&lt;/b&gt;. To be a &lt;i&gt;professional&lt;/i&gt; software developer, we need to take our own time and money to keep learning and improving. As professionals, we should be paid for what we know, our ability to learn fast and for the quality of the work we do. We own our careers and are responsible for them. Working for a customer/employer that helps us with our career in terms of training, books, conferences, seminars, etc, is great but should be considered a bonus.&lt;br /&gt;&lt;br /&gt;&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;... but how can we learn and keep ourselves up-to-date?&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Different developers have different preferences but here is a list of ways I find useful.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Literature&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Books, many books&lt;/b&gt;. Having your own library is essential. Books give you a good overview of a specific technology or subject quickly. No, it does not mean you will be proficient and next day you will be a specialist. What a book will give you is an understanding of what a technology or subject is about. It will be up to you then to decide if you want to practice what you've learned and become proficient. If you don't have the habit, try reading 3 to 4 technical books per year. Once you get the habit, try one per month. The most common excuse is that you don't have time. The cool thing about books is that you can read them during periods of&amp;nbsp; "dead" time, like on the tube, bus, in your dentist's waiting room, on the bed before going to sleep, toilet, etc. &amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Blogs&lt;/b&gt; are now one of my favourite types of reading. They tend to fit more the software craftsmanship model since they are much more personal and in general, related to personal findings, opinions, successes and failures. Reading blogs from more experienced professionals and subject matter experts is a good, quick and free way for apprentices and journeymen to learn from multiple master craftsmen at the same time. But don't think that just experienced professionals should write blogs. Every software developer should write his or her own blogs, sharing their experiences and findings, helping to create a great &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;community of professionals&lt;/a&gt;. &amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Technical websites&lt;/b&gt; are also good in order to keep yourself up-to-date with what's going in the market. New technologies, techniques, etc.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Practice, practice, practice&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pet project(s)&lt;/b&gt; is for me, by far, the best way to learn and study. A pet project is a &lt;i&gt;real&lt;/i&gt; project but without the boring bits. There are no deadlines, does not need to make money, you control the requirements and most importantly, you use the technologies and methodologies you want, whenever you want, wherever you want. You are the boss. Pet projects give something for you to focus and help you to understand why and how you can use certain technologies. It gives you the experience you need to apply what you've learned into real projects. Pet projects are meant to be fun.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Contributing to &lt;b&gt;open source&lt;/b&gt; projects can also be a great thing. There are thousands of them out there. Find a project that is related to what you want to learn or know more about and download the source code. Start running and reading the tests, if any. Inspect and debug the code. If you want to contribute, start small. Add some documentation and write some tests. Then, check the list of features to be implemented and pick a simple one and give it a go. You can also propose and implement a new and small one to start with. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pair-programming&lt;/b&gt; can be a great experience. Many developers are afraid to try or think they will feel uncomfortable. That's what I thought as well before I tried. Today I really enjoy it. Pair-programming gives you an opportunity to discuss your ideas, to learn new tricks and techniques from your pair and the resulting code is much better. Pairing with someone from your team is good but pairing with someone that you barely know can be a very interesting experience. &lt;br /&gt;&lt;br /&gt;If learning a new language or new technique like TDD / BDD or trying different approaches to OOP or functional programming, try a &lt;b&gt;code kata&lt;/b&gt;. Code kata is a small exercise that in general can be solved in a few minutes or in a few hours. Code katas were created to help developers to focus in a problem while improving their skills. You can find a good source of code katas at &lt;a href="http://codingkata.org/"&gt;codingkata.org&lt;/a&gt; and &lt;a href="http://codekata.pragprog.com/"&gt;codekata.pragprog.com&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Community and Events&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Be part of your local community. &lt;/b&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;Software craftsmanship is all about a &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;community of professionals&lt;/a&gt;, learning and sharing with each other and elevating the level of professionalism and maturity of our industry. Join your nearest user groups and participate in their events. User groups are the best way for making contacts, sharing ideas and learning things. Many user groups promote free talks, coding activities and social events. A great aspect of being part of a community if the feeling that you are not alone. There are many people out there having the same problems you've got and many others that will happily share their solution to it.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Raising the bar&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The main changes proposed by the &lt;a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html"&gt;software craftsmanship movement&lt;/a&gt; are related to the developers attitude. In summary, it's about being proud about your work, the code you produce and the software you create. It's about constantly trying to improve your skills and learn new ones.&lt;br /&gt;&lt;br /&gt;An aspiring software craftsman is intolerant of bad code will constantly apply the &lt;a href="http://programmer.97things.oreilly.com/wiki/index.php/The_Boy_Scout_Rule"&gt;Boy Scout Rule&lt;/a&gt;.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span class="status-body"&gt;&lt;span class="entry-content"&gt;If you find that the  good code you wrote one year ago is still good enough today, it means you  didn't learn anything during this period and this is unacceptable.&lt;/span&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;b&gt;Productive partnerships &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The attitude of a software craftsman goes beyond good code. The relationship between a software craftsman and his or her customer (or employer) is of a &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;productive partnership&lt;/a&gt; and not employer / employee. As a productive partnership, it's our role to constantly question the requirements and propose improvements and new features. It's our job to warn our customers about the problems we see. Due to the knowledge of the code and technology, developers are well positioned to help their customers improve their business.&lt;br /&gt;&lt;br /&gt;However, sometimes some customers or employers don't want or don't see the advantages of this partnership and will treat developers as production line workers that should just do what they are told. Coding monkeys. In cases like that, any aspiring software craftsman should move on and find another job. Staying in a place where your skills are not appreciated is a career suicide. &amp;nbsp; &lt;br /&gt;&lt;br /&gt;Raising the bar of our industry is on our own interest. The better we become in writing code and delivering valuable software, the better our lives will be, professionally and financially.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;PS: If&amp;nbsp; you are in London or nearby, join the &lt;a href="http://www.londonswcraft.com/"&gt;London Software Craftsmanship Community&lt;/a&gt;. &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-8346000483478607958?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/8346000483478607958/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/09/beyond-manifesto-software-craftsmanship.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/8346000483478607958'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/8346000483478607958'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/09/beyond-manifesto-software-craftsmanship.html' title='Beyond the manifesto: The Software Craftsmanship Attitude'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-6843022714284326854</id><published>2010-09-03T17:40:00.000+01:00</published><updated>2010-09-14T01:21:18.344+01:00</updated><title type='text'>Software Craftsmanship</title><content type='html'>&lt;b&gt;&lt;span style="font-size: large;"&gt;So what is software craftsmanship?&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A better metaphor&lt;/b&gt;: In a very simplistic way, we can say that software craftsmanship is a better metaphor for software development than software engineering, as I wrote in a &lt;a href="http://craftedsw.blogspot.com/2010/08/software-engineering-process-vs-people.html"&gt;previous post&lt;/a&gt;. Software craftsmanship sees software as a craft and compares software developers to the medieval blacksmiths. Apprentices would work with more experienced blacksmiths, travelling from place to place, working with and for different masters, learning different tools and techniques, improving their craft until the point they were good enough to become master themselves. (There is more to it, but let's keep it simple for now).&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Wikipedia Definition&lt;/b&gt;:&amp;nbsp; is an approach to software development that emphasizes the coding skills  of the software developers themselves. It is a response by software  developers to the perceived ills of the mainstream software industry,  including the prioritization of financial concerns over developer  accountability. (&lt;a href="http://en.wikipedia.org/wiki/Software_craftsmanship"&gt;read in full&lt;/a&gt;)&lt;br /&gt;&lt;br /&gt;I personally don't like too much the Wikipedia's definition. It's very dry and I don't think it captures the essence of what being a software craftsman means to a software developer.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;A more personal definition&lt;/b&gt;: Software craftsmanship is a long journey to mastery. It's a lifestyle where developers choose to be responsible for their own careers and for improving their craft, constantly learning new tools and techniques. &lt;span class="status-body"&gt;&lt;span class="entry-content"&gt;Software  Craftsmanship is all about putting responsibility, professionalism,  pragmatism and pride back into software development&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A software craftsman cares and is proud of his or her work and is extremely professional and pragmatic when it comes to its implementation. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ONTWYUiOUvw/TH70f-RTkbI/AAAAAAAAAJ0/JM-0EmWb2go/s1600/violinmaker.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_ONTWYUiOUvw/TH70f-RTkbI/AAAAAAAAAJ0/JM-0EmWb2go/s320/violinmaker.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The Software Craftsmanship Movement &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The software craftsmanship movement is basically an evolution of ideas that started probably in the late 90ies, early 2000 with the publication of &lt;a href="http://en.wikipedia.org/wiki/The_Pragmatic_Programmer"&gt;The Pragmatic Programmer&lt;/a&gt; by Andy Hunt and Dave Thomas (1999) and &lt;a href="http://www.amazon.co.uk/Software-Craftsmanship-Imperative-Pete-McBreen/dp/0201733862/ref=sr_1_1?s=books&amp;amp;ie=UTF8&amp;amp;qid=1283437984&amp;amp;sr=1-1"&gt;Software Craftsmanship: The New Imperative&lt;/a&gt; by Pete McBreen (2001). In 2008, &lt;a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin"&gt;Uncle Bob&lt;/a&gt; proposed "Craftsmanship over Execution" (originally Craftsmanship over Crap) as the fifth value for the &lt;a href="http://agilemanifesto.org/"&gt;Agile Manifesto&lt;/a&gt;. In 2009, the &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;Manifesto for Software Craftsmanship&lt;/a&gt; was created, defining the values of the movement and international Software Craftsmanship conferences emerged in the US and UK. &lt;br /&gt;&lt;br /&gt;In the &lt;a href="http://manifesto.softwarecraftsmanship.org/"&gt;manifesto&lt;/a&gt;, the essence of the software craftsmanship is capture in its subtitle: &lt;b&gt;Raising the bar&lt;/b&gt;. The manifesto was idealised by very experienced developers that had enough of project failures mainly caused by poor management, ill processes and, of course, badly-written code.&lt;br /&gt;&lt;br /&gt;Developers are taking the matter into their own hands and are trying to  change how the industry sees software development not just proposing new and revolutionary processes but showing customers that they care about  what they do and that they want to work together with their customers in order to  produce great and long-lived software.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;The values of the Software Craftsmanship Movement&lt;/b&gt;&lt;/span&gt; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div class="right"&gt;&lt;i&gt;Not only working software, but also &lt;b&gt;&lt;span class="value"&gt;well-crafted software&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="right"&gt;&lt;span class="value"&gt;Working code is not good enough. Think on a 5 year old application (it could be 2 or 10) where we are scared to change some of its parts (fix bugs, add new features, etc.) because we don't understand how it works and have no confidence that we will not break anything else. This application is &lt;i&gt;working software&lt;/i&gt; but is it good enough? Well crafted software means that regardless how old the application is, developers can understand it easily, side effects are well known and controlled, high test coverage, clear design, business language well expressed in the code and adding or changing features does not take longer that it used to take at the beginning of the project, when the code base was small. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;The &lt;b&gt;code must be maintainable&lt;/b&gt; &lt;b&gt;and predictable&lt;/b&gt;. Developers must know what is going to happen when changing the code and must not fear to change it. Changes should be localised and not cause impact in other parts of the application. Tests will guarantee that nothing else was broken.&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;div class="right"&gt;&lt;i&gt;Not only responding to change, but also &lt;b&gt;&lt;span class="value"&gt;steadily adding value&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="right"&gt;&lt;span class="value"&gt;This is not just about adding new features and fixing bugs. This is also about constantly improving the structure and cleanliness of the code. The software must be seen as an asset and the constant maintenance of it will make it more valuable during its lifetime, instead of letting it rot and devalue.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;The Boy Scout Rule (defined by &lt;a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin"&gt;Uncle Bob&lt;/a&gt;) states that we should &lt;b&gt;always let the code a bit cleaner than we found it&lt;/b&gt;. This is a paraphrase of Boy Scouts rule&lt;/span&gt;: &lt;i&gt;leave the camp cleaner than you found it&lt;/i&gt;.&lt;span class="value"&gt;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;If customers want to keep benefiting from adding and  changing features quickly, they will need high quality code to enable  them to do it. &amp;nbsp;&lt;/span&gt;&lt;span class="value"&gt; &lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div class="right"&gt;&lt;i&gt;Not only individuals and interactions, but also &lt;span class="value"&gt;a &lt;b&gt;community of professionals&lt;/b&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;&lt;div class="right"&gt;&lt;span class="value"&gt;This is somehow related to the idea of apprentices, journeymen and masters, where software craftsmanship masters will mentor apprentices and help them in their journey. The software craftsmanship community is responsible for training the next generation of professionals. Knowledge and ideas must be shared and discussed within the community in order to keep moving the software development industry forward.&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="value"&gt;&lt;/span&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div class="right"&gt;&lt;i&gt;Not only customer collaboration, but also &lt;b&gt;&lt;span class="value"&gt;productive partnerships&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;&lt;/div&gt;&lt;/blockquote&gt;Software craftsmen need successful projects to build their reputation and are proud of their achievements. Successfully delivering high quality software is essential for any software craftsman journey. With this in mind, software craftsmen will do whatever they can for a project to succeed. They don't act like simple employees that just do what they are told to do. They want to actively contribute to the success of the project, questioning requirements, understanding the business, proposing improvements and productively partnering with their customers or employers. This is an interesting shift of perspective, if you like, and the advantages for the customer and for the project success are enormous. A well-motivated team has a much bigger chance to make any project succeed. However, if the customer is not prepared to have this partnership and sees software development as an industrial process and the least important part of the project, this customer will never have real software craftsmen working for him for too long. Not getting involved with the business, not questioning requirements, not proposing improvements and not knowing the customers needs is not a partnership. Real software craftsmen make the customer needs, their needs. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;span style="font-size: large;"&gt;Conclusion&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Recently, &lt;a href="http://en.wikipedia.org/wiki/Robert_Cecil_Martin"&gt;Uncle Bob Martin&lt;/a&gt; said during an &lt;a href="http://www.azullo.com/blog/think-agile/interview-with-robert-c-martin-co-author-of-the-agile-manifesto/"&gt;interview&lt;/a&gt;:&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;blockquote&gt;The original torch of the Agile message has changed hands, and is now  being carried by the Software Craftsmanship movement.  These are the  folks who continue to pursue the technical excellence and professionalism that drove the original founders of the Agile  movement. &lt;/blockquote&gt;&lt;/div&gt;&lt;br /&gt;The Software Craftsmanship Movement is another step forward towards better and healthier software projects. Instead of just focusing on processes, it focuses on the quality of the software that is produced and most importantly on the attitude and competence of the people involved. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Software Craftsmanship brings pride and professionalism into software development.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-6843022714284326854?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/6843022714284326854/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/6843022714284326854'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/6843022714284326854'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html' title='Software Craftsmanship'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_ONTWYUiOUvw/TH70f-RTkbI/AAAAAAAAAJ0/JM-0EmWb2go/s72-c/violinmaker.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-8882835982301412199</id><published>2010-08-22T23:35:00.000+01:00</published><updated>2010-08-24T13:36:26.281+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='&quot;sofware craftsmanship&quot; craftsmanship &quot;software engineering&quot;'/><title type='text'>Software Engineering: The problem with the production line</title><content type='html'>Is software engineering the best approach for developing software? Does it apply for the majority of the software projects or just a very few of them?&lt;br /&gt;&lt;br /&gt;Software Engineering was an answer for the perceived "&lt;a href="http://en.wikipedia.org/wiki/Software_crisis"&gt;software crisis&lt;/a&gt;", back in 1968, in the First NATO Software Engineering Conference and it was created to solve the problems of extremely large NATO and U.S. Department of Defence projects. In the majority of these projects, the hardware was still being designed and with no hardware to test, there was plenty of time to investigate requirements and write the software specifications. Hardware controlled by the software was generally worth billions of dollars like in the case of &lt;a href="http://www.fastcompany.com/magazine/06/writestuff.html%20"&gt;space shuttle&lt;/a&gt; and the &lt;a href="http://en.wikipedia.org/wiki/Safeguard_Program"&gt;Safeguard Ballistic Missile Defence System&lt;/a&gt;. People's lives and national security were also at stake. &lt;br /&gt;&lt;br /&gt;The &lt;a href="http://en.wikipedia.org/wiki/IEEE_Computer_Society" title="IEEE Computer Society"&gt;IEEE Computer Society&lt;/a&gt;'s &lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Software_Engineering_Body_of_Knowledge" title="Software Engineering Body of Knowledge"&gt;Software Engineering Body of Knowledge&lt;/a&gt;&lt;/i&gt;  defines "software engineering" as:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Software engineering is the application of a systematic,  disciplined, quantifiable approach to the development, operation, and  maintenance of software, and the study of these approaches; that is, the application of engineering to software.&lt;/i&gt;&lt;/blockquote&gt;Software Engineering can be very effective when developing safety critical systems like the one for the space shuttle as described on "&lt;a href="http://www.fastcompany.com/magazine/06/writestuff.html"&gt;They Write The Right Stuff&lt;/a&gt;" - Fast Company article, from 1996: &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;The last three versions of the program - each 420,000 lines long - had just one error each. The last 11 versions of this software had a total of 17 errors. Commercial programs of equivalent complexity would have 5,000 errors.&lt;/i&gt;&lt;/blockquote&gt;Of course that this looks really impressive but there is more to it:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Money is not the critical constraint: The group's $35 million per year budget is a trivial slice of the NASA pie, but on a dollars-per-line basis, it makes the group among the nation's most expensive software organizations.&lt;/i&gt;&lt;/blockquote&gt;Another extract from this same article when they were discussing the process:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;And the culture is equally intolerant of creativity, the individual  coding flourishes and styles that are the signature of the all-night  software world. "People ask, doesn't this process stifle creativity? You  have to do exactly what the manual says, and you've got someone looking  over your shoulder," says Ted Keller (senior technical manager). "The answer is, yes, the process does  stifle creativity."&lt;/i&gt;&lt;/blockquote&gt;Many of the NATO and US Department of Defence took years, some over a decade to complete. Many had hundreds of people involved and almost half of the time was spend in requirements and design specifications, with uncountable reviews and approval cycles. Of course that, due to their reliability and quality, many are still in use today. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Software Engineering for the Masses&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;More and more hardware became cheap and business of all sizes needed software in order to survive and be competitive. The difference was that a the big majority of these businesses couldn't afford to pay $35 million dollars per year and neither wait for too many years to start benefiting from their software. Also, many of those software projects were not manipulating expensive hardware or dealing with &lt;span class="sense_b "&gt;&lt;span class="def parentof__def__is__sense_b"&gt;life-threatening situations.&lt;/span&gt;&lt;/span&gt; &lt;a href="http://yourdon.com/about/"&gt;Edward Yourdon&lt;/a&gt;, in his book Rise and Resurrection of the American Programmer, wrote:&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;I'm going to deliver a system to you in six months that will have 5,000 bugs in it - and you're going to be very happy!&lt;/i&gt; &lt;/blockquote&gt;It was clear that software engineering processes had to be adapted in order to satisfy a more impatient and lower budget legion of businesses.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The "Good Enough Software&lt;/b&gt;" &lt;b&gt;Era&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Over the decades, many new software engineering processes and methodologies were created in order to make software development faster and cheaper. The most adopted were the ones based on &lt;a href="http://en.wikipedia.org/wiki/Iterative_and_incremental_development"&gt;iterative and incremental development&lt;/a&gt; that evolved into the &lt;a href="http://en.wikipedia.org/wiki/Agile_software_development"&gt;agile software development&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Agile software development and "good enough software" were an amazing improvement in bringing costs down, mitigating risks with quicker feedbacks and much faster time to market. &lt;br /&gt;&lt;br /&gt;Regardless the methodology or process used, software projects are still failing. Some fail because they were over-budget, others because they were not delivered on time, others failed to satisfy the requirements and business goals, et al. &lt;br /&gt;&lt;br /&gt;The main problem is that for decades, software development was seen as a production line. That's the software engineering perspective of software development. Processes and methodologies are generally much more focused in making this production line more productive, creating different management and organisational styles than actually trying to make the employees more capable. Developers are treated as mere brain-damaged programmers and are at the bottom of the food chain.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Good enough is not always good enough&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Using agile, lean or any methodology is not enough. It is all about the people involved in the project and their willingness to succeed and be proud of what they produce. If developers are seen as the least important and cheapest members of a software project, the maximum that this team is going to produce is mediocre software, regardless of methodology.&lt;br /&gt;&lt;br /&gt;A software project would have much better chances to succeed with "good people with a bad process" than "mediocre people with a good process". Good people would always find a way to improve the process, be productive and produce something that they are proud of. Mediocre people accepts whatever is established, even when it is not good enough, and will produce just what they were asked for.&lt;br /&gt;&lt;br /&gt;In a software project, if a company wants a good software, they will need &lt;b&gt;good&lt;/b&gt; and &lt;b&gt;empowered &lt;/b&gt;software developers. Instead of 10 mediocre people with a good process, it would be better to have 3 or 4 good people and empower them to deliver the project.&lt;br /&gt;&lt;br /&gt;A process, imposed by managers and people that have no clue how to write software, will just guarantee that mediocre software is predictably delivered (if lucky). On the other hand, a team of self-organised and great developers would have a better shot at creating a more efficient way to produce great software, constantly trying to improve they way they work.&lt;br /&gt;&lt;br /&gt;A process should never be more important than the people. Managers should facilitate the work of great software developers and not tell them what to do. It should always be harder to replace a good software developers than a manager since they are the ones that know the system inside-out. Managing a few well motivated, well paid and good professionals is always easier than manage many mediocre people.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Software development is a creative and highly skilled profession that takes years to master. While software development is treated like a production line, projects will continue to fail. &lt;br /&gt;&lt;br /&gt;&lt;div style="background-color: white; color: #444444;"&gt;&lt;b&gt;Source&lt;/b&gt;&lt;/div&gt;&lt;span style="font-size: small;"&gt;Software Craftsmanship: The New Imperative - ISBN 0-201-73386-2, 2002 &lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Software_engineering"&gt;http://en.wikipedia.org/wiki/Software_engineering&lt;/a&gt;&lt;/span&gt; &lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;a href="http://en.wikipedia.org/wiki/Software_crisis"&gt;http://en.wikipedia.org/wiki/Software_crisis&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;IEEE Standard Computer Dictionary, ISBN 1-55937-079-3, IEEE 1990&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;"They Write The Right Stuff", Fast Company, &lt;a href="http://www.fastcompany.com/magazine/06/writestuff.html"&gt;http://www.fastcompany.com/magazine/06/writestuff.html&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Safeguard Program: &lt;a href="http://en.wikipedia.org/wiki/Safeguard_Program"&gt;http://en.wikipedia.org/wiki/Safeguard_Program&lt;/a&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Stephenson, W. E. "&lt;b style="font-weight: normal;"&gt;An analysis of the resources used in the SAFEGUARD system software development"&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b style="font-weight: normal;"&gt;Edward Yourdon&amp;nbsp; - &lt;a href="http://yourdon.com/about/"&gt;http://yourdon.com/about/&amp;nbsp;&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b style="font-weight: normal;"&gt;http://en.wikipedia.org/wiki/Iterative_and_incremental_development&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b style="font-weight: normal;"&gt;http://en.wikipedia.org/wiki/Agile_software_development&lt;/b&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-8882835982301412199?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/8882835982301412199/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/08/software-engineering-process-vs-people.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/8882835982301412199'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/8882835982301412199'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/08/software-engineering-process-vs-people.html' title='Software Engineering: The problem with the production line'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-8342500768802005514</id><published>2010-08-07T01:29:00.000+01:00</published><updated>2010-08-24T13:40:37.756+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='&quot;sofware craftsmanship&quot; craftsmanship &quot;software engineering&quot;'/><title type='text'>Which type of barista are you?</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: left;"&gt;A colleague from New Zealand once was telling me about a type of coffee that was originated there. It's called &lt;a href="http://en.wikipedia.org/wiki/Flat_white"&gt;Flat White Coffee&lt;/a&gt;. We were discussing about the difference between this coffee and all the other types of coffee with milk. Eventually we started talking about the quality of the drink and what makes it be better or worse. He mentioned that, of course, the quality of the beans and milk are very important for a good coffee but what makes a good coffee an excellent coffee is the &lt;a href="http://en.wikipedia.org/wiki/Barista"&gt;barista's&lt;/a&gt; ability. &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;What makes a coffee to be a rubbish coffee then? If the coffee grains are rubbish, you will have a rubbish coffee. However, for a flat white coffee, coffee is just one variable in the equation. There are other variables like how the grains are roasted, steaming the milk at the right temperature, not adding sugar, how the milk is poured, the microfoam on top of the drink, etc. See the &lt;a href="http://en.wikipedia.org/wiki/Flat_white"&gt;distinction from cafe con leche for details&lt;/a&gt;. Anyway, the point is, a rubbish (or careless) barista, with rubbish coffee will produce a rubbish coffee drink. &lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/TFtLv2MxYMI/AAAAAAAAAJM/G6R-sxn22UA/s320/RubbishFlatWhite.jpg" style="margin-left: auto; margin-right: auto;" /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Rubbish Coffee&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Clearly a business that serves a rubbish coffee will not survive if their main business is to sell coffee drinks. Also, this business will never attract customers that really appreciate a good coffee. &lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ONTWYUiOUvw/TFtL0ybcCgI/AAAAAAAAAJU/bERxdV2Mv-c/s1600/AverageFlatWhite.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;/a&gt;&lt;/div&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/_ONTWYUiOUvw/TFtL0ybcCgI/AAAAAAAAAJU/bERxdV2Mv-c/s320/AverageFlatWhite.jpg" style="margin-left: auto; margin-right: auto;" /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Average Coffee&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Producing an average coffee is easy. You buy average coffee grains, hire an average barista and, hey presto, you have an average coffee drink. There is nothing wrong with an average coffee drink if you are &lt;b&gt;not&lt;/b&gt; in the coffee business. However, if you are in a coffee business, your business will be just another one. No one will remember you and chances are that you will have occasional customers, but not regulars.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/TFtL2vamkjI/AAAAAAAAAJc/K002UKBvm04/s320/GoodFlatWhite.jpg" style="margin-left: auto; margin-right: auto;" /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr align="center"&gt;&lt;td class="tr-caption"&gt;Good Coffee&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;Producing a good coffee is not that simple. However, it does not need to be expensive. You don't need to buy the best quality ingredients to be able to make a good coffee. Best quality ingredients are expensive and inevitably will make your coffee drinks more expensive as well. You can mitigate this situation hiring a good barista, or maybe someone that has the potential and willingness to become a good one. Clearly, the barista that prepared the coffee above is trying his best to make a good coffee. It's still not perfect (purely looking at the pattern on top of the drink) but it is definitely a much better coffee than the normal and average one that you get everywhere. It is clear that the barista cares about it and eventually he will be able to produce a very good coffee.If you are in the coffee business, producing anything less than a good coffee is just &lt;b&gt;unacceptable&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;&lt;table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style="text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_ONTWYUiOUvw/TFtL4QfosNI/AAAAAAAAAJk/mCdTpa0Ue-Q/s1600/ExcellentFlatWhite.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_ONTWYUiOUvw/TFtL4QfosNI/AAAAAAAAAJk/mCdTpa0Ue-Q/s320/ExcellentFlatWhite.jpg" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class="tr-caption" style="text-align: center;"&gt;Great Coffee&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;And then you have the great coffee, that is made with great coffee beans, carefully roasted, prepared in a very good coffee machine and by a great barista. Great baristas are proud of their ability to prepare a great coffee and they would not work for too long for a business where coffee making is not treated with the deserved respect.&lt;br /&gt;&lt;br /&gt;Now imagine that you are the barista. But instead of coffee, you produce code. Imagine that the the coffee grains, milk and coffee machine are the  tools you use to produce your code like the computer language, the IDE,  the database, etc. Instead of serving coffee for your customers, you are producing software that will be used by your team mates, project sponsors, the company they (or you) work for, external clients, etc.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Like in the flat white coffee example above, of course that the tools we use are very important when producing a good software. However, more importantly, it is the quality of the software engineers that counts. A good barista can make a good coffee even when using average coffee grains, due to his or her ability to combine ingredients and prepare the drink. A bad barista can ruin the coffee even if he or she is using the best quality coffee beans. The biggest difference between the two baristas is how much they care about each cup of flat white coffee they prepare. Their pride and willingness to achieve the best pattern on top of each drink. The great feeling of achievement when they produce a great one. The happiness to see returning customers, queuing and waiting their turn to order the coffee that he, skilfully, prepares.&lt;br /&gt;&lt;br /&gt;So, which type of barista are you?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-8342500768802005514?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/8342500768802005514/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/08/which-type-of-barista-are-you.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/8342500768802005514'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/8342500768802005514'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/08/which-type-of-barista-are-you.html' title='Which type of barista are you?'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_ONTWYUiOUvw/TFtLv2MxYMI/AAAAAAAAAJM/G6R-sxn22UA/s72-c/RubbishFlatWhite.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-2937834842513651382</id><published>2010-06-23T12:52:00.000+01:00</published><updated>2010-08-24T13:41:07.785+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='OOP DDD Software Craftsmanship'/><title type='text'>One team, one language</title><content type='html'>On a &lt;a href="http://craftedsw.blogspot.com/2010/06/wolf-in-sheeps-clothing.html"&gt;previous post&lt;/a&gt; I was discussing, among other things, how code often doesn't represent the business properly. The code "satisfies" the business requirements but doesn't express them very well. The main reason for that is because we, developers, like to abstract business terms and rules into technical implementations and patterns.&lt;br /&gt;&lt;br /&gt;Very often, we discuss the user stories (requirement documents, use cases, whatever the methodology used is) with the "domain experts" and as soon as we understand what needs to be done, we map the requirements to a &lt;a href="http://craftedsw.blogspot.com/2010/06/wolf-in-sheeps-clothing.html"&gt;technical design&lt;/a&gt; (actions, services, entities, helpers, DAOs, etc) that is &lt;a href="http://craftedsw.blogspot.com/2010/06/wolf-in-sheeps-clothing.html"&gt;completely meaningless&lt;/a&gt; to the domain experts. Sometimes, even among developers themselves, different names and expressions are used to refer to the same thing. The main reason is that different developers talk to different domain experts and come up with different abstractions. As a result,&amp;nbsp; the usage of different terms to describe requirements leads to confusion, duplication of code and unpredictable behaviour in the system.&lt;br /&gt;&lt;br /&gt;The first step towards an expressive and domain-focused design is to have a common language among ALL members of the team. ALL means ALL: developers, domain experts (business analysts, users, product owner, etc), testers, project manager and anyone else involved in the project.&lt;br /&gt;&lt;br /&gt;Developers very often say that domain experts don't understand objects and database and because of that, they need to "translate" business requirements into software design. However, we developers don't understand the business as well as the domain experts do, what more often than not, leads to imperfect and confusing abstractions. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Ubiquitous Language&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;A language structured around the domain model and used by all team  members to connect all the activities of the team with the software.&lt;/i&gt;&lt;/blockquote&gt;&lt;a href="http://domaindrivendesign.org/node/132"&gt;The Ubiquitous Language&lt;/a&gt; is one of the most important things, if not the most, in &lt;a href="http://domaindrivendesign.org/"&gt;Domain-Driven Design&lt;/a&gt;. The main idea is that the whole team speaks a single language, that is the business language. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBgVFwNWmdI/AAAAAAAAAJA/2ADOaIfW-fc/s1600/ubiquitouslanguage.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="182" src="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBgVFwNWmdI/AAAAAAAAAJA/2ADOaIfW-fc/s400/ubiquitouslanguage.jpg" width="400" /&gt;&amp;nbsp;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Business terms related to the software to be implemented must enter the ubiquitous language and each of these terms must be understood clearly by all members. During requirements gathering sessions and planning meetings, these terms must be captured and made available to everybody. Technical terms from the development team and business terms not relevant for the piece of software being implemented MUST NOT enter the ubiquitous language.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Capturing the ubiquitous language&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;br /&gt;In order to capture the ubiquitous language, it is mandatory that you work on a iterative software development environment. Trying to capture the ubiquitous language up-front could straitjacket the whole process, inhibiting team members to make the necessary changes along the way. As the language is used to express the business requirements, it is natural that it evolves during the lifetime of the project, where new terms are added, deleted and also re-defined.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Methodologies like Extreme Programming (XP) says that the only documentation should be the code. Not even comments on the code are appreciated, since they can easily get out of sync with the code. The code should be the only documentation since it is the only one that represents exactly what the system does.&lt;br /&gt;&lt;br /&gt;On the other hands, we have UML (Unified Modeling Language), that in theory, should be a great candidate to document the ubiquitous language since the whole purpose of UML was to document requirements and express them in a language that is common to developers and business people.&lt;br /&gt;&lt;br /&gt;In summary, showing code during discussions with domain experts, testers and other members of the team during a design session is not exactly a fantastic idea. Also, using just UML, because of its bureaucracy, rules and details is also a bad idea. The whole UML notation could easily straitjacket the creative process during the exercise. &lt;br /&gt;&lt;br /&gt;There are many discussions about what would be the best way to capture the ubiquitous language. My preferred way is to draw diagrams (boxes and arrows mixed with some well understood UMLish notation) where each box represent a "&lt;b&gt;domain object&lt;/b&gt;" (aka domain concept). A domain object can be anything that is expressed by the business, like &lt;i&gt;client, organisation, product, route specification,&amp;nbsp; sales system&lt;/i&gt;, etc. They would all be boxes. Add to it a few arrows linking the boxes and with just a couple of words explaining how they related to each other. Sometimes a mixture of a class and sequence diagram (or an active diagram) can be very helpful, but don't get to picky about any notation. Preferably, draw on a white board, take a picture and store that on the wiki. For further sessions, just open the wiki and re-draw just the bit of the design that is important to the feature being discussed. Make the necessary adjusts on the white board, take another picture and stored it on the wiki again. There is much more to that, if you want to dive into &lt;a href="http://www.agilemodeling.com/%20%20"&gt;agile modeling&lt;/a&gt;, but I will leave it to another post. &lt;br /&gt;&lt;br /&gt;This goes way beyond transforming nouns and verbs into classes and methods. Taking the examples above, for example, &lt;i&gt;client, organisation&lt;/i&gt; and &lt;i&gt;products&lt;/i&gt; could be transformed in entities; &lt;i&gt;route specification&lt;/i&gt; could be a strategy class used by a &lt;i&gt;routing service&lt;/i&gt; (that would also need to be added to the diagram and to the ubiquitous language); &lt;i&gt;sales system&lt;/i&gt; would be an external system that we need to integrate to, etc. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Making the code more expressive&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The code should reflect all concepts exposed by the model. Classes and methods should be named according to the names defined by the domain. Associations, compositions, aggregations and sometimes even inheritances should be extracted from the model.&amp;nbsp; &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Sometimes, during implementation, we realise that some of the domain concepts discussed and added to the model don't actually fit well together and some changes are necessary. When it happens, developers should discuss the problems and/or limitations with the domain experts and refactor the domain model in order to favour a more precise implementation, without ever distorting the business significance of the design.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Ultimately, the code is the most important artefact of a software project and it needs to work efficiently. Regardless of what many experts in the subject say, code implementation will have some impact on the design. However, we need to be careful and very selective about which aspects of the code can influence design changes. As a rule, try as much as you can to never let technical frameworks limitations influence your design, but as we know, every rule has exceptions. &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;A common implementation problem that very often get in the way is mapping objects to databases using ORM tools. In this case, bending the model a little bit in favour of a more &lt;i&gt;realistic &lt;/i&gt;relation among entities is not a bad thing. Just make sure that changes like that are represented in the model and understood by everyone involved. &amp;nbsp; &amp;nbsp; &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;DOs and DON'Ts&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;Don't try to model everything.&lt;b&gt; &lt;/b&gt;Focus on the core of your application. We are not working on a waterfall or Unified Process project here. &lt;/li&gt;&lt;li&gt;Try to model just the key concepts of the domain problem;&lt;/li&gt;&lt;li&gt;Do not clutter your models with too much details. Keep it focused on the main responsibilities;&lt;/li&gt;&lt;li&gt;Limit your discussions and changes in the model to the business concepts (domain objects) related to the user story being discussed;&lt;/li&gt;&lt;li&gt;Don't add architectural concepts like DAOs, Actions, etc. We are not writing implementation diagrams.&amp;nbsp;&lt;/li&gt;&lt;li&gt;As your application grows, break the application into multiple models (domains), explicitly defining the context and boundaries within which a model applies. This is called &lt;a href="http://domaindrivendesign.org/node/91"&gt;Bounded Context&lt;/a&gt; in Domain-Driven Design.&lt;/li&gt;&lt;li&gt;Avoid thinking purely on the implementation when designing your model. Understanding and modeling the business is the most important thing here.&amp;nbsp; &lt;/li&gt;&lt;/ul&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;b&gt;Challenges of a Model-Driven Design&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/node/121"&gt;Model-Driven Design (MDD)&lt;/a&gt; is more an art than a science. It takes a lot of practice and willingness to get it going and get it right. Refactoring towards deeper insights must be seen as a positive and essential part of the project development. TDD and continuous integration are also essential for any agile and domain-driven application. &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;The goal of &lt;a href="http://domaindrivendesign.org/node/121"&gt;MDD&lt;/a&gt; is having the software expressing a &lt;a href="http://domaindrivendesign.org/node/101"&gt;deep&lt;/a&gt; and &lt;a href="http://domaindrivendesign.org/node/131"&gt;supple&lt;/a&gt; design.&lt;a href="http://www.blogger.com/goog_972650201"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/node/101"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Last buy not least, developers with good &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_design"&gt;Object-Oriented Design&lt;/a&gt; skills are needed in the project. The lack of design skills could easily transform ANY software project in a total failure in the long term.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/node/101"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Source&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/"&gt;http://domaindrivendesign.org/&lt;/a&gt; &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/node/91%7C"&gt;http://domaindrivendesign.org/node/91|&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/node/132"&gt;http://domaindrivendesign.org/node/132&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://domaindrivendesign.org/node/121"&gt;http://domaindrivendesign.org/node/121&lt;/a&gt; &lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;a href="http://www.agilemodeling.com/"&gt;http://www.agilemodeling.com/&lt;/a&gt; &lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-2937834842513651382?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/2937834842513651382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/06/one-team-one-language.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2937834842513651382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2937834842513651382'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/06/one-team-one-language.html' title='One team, one language'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ONTWYUiOUvw/TBgVFwNWmdI/AAAAAAAAAJA/2ADOaIfW-fc/s72-c/ubiquitouslanguage.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-4099309548608407319</id><published>2010-06-12T03:51:00.000+01:00</published><updated>2010-06-12T03:51:13.943+01:00</updated><title type='text'>The Wolf in Sheep's Clothing</title><content type='html'>In the last few years, I've noticed that the majority of the projects that I've  participated roughly  followed the same design. Speaking to colleagues and friends, the great majority said that they were also following the same design. It's what I call "&lt;b&gt;ASD&lt;/b&gt;"  design (Action-Service-DAO). &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ONTWYUiOUvw/TBIWQTGjE5I/AAAAAAAAAH4/Y98_C2MOjZU/s1600/ASD.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="35" src="http://1.bp.blogspot.com/_ONTWYUiOUvw/TBIWQTGjE5I/AAAAAAAAAH4/Y98_C2MOjZU/s400/ASD.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;by Action we mean a Struts Action, Spring Controller, JSF backing bean, etc. Any class that handles an action triggered by the user interface. &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;We can  argue that there is nothing really wrong about this approach since if we  map that to a &lt;a href="http://craftedsw.blogspot.com/2010/05/mvc-and-multi-tier-architecture.html"&gt;three-tier architecture&lt;/a&gt;, that is followed by the majority  of the applications, the ASD classes would be in the right places,  keeping a good isolation between the tiers.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ONTWYUiOUvw/TBIYlIGFyUI/AAAAAAAAAIA/eaKCuxwpbCk/s1600/ASD_3Tier.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="62" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/TBIYlIGFyUI/AAAAAAAAAIA/eaKCuxwpbCk/s400/ASD_3Tier.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;One of the problems of this approach is when services are created randomly, with different granularities, &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;low cohesion&lt;/a&gt; and with a weak representation of the business domains. Services end up being function libraries, almost like an utility class where all "functions" related to a specified "module" are grouped. When it comes to DAOs, the situation is not very different. DAOs are developed in a way that they become utility classes where sometimes we find a single DAO with all queries, inserts, delete, updates for an entire module or sometimes you find one DAO per entity. Either way, regardless what the query returns (or what it is its intention), or any rules related to updates or deletes, the methods will go to the same class. As the application grows, the code becomes something like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBIvqV_26pI/AAAAAAAAAIQ/QPE-uckZXF4/s1600/ASD_Mess.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBIvqV_26pI/AAAAAAAAAIQ/QPE-uckZXF4/s400/ASD_Mess.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;Looking at the picture above, can we really say that it is object-oriented programming? As services and DAOs don't strongly represent business concepts, the code becomes procedural. I don't want to bang on about the advantages of OOP over Procedural code. I believe that too many people have already discussed that over the past 30 years. My point here is to discuss what a "design" like that can do to an application.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Following bad examples&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Unfortunately, in software development, bad examples are easier to be followed than good examples. With a non-expressive business model like that, the services get overloaded with methods. When adding new features to the application, developers need to go through all the methods of a service to see if there is already a method that does what they need. Due to the &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;lack of cohesion&lt;/a&gt; and method explosion in the services, many developers will just add a new method in there, that can be very similar to existing ones, instead of re-factor the existing ones. This leads to services with confusingly similar methods and a lot of duplication. As a chain of "bad" events, the more methods a service has, the more classes depending on it the application will have. Many dependencies means that re-factoring the class would be harder, discouraging any one willing to improve the quality of the code. &lt;br /&gt;&lt;br /&gt;Duplication does not happen just inside a single service. It's also very common to find different services with very similar methods, if not the same. In general, this is due for the &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;lack of clarity on the responsibility&lt;/a&gt; of each service. According to the feature that developers are working on, they will choose a service to add (or reuse) the methods they need. If the responsibility and granularity of each service is not clear, business rules related to a certain area of the business will be spread all over the place since different developers will think that the method will belong to different classes. &amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Exposing DAOs to the presentation tier&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Another side effect of this approach is that since the DAOs are also "utility classes" with no business meaning (it just has an architectural meaning), some developers can easily expose the DAOs to the actions, without going through the services. Let's give more meaningful names and more details about the Action 4 and DAO 4 shown above. Let's call them ClientAction and ClientDAO.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBJr-biWIjI/AAAAAAAAAIY/9aKLt2EtXLQ/s1600/ClientAction_DAO.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="70" src="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBJr-biWIjI/AAAAAAAAAIY/9aKLt2EtXLQ/s400/ClientAction_DAO.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Here the user interface needs to display a list of clients. ClientDAO has a method that returns a list of clients. In theory this may make sense. The most used argument in favour of this approach instead of adding a "ClientService" in between the ClientAction and the ClientDAO is that the service would have a method that just delegates the call to the DAO. The service layer, in this case, would be considered redundant and just pointless extra work.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ONTWYUiOUvw/TBLIJH_oItI/AAAAAAAAAIg/xPmS5p-sBig/s1600/ClientASD_allClients.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="56" src="http://1.bp.blogspot.com/_ONTWYUiOUvw/TBLIJH_oItI/AAAAAAAAAIg/xPmS5p-sBig/s400/ClientASD_allClients.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Looking at this isolated scenario, having a service in the middle really looks a bit overkill and unnecessary. However, we will probably want to do more things with a client. We will probably want to create a new client, delete or update an existing client.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBLNxcSexsI/AAAAAAAAAIw/31fFgxmPgaw/s1600/ClientAction_DAO_allMethods.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="132" src="http://4.bp.blogspot.com/_ONTWYUiOUvw/TBLNxcSexsI/AAAAAAAAAIw/31fFgxmPgaw/s400/ClientAction_DAO_allMethods.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Here is where the problems begin. Very rarely, we have a pure &lt;a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete"&gt;CRUD&lt;/a&gt; application. In general, many business rules have to be performed before or after any changes are made in the persistence tier (generally a database). For example, before inserting a new client, a credit check needs to be performed. When deleting a new client, we need to make sure that there is no outstanding balance for that client and close his or her account. We also need to archive all the orders for this client.&amp;nbsp; Whatever the application's business rules dictate. Multiple entities (or database operations) may be involved in a operation like that. We need to be able to define transaction boundaries. Besides CRUD operations, we will also have all business methods like check if client has credit, add orders to a client, etc. This is too much for a single DAO to handle. DAOs should not perform any business logic and should be hidden from the presentation tier. It should be hidden (encapsulated) even from different services. DAOs should just deal with the persistence. Business logic and transaction boundaries should be controlled by a class with business responsibilities, that in the case of this "poor" design, it would be a service.&amp;nbsp; &amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ONTWYUiOUvw/TBLL4e4PlhI/AAAAAAAAAIo/D_GYk7jKRn8/s1600/ClientASD_allMethods.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="82" src="http://1.bp.blogspot.com/_ONTWYUiOUvw/TBLL4e4PlhI/AAAAAAAAAIo/D_GYk7jKRn8/s400/ClientASD_allMethods.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So even having a few methods in the service that just delegate the &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;responsibility&lt;/a&gt; to a DAO, it is still a price worth paying. The service should hide (encapsulate) the details of it's implementation. A client code does not need to know how and where the data is persisted. &lt;br /&gt;&lt;br /&gt;OK, enough of this. Exposing DAOs to the presentation tier is WRONG. Let's move on. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Moving away from the procedural code&lt;/b&gt; &lt;b&gt;(baby steps)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The first thing to do to move away from the procedural code is to make your code more expressive and aligned to the business. We need to narrow the gap between developers and domain experts (business analysts, users, product owner or whoever knows the business rules) so we all start speaking the same language. The code must be written in a way that it expresses the business and not just architectural concepts that means nothing to the business. Actions, Services and DAOs are technical terms with no connection to any business term. &lt;br /&gt;&lt;br /&gt;There are a few techniques that can be applied (or even combined) in order to make it possible. In future posts, I'll be talking about some of these techniques in more details. I know, it's frustrating that I will not tell you right now how to do it after have spending all this time criticising the ASD procedural design. The important thing for now is to know that what looks a good solution, since it is used by many different people and in many different projects, may not be as good as it seems.&lt;br /&gt;&lt;br /&gt;In the meantime, there is something that we can start doing to our code in order to reduce the mess and make the necessary refactorings easier in the future.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Preparing your code for an easier transition&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;The following advices will help us to get our code to a point where it can be easily refactored into a more domain (business) focused approach in the future. It will still be a bit procedural but will be much more well organised and a notion of components (business components) will start to emerge. &lt;br /&gt;&lt;br /&gt;1. Identify key concepts (domains) in your application. (e.g. Client, Order, Invoice, Trip, Itinerary, etc)&lt;br /&gt;2. You can create / refactor services for each one of the key domains.&lt;br /&gt;3. Try to keep a well balanced granularity for all services.&lt;br /&gt;4. Avoid services for small parts of the domain. For example, do not create a service for line items. Line items should be handled by the OrderService.&lt;br /&gt;5. Services are not allowed to manipulate multiple domains (with exceptions of whole-part relations - compositions)&lt;br /&gt;6. DAOs are encapsulated by the services and never accessed by any other class.&lt;br /&gt;7. Not every service must access a DAO, but any DAO must be accessed by one and only one service.&lt;br /&gt;8. Services must delegate operations to other services if the operation is related to a different domain from the one the service is handling.&lt;br /&gt;9. Services talk to each other. DAOs never talk to each other.&lt;br /&gt;10. Parts (like a line item) are never exposed by a service. Service always exposes the whole (like Order). Parts are accessed via the whole. (e.g. order.getLineItems();)&lt;br /&gt;&lt;br /&gt;With the following rules, our procedural code starts looking more like meaningful objects, with a reasonably well defined interface and some significance in terms of business.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ONTWYUiOUvw/TBLp6zdyr7I/AAAAAAAAAI4/xVjr-Pz6t7w/s1600/ASD_normalised.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/TBLp6zdyr7I/AAAAAAAAAI4/xVjr-Pz6t7w/s400/ASD_normalised.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&amp;nbsp;&amp;nbsp;&lt;br /&gt;As mentioned before, this is still a bit procedural but this design already solve a some of the problems discussed earlier like having more meaningful and specific services. The &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;responsibility &lt;/a&gt;and boundaries of each service are more defined, making it easier for developers to look for implemented methods and re-use what it is in there, reducing duplication.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;In future posts I'll be talking about the next steps towards a more expressive and business focused code, less procedural and more object-oriented.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;i&gt;If you are curious about the next steps and can't wait for my posts, have a look at:&lt;/i&gt;&lt;br /&gt;&lt;a href="http://domaindrivendesign.org/"&gt;http://domaindrivendesign.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;http://en.wikipedia.org/wiki/Behavior_Driven_Development&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Model-Driven_Architecture"&gt;http://en.wikipedia.org/wiki/Model-Driven_Architecture&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/OOD"&gt;http://en.wikipedia.org/wiki/OOD&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-4099309548608407319?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/4099309548608407319/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/06/wolf-in-sheeps-clothing.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/4099309548608407319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/4099309548608407319'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/06/wolf-in-sheeps-clothing.html' title='The Wolf in Sheep&apos;s Clothing'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_ONTWYUiOUvw/TBIWQTGjE5I/AAAAAAAAAH4/Y98_C2MOjZU/s72-c/ASD.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-356304251367071023</id><published>2010-06-06T19:22:00.000+01:00</published><updated>2010-06-06T19:22:31.305+01:00</updated><title type='text'>Object-Oriented Design Principles - Part 2</title><content type='html'>&lt;i&gt;In the &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;first part&lt;/a&gt; of this Object-Oriented Design principles series, I covered the &lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;Single Responsibility Principle (SRP)&lt;/a&gt;. I had also covered the &lt;a href="http://craftedsw.blogspot.com/2010/06/liskov-substitution-principle-lsp.html"&gt;Liskov Substitution Principle (LSP)&lt;/a&gt; on a previous post. So let's move on to another Object-Oriented Design Principle.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Open Closed Principle (OCP)&lt;/b&gt; &lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;Software entities (classes, modules, functions, etc.) should be open  for extension, but closed for modification&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;We know that requirements will change, new requirements will come and we will need to change some existing code during the life of a project. However, when a change in one place results in a cascade of changes in other classes, that's a sign that the design is not quite right. Changes causing side effects are undesirable since it makes the program unstable, rigid and fragile where parts can not be re-used. &lt;br /&gt;&lt;br /&gt;The Open Closed Principle target all problems described above. Being open for extension means that modules can be extended  in order to make them behave in a new or different way. Closed for modification means that we should not change existing code unless that we are fixing a bug.&lt;br /&gt;&lt;br /&gt;There were two proposed ways to achieve the OCP and both use inheritance:&lt;br /&gt;&lt;ol&gt;&lt;li&gt; Dr. &lt;a href="http://en.wikipedia.org/wiki/Bertrand_Meyer" title="Bertrand Meyer"&gt;Bertrand Meyer&lt;/a&gt;, that coined the &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;Open Closed Principle in 1988&lt;/a&gt;, proposes the use of inheritance. When a new feature or a changing on an existing feature is needed, a new class must be created, inheriting from the old one. The new class does not necessarily keep the same interface.&amp;nbsp; &lt;/li&gt;&lt;li&gt;A few other &lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;authors redefined the OCP&lt;/a&gt; in the 90ies. Basically they suggested the use of abstract base classes and concrete implementations. The abstract class would define the interface that would be closed to modifications. The concrete classes would implement the abstract class interface (open for extension) and multiple implementations could be created and polymorphically  substituted for each other.&amp;nbsp;&lt;/li&gt;&lt;/ol&gt;Nowadays, with the evolution of frameworks with dependency injection capabilities, a better approach would be having a client class pointing to an plain Java  interface and inject the implementations.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;OCP is an old OOP design principle and is one of the most important ones, due to the problems it solves. It can be an interesting approach in cases where the bureaucracy of changing old code and deployment to the production environment is very high. Some companies may ask for code reviews, a long test cycle (non-automated), documentation, etc. With OCP, no existing code is changed and just new code is added. &lt;br /&gt;&lt;br /&gt;However, in a more agile environment, good test coverage, IDEs that have good re-factoring tools (like Eclipse, Idea, etc) I wouldn't be too worried about changing classes and interfaces but this would not invalidate all the advantages of the OCP.&lt;br /&gt;&lt;br /&gt;Source&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29"&gt;http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29&lt;/a&gt; &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Open/closed_principle"&gt;http://en.wikipedia.org/wiki/Open/closed_principle&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.objectmentor.com/resources/articles/ocp.pdf"&gt;http://www.objectmentor.com/resources/articles/ocp.pdf&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Design_by_Contract"&gt;http://en.wikipedia.org/wiki/Design_by_Contract&lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Information_hiding"&gt;http://en.wikipedia.org/wiki/Information_hiding&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-356304251367071023?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/356304251367071023/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part_06.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/356304251367071023'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/356304251367071023'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part_06.html' title='Object-Oriented Design Principles - Part 2'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-7696888802968737838</id><published>2010-06-03T16:21:00.000+01:00</published><updated>2010-06-06T20:00:40.408+01:00</updated><title type='text'>Object-Oriented Design Principles - Part 1</title><content type='html'>Almost every developer that I know would be able to give a reasonable explanation about inheritance, encapsulation and polymorphism. However, there is much more to Object-Oriented Programming (OOP) than that. In  order to come up with a good and clean design, we need to bear in mind some Object-Oriented Design (OOD) principles. Although many of these principles were already published in books and blogs, they are known to just a very small percentage of developers. I don't want to show my age here, but very rarely we find young developers talking about OOD Principles.&lt;br /&gt;&lt;br /&gt;There  are quite a few OOD principles out there, created/coined by different developers and academics, but I will be listing here just the OOD principles that I consider to be the most important ones. &lt;br /&gt;&lt;br /&gt;The following 5 principles together are known by the mnemonic acronym "&lt;a href="http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29"&gt;SOLID&lt;/a&gt;". They were first put together by &lt;a href="http://en.wikipedia.org/wiki/Robert_C._Martin"&gt;Robert C. Martin (Uncle Bob)&lt;/a&gt; in the early  2000s and should be applied at class level. They are: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html"&gt;SRP — The Single Responsibility Principle&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part_06.html"&gt;OCP — The Open Closed Principle&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://craftedsw.blogspot.com/2010/06/liskov-substitution-principle-lsp.html"&gt;LSP — The Liskov Substitution Principle&lt;/a&gt;&lt;/li&gt;&lt;li&gt;ISP — The Interface Segregation Principle&lt;/li&gt;&lt;li&gt;DIP — The Dependency Inversion Principle&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;The Single Responsibility Principle (SRP)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;&lt;b&gt;There should never be more than one reason for a class to change.&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;The SRP is the simplest OOD Principle and probably one of the hardest to get right. It is also one of the most violated principles.  &lt;br /&gt;&lt;br /&gt;Let's have a look at the following class:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class TripItinerary {&lt;br /&gt;    public void addPlace(Place place) { ... }&lt;br /&gt;    public void removePlace(Place place) { ... }&lt;br /&gt;    public List&amp;lt;Place&amp;gt; getPlaces() { ... }&lt;br /&gt;    public void displayOnMap() { ... }&lt;br /&gt;    public Place findPlaceByName(String placeName) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The class above has 3 different responsibilities, that means, 3 different reasons to change:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Store the places to be visited. &lt;/li&gt;&lt;li&gt;Display the itinerary on a map. &lt;/li&gt;&lt;li&gt;Finds a place by name.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Storing places on the itinerary may have rules like not adding repeated places, keeping the sequence that places will be visited, etc. &lt;br /&gt;Displaying on the map may vary according to the map API being used like Google Map, Bing Map, Yahoo Maps, etc.&lt;br /&gt;Find a place by name may involve calling a web-services to see if the place exists, if there are more than one place with the same name, checking the type of place (city, town, waterfall, monument, castle, etc).&lt;br /&gt;&lt;br /&gt;Ideally we would have three different classes to do that, each one with its own responsibility. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class TripItinerary {&lt;br /&gt;    public void addPlace(Place place) { ... }&lt;br /&gt;    public void removePlace(Place place) { ... }&lt;br /&gt;    public List&amp;lt;Place&amp;gt; getPlaces() { ... }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class ItineraryMapService {&lt;br /&gt;    public void displayOnMap(TripItinerary tripItinerary) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class PlaceService {&lt;br /&gt;    public List&amp;lt;Place&amp;gt; findPlaceByName(String placeName) { ... }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;With these approach, we can change the internals of all classes without having the risk of breaking any of the behaviour of the other classes. Without this separation, the design becomes fragile and might break in unexpected ways when changed. &lt;br /&gt;&lt;br /&gt;When thinking about a single responsibility, think &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;cohesion at class level&lt;/a&gt;. Before creating a class, we need to define what its responsibility should be and the reason for its existence. Before adding  any other public method to an existing class, check if this new method relates to the other public methods (the class interface).  When creating public methods for a class, have them at least at a &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;communicational cohesion level&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;On the next posts, I'll be covering the remaining SOLID OOD principles.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part_06.html"&gt;Object-Oriented Design Principles - Part 2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Source&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29"&gt;http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;http://en.wikipedia.org/wiki/Single_responsibility_principle&lt;/a&gt;  &lt;br /&gt;&lt;a href="http://www.objectmentor.com/resources/articles/srp.pdf"&gt;http://www.objectmentor.com/resources/articles/srp.pdf&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-7696888802968737838?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/7696888802968737838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7696888802968737838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/7696888802968737838'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html' title='Object-Oriented Design Principles - Part 1'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-5776600455144649729</id><published>2010-06-02T01:50:00.000+01:00</published><updated>2010-06-02T01:54:39.938+01:00</updated><title type='text'>The Liskov Substitution Principle (LSP)</title><content type='html'>The Liskov Substitution Principle was initially introduced by &lt;a href="http://en.wikipedia.org/wiki/Barbara_Liskov" title="Barbara Liskov"&gt;Barbara Liskov&lt;/a&gt; in a 1987 conference keynote address entitled  &lt;i&gt;Data abstraction and hierarchy.&lt;/i&gt; LSP is also part of &lt;a href="http://en.wikipedia.org/wiki/Solid_%28object-oriented_design%29"&gt;SOLID&lt;/a&gt;, a group of five Object-Oriented Design Principles put together by Robert C. Martin in the early 2000s.&amp;nbsp;&lt;i&gt; &lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;b&gt;&lt;i&gt;Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.&lt;/i&gt;&lt;/b&gt;&lt;/blockquote&gt;&lt;br /&gt;The LSP's summary above looks quite obvious. If the calling code was written to use a base class, replacing it with a sub-class (inheritance) should make no difference to the calling code. That means, the calling code should not be changed and should be totally agnostic about which implementation is being used.&lt;br /&gt;&lt;br /&gt;LSP's importance is noticed mainly when it is violated. If a subclass causes changes on the calling code, that means, the calling code needs to test which subclass it is dealing with (instanceof, casting, etc), the code is violating the Liskov Substitution Principle and also the Open Closed Principle. This violation causes high coupling, low cohesion and a cascade of changes. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Violation of Liskov Substitution Principle&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public void drawShape(Shape s) {&lt;br /&gt;    if (s instanceof Square) {&lt;br /&gt;        drawSquare((Square) s);&lt;br /&gt;    } else if (s instanceof Circle){&lt;br /&gt;        drawCircle((Circle) s);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The Liskov Substitution Principle also imposes a few rules that the sub-classes must obey. It bears a certain resemblance with &lt;a href="http://en.wikipedia.org/wiki/Bertrand_Meyer"&gt;Bertrand Meyer&lt;/a&gt;'s &lt;a href="http://en.wikipedia.org/wiki/Design_by_Contract"&gt;Design by Contract&lt;/a&gt; in that it considers the interaction of subtyping with pre- and postconditions&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;i&gt;...when redefining a routine [in a derivative], you may only replace its precondition by a weaker one, and its postcondition by a stronger one.&lt;/i&gt;&lt;/blockquote&gt;&lt;br /&gt;This means the sub-classes must accept everything that the base class accepts (pre-condition) and must conform to all postconditions of the base class. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Example of a more subtle violation&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class Rectangle {&lt;br /&gt;    private int height;&lt;br /&gt;    private int width;&lt;br /&gt;&lt;br /&gt;    public Rectangle(int height, int width) {&lt;br /&gt;        this.height = height;&lt;br /&gt;        this.width = width;&lt;br /&gt;    }&lt;br /&gt;    public int getHeight() {&lt;br /&gt;        return this.height;&lt;br /&gt;    }&lt;br /&gt;    public void setHeight(int height) {&lt;br /&gt;        this.height = height;&lt;br /&gt;    }&lt;br /&gt;    public int getWidth() {&lt;br /&gt;        return this.width;&lt;br /&gt;    }&lt;br /&gt;    public void setWidth(int width) {&lt;br /&gt;        this.width = width;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Square extends Rectangle {&lt;br /&gt;&lt;br /&gt;    public Square(int size) {&lt;br /&gt;        super(size, size);&lt;br /&gt;    }  &lt;br /&gt;    public int getHeight() {&lt;br /&gt;        return super.height;&lt;br /&gt;    }&lt;br /&gt;    public int getWidth() {&lt;br /&gt;        return super.width;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In the code above, a Square &lt;b&gt;IS A&lt;/b&gt; Rectangle. Note that a rectangle can have different sizes for width and height, but in a square, height and width must be of the same size. What would happen in the following code is executed ?&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;Rectangle r = new Square();&lt;br /&gt;r.setHeight(5);&lt;br /&gt;r.setWidth(6);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We should not allow this to happen since that would make the Square object invalid. In a square, height and width must always be the same. A quick fix for this would be to override the setter methods:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class Square extends Rectangle {&lt;br /&gt;&lt;br /&gt;    public Square(int size) {&lt;br /&gt;        super(size, size);&lt;br /&gt;    }  &lt;br /&gt;    public int getHeight() {&lt;br /&gt;        return super.height;&lt;br /&gt;    }&lt;br /&gt;    public int getWidth() {&lt;br /&gt;        return super.width;&lt;br /&gt;    }&lt;br /&gt;    public void setHeight(int height) {&lt;br /&gt;        super.height = height;&lt;br /&gt;        super.width = width;&lt;br /&gt;    }&lt;br /&gt;    public void setWidth(int width) {&lt;br /&gt;        super.width = width;&lt;br /&gt;        super.height = width;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Although this approach would fix the problem, is a violation of the Liskov Substitution Principle since the methods will weaken (violate) the postconditions  for the Rectangle setters, which state that dimensions can be modified independently.&lt;br /&gt;&lt;br /&gt;One interesting thing to note is that if we analyse the Rectangle and Square classes in isolation, they are consistent and valid. However, when we look at how the classes can be used by a client program, we realise that the model is broken. &lt;br /&gt;&lt;br /&gt;Every time you get yourself adapting a sub-class so that it does not break or its state does not become invalid if used in the context of a super-class, this is a clue that the sub-class should not be a sub-class at all. &lt;br /&gt;&lt;br /&gt;In this example, maybe a Square is not a Rectangle. Square should not have height and width to start with. It should just have size. And since a Square is not a Rectangle, it should never be used in a Rectangle context. &lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;public class Square {&lt;br /&gt;    int size;&lt;br /&gt;    &lt;br /&gt;    public Square(int size) {&lt;br /&gt;        this.size = size;&lt;br /&gt;    }  &lt;br /&gt;    public int getSize() {&lt;br /&gt;        return this.size;&lt;br /&gt;    }&lt;br /&gt;    public void setSize(int size) {&lt;br /&gt;        this.size = size;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;We can not validate a model in isolation. A model should be validated just in terms of its clients. &lt;br /&gt;&lt;br /&gt;Source&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Liskov_substitution_principle"&gt;http://en.wikipedia.org/wiki/Liskov_substitution_principle&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.objectmentor.com/resources/articles/lsp.pdf"&gt;http://www.objectmentor.com/resources/articles/lsp.pdf&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-5776600455144649729?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/5776600455144649729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/06/liskov-substitution-principle-lsp.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/5776600455144649729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/5776600455144649729'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/06/liskov-substitution-principle-lsp.html' title='The Liskov Substitution Principle (LSP)'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-901092446006319007</id><published>2010-05-24T23:44:00.000+01:00</published><updated>2010-05-26T22:24:50.767+01:00</updated><title type='text'>Empowering your entities</title><content type='html'>The first thing I learnt when I started with Object-Oriented Programming was that an object should have &lt;b&gt;state &lt;/b&gt;and &lt;b&gt;behaviour&lt;/b&gt;. And indeed, that's how it was back then. However, since J2EE (Entity Beans) and other ORM tools like Hibernate, iBATIS, TopLink, JPA, etc, everything changed. We were so focused in mapping tables to objects, configure the relationships, lazy loading, eager fetching, primary keys and everything else that you can map and configure on the ORM tools that we simply forgot that those entities could and should also have some behaviour.&lt;br /&gt;&lt;br /&gt;In general, for applications that use a database, the entities are the key focus of the application. They are the main components of an application's &lt;a href="http://domaindrivendesign.org/node/99"&gt;core domain&lt;/a&gt; and their names and methods should represent, and also help to define, a common language used by all members of the team and not just developers (&lt;a href="http://domaindrivendesign.org/node/132"&gt;See Ubiquitous Language - Domain Driven Design&lt;/a&gt;).&amp;nbsp; &lt;br /&gt;&amp;nbsp; &lt;br /&gt;Let's see a few situations where your entities could be empowered.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1.&lt;/b&gt; &lt;b&gt;Default values / initialisation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Let's have a look at a fairly simple piece of code and see how many problems it may cause:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 1.1&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// Somewhere in the code &lt;br /&gt;DiscussionGroup dicussionGroup = new DiscussionGroup();&lt;br /&gt;discussionGroup.setCreationDate(new Date());&lt;br /&gt;discussionGroup.setLastUpdate(new Date()); &lt;br /&gt;discussionGroup.setAllowAnonymousPosts(false);&lt;br /&gt;&lt;br /&gt;// Somewhere else in the code&lt;br /&gt;if (discussionGroup.getAccess().equals(Access.PUBLIC) {&lt;br /&gt;   this.displayDiscussionGroupInfo(discussionGroup);&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Members members = discussionGroup.getMembers();&lt;br /&gt;for (Member member : members) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Do something&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This code above has the following problems:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;i&gt;creationDate&lt;/i&gt; and &lt;i&gt;lastUpdate&lt;/i&gt; setters being called right after creation. Let's assume both attributes are mandatory on the database. Wherever in the code a DiscussionGroup is created, we need to remember to set them both. In Failing to do so, we will get an error when persisting the entity. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;The check to verify if the discussion group is public may throw a NullPointerException if the attribute is not initialised.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Like the access check, the iteration over the discussion group members can also fail if the list of members is not initialised.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The calling code needs to know about the internals of the entity and cater for that, like setting values to mandatory fields and also do null checks for some attributes. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;To solve the problems, just initialise all the attributes you can, I mean, the ones where a default value would make sense. Always avoid having getters returning &lt;b&gt;null&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 1.2&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// DiscussionGroup.class&lt;br /&gt;public class DiscussionGroup {&lt;br /&gt;    private Date creationDate;&lt;br /&gt;    private Date lastUpdate;&lt;br /&gt;    private boolean allowAnonymousPosts;&lt;br /&gt;    private Access access;&lt;br /&gt;    private List&amp;lt;Member&amp;gt; members;&lt;br /&gt;    &lt;br /&gt;    public DiscussionGroup() {&lt;br /&gt;        this.creationDate = new Date();&lt;br /&gt;        this.lastUpdate = new Date();&lt;br /&gt;        this.allowAnonymousPosts = false;&lt;br /&gt;        this.access = Access.PRIVATE;&lt;br /&gt;        this.members = new ArrayList&amp;lt;Member&amp;gt;();    &lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;2. Operation that just involves an entity's attributes.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Look at the code below. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 2.1&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// OrderService.class&lt;br /&gt;if (order.getTotal() &gt; 0 &lt;br /&gt;        &amp;&amp; order.getOrderItems().size() &gt; 0&lt;br /&gt;        &amp;&amp; order.getAuthorizationDate() != null &lt;br /&gt;        &amp;&amp; order.getClient() != null) {&lt;br /&gt;    this.processOrder(order);&lt;br /&gt;}    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The if statement checks attributes from the order object so that it can decide if the order can be processed or not. Note that this logic is outside the order object, making the two classes tightly coupled and making a poor use of encapsulation. In this case, we could re-factor this code like that:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 2.2&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// Order.class&lt;br /&gt;public boolean isReadyForProcessing() {&lt;br /&gt;    this.getTotal() &gt; 0 &lt;br /&gt;        &amp;&amp; this.getOrderItems().size() &gt; 0&lt;br /&gt;        &amp;&amp; this.getAuthorizationDate() != null &lt;br /&gt;        &amp;&amp; this.getClient() != null);&lt;br /&gt;}      &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// OrderService.class - Somewhere in the code&lt;br /&gt;if (order.isReadyForProcessing() {&lt;br /&gt;    this.processOrder(order);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This re-factored code makes the code more expressive, easy to read and easy to test. This also makes the code to better represent the business rules. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. Children manipulation&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Look at the listings 3.1 and 3.2.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 3.1&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// Add an entry to a diary.&lt;br /&gt;Diary diary = new Diary();&lt;br /&gt;Entry entry = new Entry();&lt;br /&gt;entry.setDate(new Date()); &lt;br /&gt;entry.setText("Today I went ... ");&lt;br /&gt;diary.getEntries().add(entry);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Listing 3.2&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// Remove an entry from a diary.&lt;br /&gt;ListIterator&amp;lt;Entry&amp;gt; entriesIterator = &lt;br /&gt;        diary.getEntries().listIterator();&lt;br /&gt;Entry entry;&lt;br /&gt;while (entriesIterator.hasNext()) {&lt;br /&gt;    entry = entriesIterator().next();&lt;br /&gt;    if (entry.getDate().equals(someDateVar)) {&lt;br /&gt;        entriesIterator.remove();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The main problem with &lt;i&gt;Listing 3.1&lt;/i&gt; and &lt;i&gt;Listing 3.2&lt;/i&gt; is that the parent class Diary is exposing its internals, the entries. Once again, this is a major encapsulation breach. As a principle, the parent should never let a stranger manipulates its children without its consent. Besides all the code duplication that this may cause, in case that I want to add/delete entry in different parts of the application (for some reason), this also makes the code to be very fragile where the parent may break since it was not notified that someone changed its children. &lt;br /&gt;&lt;br /&gt;This could be easily fixed if we add this logic to the parent class. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 3.3&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// Diary.class&lt;br /&gt;public Entry addEntry(Date date, String text) {&lt;br /&gt;    Entry entry = new Entry();&lt;br /&gt;    entry.setDate(date);&lt;br /&gt;    entry.setText(text);&lt;br /&gt;    this.entries.add(entry);&lt;br /&gt;    return entry;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Entry deleteEntry(Date date) {&lt;br /&gt;    ListIterator&amp;lt;entry&amp;gt; entriesIterator = &lt;br /&gt;            this.getEntries().listIterator();&lt;br /&gt;    Entry entry;&lt;br /&gt;    while (entriesIterator.hasNext()) {&lt;br /&gt;        entry = entriesIterator().next();&lt;br /&gt;        if (entry.getDate().equals(someDateVar) {&lt;br /&gt;            entriesIterator.remove();&lt;br /&gt;            break;&lt;br /&gt;        }&lt;br /&gt;    }        &lt;br /&gt;    return entry;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The calling code would be like:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Listing 3.4&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: java"&gt;// Add an entry to a diary.&lt;br /&gt;Diary diary = new Diary();&lt;br /&gt;Date date = new Date();&lt;br /&gt;diary.addEntry(date, "Today I went ... ");&lt;br /&gt;&lt;br /&gt;// Remove an entry from a diary.&lt;br /&gt;diary.deleteEntry(date);&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;br /&gt;Entities don't need to be just dumb classes with state and no behaviour. They should contain business logic that is related to their attributes and children. This will promote encapsulation, reduce code duplication, make your code more expressive and easy to read and also much easier to test.&lt;br /&gt;&lt;br /&gt;Sources:&lt;br /&gt;&lt;a href="http://domaindrivendesign.org/"&gt;http://domaindrivendesign.org/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.amazon.co.uk/Domain-driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1274395774&amp;amp;sr=8-1"&gt;Domain Driven Design - by Eric Evans&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.amazon.co.uk/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1274395683&amp;amp;sr=8-1"&gt;Clean Code - by Robert C. Martin&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-901092446006319007?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/901092446006319007/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/05/empowering-your-entities_24.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/901092446006319007'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/901092446006319007'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/05/empowering-your-entities_24.html' title='Empowering your entities'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-1471788464541250127</id><published>2010-05-09T03:28:00.000+01:00</published><updated>2010-05-09T04:09:08.040+01:00</updated><title type='text'>MVC and Multi-tier architecture</title><content type='html'>Over the years, working in different web-based Java projects, I noticed that there is a big confusion about the boundaries and overlaps between MVC, that is an architectural pattern, and a multi-tier architecture (also known as n-tier architecture). The main confusion is in identifying what is controller, what is model and what is application (business) tier. The results of this confusion, to name just a few, are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; Unclear design; &lt;/li&gt;&lt;li&gt;Poor re-usability (loads of copy and paste);&lt;/li&gt;&lt;li&gt; Non-cohesive classes and methods;&lt;/li&gt;&lt;li&gt;Business logic all over the place;&lt;/li&gt;&lt;li&gt; Difficult to test;&lt;/li&gt;&lt;li&gt; Difficult to measure the impact of changes and improvements;&lt;/li&gt;&lt;li&gt;And people's favourite, actions (if using Struts-like web frameworks) with hundreds, if not thousands of lines.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;I'll quickly refresh our memories about multi-tier architecture and MVC so that later we can see how they relate to each other.&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Multi-tier architecture&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Often called n-tier architecture, the multi-tier architecture is a logical way to separate the different responsibilities of your application. The most common multi-tier architecture is the &lt;b&gt;three-tier architecture&lt;/b&gt;, which will be the one that I'll be focusing on. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_ONTWYUiOUvw/S-YCABMbb2I/AAAAAAAAAHI/ZXk8yijlxNw/s1600/3_tier.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="27" src="http://4.bp.blogspot.com/_ONTWYUiOUvw/S-YCABMbb2I/AAAAAAAAAHI/ZXk8yijlxNw/s400/3_tier.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The tree-tier architecture is divided in the following tiers:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Presentation tier&lt;/b&gt;: It is responsible to interact with the user, displaying information and providing ways where the user can input data and perform actions.&amp;nbsp;&lt;/li&gt;&lt;li&gt; &lt;b&gt;Application tier&lt;/b&gt;: It is responsible for the coordination of the application, its business logic, decisions, calculations and evaluations. It executes commands, actions and moves data between the presentation and data tiers. It is also known as business tier, logic tier or middle tier.&lt;/li&gt;&lt;li&gt;&lt;b&gt;Data tier&lt;/b&gt;: It is responsible to retrieve and store data. Data can be stored in a database, xml, file system or even other system. It is also known as persistence tier.&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;Each tier must be as independent as possible from each other, where a good practice would be to provide interfaces as "facades" to each tier. Organising your classes according to these logical tiers would make the code more &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;cohesive&lt;/a&gt;, loosely coupled, easier to understand and easier to test. This approach would also help to improve greatly the re-usability and would make changes to be more localised, minimising the impact on the rest of the code.&lt;br /&gt;&lt;br /&gt;A multi-tier architecture would be for applications that access other systems (RPCs, webservices, etc), access multiple sources of data, or uses any sort of &lt;a href="http://en.wikipedia.org/wiki/Middleware"&gt;middleware&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;MVC and Java MVC frameworks.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;i&gt;I will assume that people reading this post already know MVC so I'll give just a brief and generic description of how MVC and its variations like Model 1 and Model 2 work. If you need more information about it, please refer to the links at the end of this post. &lt;/i&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ONTWYUiOUvw/S-YAm2IZWgI/AAAAAAAAAHA/-8p3XHqBPgs/s1600/MVC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="116" src="http://1.bp.blogspot.com/_ONTWYUiOUvw/S-YAm2IZWgI/AAAAAAAAAHA/-8p3XHqBPgs/s400/MVC.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;The general behaviour of the &lt;a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;MVC pattern&lt;/a&gt; is:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;User performs an action on the view (screen, page). This action can be anything like clicking a button, clicking a link, selecting an item from a drop down list, etc. Data may be submitted, in case of a form. &lt;/li&gt;&lt;li&gt; Controller receives the request or event and invokes the model.&lt;/li&gt;&lt;li&gt;Model will perform some business logic, persist or fetch some data.&lt;/li&gt;&lt;li&gt;Model return the result of this operation to the controller. This result may include some data.&amp;nbsp;&lt;/li&gt;&lt;li&gt;Controller, according to the result from the model, invokes the next view. The next view can be the same one that originated the request or a different one.&lt;/li&gt;&lt;li&gt;View is rendered. The view may display any data returned from the model. &lt;/li&gt;&lt;/ol&gt;Java MVC frameworks like Struts, Spring MVC and alike are based on what we call &lt;a href="http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html"&gt;MVC Model 2&lt;/a&gt;, that is a variation of the original MVC pattern. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Fitting MVC into a Three-tier Architecture&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In a traditional java web application, View and Controller will belong to the Presentation tier and Model will belong to the application and data tiers. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ONTWYUiOUvw/S-YDvM2hnDI/AAAAAAAAAHQ/lmgoUCwxSH4/s1600/3TierVsMVC.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="53" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/S-YDvM2hnDI/AAAAAAAAAHQ/lmgoUCwxSH4/s400/3TierVsMVC.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;So far so good, but when using Java Web frameworks like Struts, Spring MVC, JSF, etc, the catch is to be able to identify what is controller and what is model. &lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Understanding the role of the "action" classes.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Struts was one of the first and one of the most used Java MVC frameworks. When it was released, back in 2000 (version 1.0 in 2001), many developers did not get the whole MVC Model 2 thing and very quickly started misusing the framework and sacrificing some important architectural patterns. The situation got worse when other frameworks also based on Model 2 were released, since the same bad old habits from Struts&amp;nbsp; were used to develop applications with frameworks like WebWork, Spring MVC, etc.&lt;br /&gt;&lt;br /&gt;In Struts, when some action is performed on the page, an "action" class is invoked. This action class is probably the source of the whole problem. What exactly is this action class? I mean, what's the purpose of this class and where does it belong, taking into consideration the MVC pattern and the three-tier application?&lt;br /&gt;&lt;br /&gt;Since the View is done by the JSPs, the Controller is done by the servlet (that is configured on the web.xml), many would answer that this class is the model. This would explain why we find so many actions with thousands of lines and full of business logic. &lt;br /&gt;&lt;br /&gt;However, the action class &lt;b&gt;DOES&lt;/b&gt; &lt;b&gt;NOT&lt;/b&gt; belong to the Model.&lt;br /&gt;&lt;br /&gt;All requests are handled by the same servlet (&lt;a href="http://java.sun.com/blueprints/patterns/FrontController.html"&gt;Front Controller design pattern&lt;/a&gt;), and then the respective action is called (&lt;a href="http://en.wikipedia.org/wiki/Command_pattern"&gt;Command design pattern&lt;/a&gt;). The result of this action will be the view to be displayed. So, in summary, what is the responsibility of this action class? The action is triggered by the view, does some thing and decides which view will be displayed next. This is exactly what a MVC Controller does, meaning that action classes are also part of the Controller, working almost as an extension or helpers for the main servlet. &lt;br /&gt;&lt;br /&gt;When Spring MVC came out, one of the first things that I noticed was that they called the equivalent Struts Action class, "Controller". That's right. In Spring MVC, you create controllers instead of actions, what makes much more sense. However, even naming the classes as controllers, some developers kept adding business logic to them. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_ONTWYUiOUvw/S-YnQsyf8eI/AAAAAAAAAHo/rQDgoiRI5Tc/s1600/Struts.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="77" src="http://2.bp.blogspot.com/_ONTWYUiOUvw/S-YnQsyf8eI/AAAAAAAAAHo/rQDgoiRI5Tc/s400/Struts.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;In summary, the action class must just invoke the model (could be a service, session bean, business object, etc.), get the result, set it into a context (session, request, etc) and invoke the view. Action classes should be small, clean and without any business logic, as a Controller class should be. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Component-centric frameworks and its "backing bean" classes&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;In component-centric frameworks like JSF, Tapestry, Wicket and alike, the pages (generally XHTML) have components that are bound to Java classes (known as backing beans in JSF). These components can be input texts, drop down lists, tables, etc, or even the entire page. Basically each component on the page can be bound to a Java class, that would behave like a model and sometimes controller for these components.The backing beans are responsible to hold the state of the components and also handle events, validation, conversions, trigger business logic, update/refresh other components, fire events, listen to events, etc. &amp;nbsp; &lt;br /&gt;&lt;br /&gt;Now that we know that Struts Actions and Spring Controllers belong to the Controller part of the MVC, where do the backing bean classes (JSF like) belong to?&lt;br /&gt;&lt;br /&gt;When we talk about component-centric web frameworks and also add AJAX into the mix, the line between controller and model becomes a little bit blurred.&lt;br /&gt;&lt;br /&gt;The backing bean may handle navigation and in this case, it would act as a controller. When acting as model for its view component, although it is a model, it is a model for that specific view component. That means, the logic that this backing bean should perform would be related to rendering the view component or invoking other view components (events, re-render, etc) and not exactly application business logic, keeping this managed bean &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;coherent&lt;/a&gt;. Any application business logic like making calculations, fetching or storing data, make a web service call, etc, should be delegated to a business class belonging to the application tier. &lt;br /&gt;&lt;br /&gt;So in the case of a component-centric framework, managed beans would belong to the presentation tier, even being models for view components.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_ONTWYUiOUvw/S-YZK-wJGNI/AAAAAAAAAHg/7mP80oSq-eg/s1600/ManagedBean.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="77" src="http://1.bp.blogspot.com/_ONTWYUiOUvw/S-YZK-wJGNI/AAAAAAAAAHg/7mP80oSq-eg/s400/ManagedBean.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;NOTE: All classes related to the java web frameworks like validators, converters, forms, etc, also belong to the Presentation tier.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Summary&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;When developing applications it is important&lt;b&gt; &lt;/b&gt;to keep your code &lt;a href="http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html"&gt;cohesive&lt;/a&gt; and loosely coupled. The first step is to make a quick analyses and define the logical tiers. In case of a web application with database access, it will not differ too much from a three-tier architecture. If integrating with other systems or accessing multiple data sources, application and data tiers may be broken down into more tiers.&lt;br /&gt;&lt;br /&gt;When using Java web frameworks, regardless if they are page-centric (Struts like) or component-centric (JSF like), chances are that everything related to the framework (forms, converters, validators, actions, controllers, managed beans, etc) will belong to the presentation tier and should not have business logic. Business logic and data access should be delegated from the presentation tier to the application tier. This would allow us to keep our managed beans and actions (controllers) very small and clean. &lt;br /&gt;&lt;br /&gt;In case of too much view logic (enabling/disabling components, populating tables and drop down lists, validations, etc), use helper classes for the actions and managed beans (see &lt;a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/ViewHelper.html"&gt;View Helper design pattern&lt;/a&gt;) &amp;nbsp;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;For the model, application and data tier, they will be covered in future posts since they can vary a lot from application to application.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;Source&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Multitier_architecture"&gt;http://en.wikipedia.org/wiki/Multitier_architecture&lt;/a&gt; &lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller"&gt;http://en.wikipedia.org/wiki/Model-view-controller&lt;/a&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/blueprints/patterns/MVC-detailed.html"&gt;http://java.sun.com/blueprints/patterns/MVC-detailed.html&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.ibm.com/developerworks/library/j-jsf1/"&gt;http://www.ibm.com/developerworks/library/j-jsf1/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html"&gt;http://www.javaworld.com/javaworld/jw-12-1999/jw-12-ssj-jspmvc.html&lt;/a&gt; &lt;br /&gt;&lt;a href="http://java.sun.com/developer/technicalArticles/J2EE/despat/"&gt;http://java.sun.com/developer/technicalArticles/J2EE/despat/&lt;/a&gt;&lt;br /&gt;&lt;a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/ViewHelper.html"&gt;http://java.sun.com/blueprints/corej2eepatterns/Patterns/ViewHelper.html &lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-1471788464541250127?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/1471788464541250127/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/05/mvc-and-multi-tier-architecture.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1471788464541250127'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/1471788464541250127'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/05/mvc-and-multi-tier-architecture.html' title='MVC and Multi-tier architecture'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_ONTWYUiOUvw/S-YCABMbb2I/AAAAAAAAAHI/ZXk8yijlxNw/s72-c/3_tier.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8424060401701893376.post-2685339140688824413</id><published>2010-04-24T02:45:00.000+01:00</published><updated>2010-08-24T13:38:05.718+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cohesion OOP &quot;Object-Oriented Programming&quot; &quot;Software Craftsmanship&quot;'/><title type='text'>Cohesion - The cornerstone of OO</title><content type='html'>Cohesion is probably the most important concept of Object-Oriented Programming since it promotes a good level of encapsulation, separation of concerns and responsibilities, re-usability and maintainability. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Definition&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Cohesion (noun)&lt;/b&gt; : when the members of a group or society are united.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Cohesive (adjective)&lt;/b&gt; : united and working together effectively.&lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;i&gt;&lt;span style="font-size: x-small;"&gt;Cambridge Dictionary&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;In computer programming, cohesion is a measure of how strongly-related and focused the various responsibilities of a software module are. &lt;/span&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;i&gt;&lt;span style="font-size: x-small;"&gt;Wikipedia&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Cohesion at method level&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;&amp;nbsp;Coincidental (worst): &lt;/b&gt;Performs multiple operations and some times they are not related to each other.&amp;nbsp; &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Conditional: &lt;/b&gt;According to an if statement, different attributes are modified or different values are set to the different attributes.&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Iterative: &lt;/b&gt;Several attributes (Array variables) are modified as a result of a looping.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Communicational: &lt;/b&gt;More than one attribute is modified according to only one input.&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Sequential: &lt;/b&gt;More than one variable (object) modification result in the change to only one attribute.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size: small;"&gt;&lt;b&gt;Functional (best): &lt;/b&gt;Method modifies fewer than 2 attributes.&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Cohesion at class level &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;Coincidental (worst):&lt;/b&gt; Methods grouped arbitrarily and have no significant relationship (E.g. Util classes with methods handling strings, lists, mathematical calculations)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Logical:&lt;/b&gt; Methods grouped because they logically are categorized to do the same thing, even if different by nature (E.g. grouping all I/O handling routine, all database selects, inserts, etc.).&lt;/li&gt;&lt;li&gt;&lt;b&gt;Temporal:&lt;/b&gt; Methods grouped by when they are processed at a particular time in program execution (E.g. validates data, persist the data, create audit information, notifies user via email).&lt;/li&gt;&lt;li&gt;&lt;b&gt;Procedural:&lt;/b&gt; Methods grouped because they always follow a certain sequence of execution. (Verify is user exist, performs login, write logs, retrieve user's detail)&lt;/li&gt;&lt;li&gt;&lt;b&gt;Communicational:&lt;/b&gt; Methods grouped because they work on the same data (E.g. Insert, delete, validate, update a client entity).&lt;/li&gt;&lt;li&gt;&lt;b&gt;Sequential:&lt;/b&gt; Methods grouped because the output of one method can be used as an input of other methods. (reads a file, process the file).&lt;/li&gt;&lt;li&gt;&lt;b&gt;Functional (best):&lt;/b&gt;&amp;nbsp; Methods grouped because they all contribute to a single well-defined task. (parsing XML)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;span style="font-size: large;"&gt;&lt;b&gt;Applying cohesion in the real world&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Depending of the type of software you are writing, you will need to compromise a little bit. It is not always possible to have all methods and classes at the highest cohesion level (functional).&lt;br /&gt;&lt;br /&gt;If you are building a framework or a very generic part of your system, chances are that the majority of your classes and methods will be at sequential and functional levels. However, when writing a more commercial application, I mean, an application where there are business logic, database access, users, etc, there is a good chance that many of your classes and methods will be more at the &lt;b&gt;communicational&lt;/b&gt; level.&lt;br /&gt;&lt;br /&gt;In a more simplistic way, each class and each method should have a &lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;single responsibility&lt;/a&gt;. A technique that I use for that is to write a brief description (javadoc) for each class and method before writing the methods of the class or the body of the method. This forces me to think what the responsibility of the class or method that I'm creating is and as soon as I realise that the class or method is doing more than what I described, I know that I need to break it down in more classes or methods (private or public ones).&lt;br /&gt;&lt;br /&gt;Some people use other criteria, like number of public methods per class or number of lines per method. This sort of metrics are helpful because it makes you re-analyse your code and can be a good indicator that something is not quite right. A class with many public methods is an indication that the class may be doing too much and does not have a single responsibility, having a low cohesion. A method with many lines is also an indication that this method may be doing too much. One of the problems with this approach as a cohesion measure is knowing how much is too much. Is 10 lines of code per method too much? What about 20? Is 10 public methods in a class too much? Number of methods per class or number of lines of code per method don't necessarily tells much about how cohesive the class or method is, but they can be used as a "smell detector". Thinking on a single purpose for each class and each method before you implement them will help you to keep your classes and methods small without much effort.&lt;br /&gt;&lt;br /&gt;The more cohesive your code is, the more reusable, robust, easy to test and reliable it is.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;b&gt;Source &lt;/b&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Cohesion_%28computer_science%29"&gt;http://en.wikipedia.org/wiki/Cohesion_%28computer_science%29&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.waysys.com/ws_content_bl_pgssd_ch06.html%20"&gt;http://www.waysys.com/ws_content_bl_pgssd_ch06.html &lt;/a&gt;&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;http://en.wikipedia.org/wiki/Single_responsibility_principle&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8424060401701893376-2685339140688824413?l=craftedsw.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://craftedsw.blogspot.com/feeds/2685339140688824413/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2685339140688824413'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8424060401701893376/posts/default/2685339140688824413'/><link rel='alternate' type='text/html' href='http://craftedsw.blogspot.com/2010/04/cohesion-cornerstone-of-oo.html' title='Cohesion - The cornerstone of OO'/><author><name>Sandro Mancuso</name><uri>http://www.blogger.com/profile/02110812790722611225</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='29' src='http://1.bp.blogspot.com/_ONTWYUiOUvw/S8mKolZXe1I/AAAAAAAAAF8/pFcbRAmVbxE/S220/Sandro2.jpg'/></author><thr:total>0</thr:total></entry></feed>
