tag:blogger.com,1999:blog-84240604017018933762024-03-14T06:18:27.467+00:00Crafted SoftwareWhere how it is done is as important as having it done.Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.comBlogger45125tag:blogger.com,1999:blog-8424060401701893376.post-38130234059916988182015-03-20T01:25:00.002+00:002015-03-20T01:25:54.327+00:00New Blog @ codurance.com/blog<div dir="ltr" style="text-align: left;" trbidi="on">
Hi all,<br />
<br />
Quite a few people asked me if I had stopped blogging. The answer is NO. In November 2013, Mashooq Badar and I started <a href="http://codurance.com/" target="_blank">Codurance</a> and since then I only blogged on our company <a href="http://codurance.com/" target="_blank">website</a>.<br />
<br />
Please visit <a href="http://codurance.com/blog">http://codurance.com/blog</a> for my latest blogs.<br />
<br />
Apologies for taking more than one year to add this message here.<br />
<br />
Cheers<br />
Sandro</div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-73775811643749800652013-11-21T23:18:00.003+00:002013-11-22T00:04:07.747+00:00Starting a Software Craftsmanship Community <div dir="ltr" style="text-align: left;" trbidi="on">
Two people that meet regularly are already a community. The first thing to know if you want to start a community is that it is much simpler than you think. You just need another person that is keen to meet regularly and a public space like a coffee shop or a quiet pub. That's it. You already have your community going. Everything else that follows in this blog post are just things that helped us to grow the <a href="http://londonswcraft.com/" target="_blank">London Software Craftsmanship Community</a> (LSCC) from two people to the largest software craftsmanship community in the world, but they are not essential to have a great and healthy community.<br />
<br />
<h2 style="text-align: left;">
Community website</h2>
<br />
This is an important thing. Don't try to run your community from a mailing list; make sure you have a proper website. One of the points of being part of a community is to know who else is in the community. As a member, I want to go to the website and see when the next events are. I want to be notified in advance about the events, and be reminded about the events one or two days before they happen. I want to know who else is going to the event. I want to place myself on a waiting list in case the event is full. I want to tell others that I'm going to the event. I want to see the profile of the people attending the event so I can have more focused conversations during or after the event. I want to have a mailing list where I can ask questions and engage in discussions.<br />
<br />
The good news is that there are a few websites out there that, for an annual subscription, you can have all that. We decided to use <a href="http://www.meetup.com/">Meetup.com</a> (used by the majority of the Software Craftsmanship communities around the world) and I highly recommend it. Don't waste your time trying to create your own website, at least not in the first year or so. Focus only on the quality and content of your meetings. Don't waste your time doing things that are already done for you. Websites like Meetup.com will take care of all the admin work for you: controlling registrations, email, waiting list, reminders, etc. (In case you are wondering, I don't get any commission from Meetup.com, however, now that I thought about it, I probably should.:))<br />
<br />
<h2 style="text-align: left;">
Your first meeting</h2>
<br />
Some communities started with a big first meeting. Others started quite small and without much noise. As you probably guessed, there is no right or wrong. In London, we decided to give a talk on Software Craftsmanship. The <a href="http://www.meetup.com/Londonjavacommunity/" target="_blank">London Java Community</a> (LJC) announced our talk to their members. <a href="http://skillsmatter.com/" target="_blank">SkillsMatter</a>, the training centre where the talk happened, also announced on their website and for our huge surprise, 120 people showed up. The <a href="http://www.meetup.com/paris-software-craftsmanship/" target="_blank">Paris Software Craftsmanship Community</a> (PSCC) invited me to give a talk for their kick off meeting and they had more than 50 people.<br />
<br />
It helps if you can have a big first meeting; potentially inviting someone that you know that can give a good talk on Software Craftsmanship but that is not really necessary. Many other communities started really small and now they are doing really well. It's important that we understand that a Software Craftsmanship community is not about numbers or well-known people. A Software Craftsmanship community is about passionate software developers sharing and learning from each other, regardless if there are 5 or 1000 of them. <br />
<br />
<h2 style="text-align: left;">
Start with simple meetings</h2>
<br />
The simpler the meetings are, the better. When starting a Software Craftsmanship community, chances are that you won't have much help. We are all busy people, with families, work, and many other activities. If we make the job of organising a community a burden, we will end up giving up. To minimise the chances for that to happen, make sure that, at least in the beginning, your meetings are extremely simple to organise.<br />
<br />
For almost one year, we just had one meeting a month: The Software Craftsmanship Roundtable. This meeting was limited to 30 people. Back then, I was working for [Valtech](http://www.valtech.co.uk/) and they were kind enough to let me use their office space from 6:30pm to 9pm. They also paid for pizzas and soft drinks.<br />
<br />
<h3 style="text-align: left;">
The Software Craftsmanship Roundtable</h3>
<br />
The Software Craftsmanship Roundtable is a very easy meeting to organise. At the start of the meeting, we ask all attendees if they want to give a lightning talk (five minutes for the presentation, two minutes for questions) or/and propose a topic for a group discussion. Attendees write their lighting talks or topics for discussion in a Post-It and stick them in a white board. While we are eating some pizza, people present their lighting talks. The facilitator, normally the community organiser, keeps track of time. Once all the lightning talks are finished (if any), we ask each person that proposed a topic, in turn, to give a 30 seconds explanation of what they want to discuss. Once all topics are explained, we take a vote. Every one raises their hands for the topics that they want to discuss (they can vote for more than one topic) and the most voted topic gets discussed. Sometimes we discuss a single topic in one night; sometimes we discuss three or four. Depending of how people vote, we some times split in two groups and then have a retrospective at the end. Every 30/45 minutes (use your gut feeling) you ask the group if they want to keep discussing the same topic or pick another one.<br />
<br />
The great thing about the round table is that whichever topic is chosen, we know we are going to have a good discussion since the majority of the people voted for it. Topics can vary immensely, from tools and good practices to continuous deployment, from design and architecture to interview techniques, from how to convince teammates to adopt TDD to functional languages.<br />
<br />
The overhead of organising a roundtable is very small. You just need to make sure you have a venue. If you don't have an office space, do it in a coffee shop or pub. Food is totally optional. If you have it, great, if you don't have it, it's OK. Don't let food sponsorship be the reason for not having a meeting. I'm sure people wouldn't mind to eat before or after the meeting and pay for it themselves. :)<br />
<br />
<h3 style="text-align: left;">
Hands-on session</h3>
<br />
Hands-on sessions tend to be slightly more difficult to organise. This is the second type of meeting we introduced. Arguably, it should have been the first type of meeting to have but that was what we did. Hands-on sessions require a venue where people can not only sit down but also have a place to put their laptops. That means that not always a pub or another public place can be a good choice. A proper office space is always a better option.<br />
<br />
Over the years we had many different types of hands-on session. Some of them required a lot of preparation; some of them were dead simple to organise. We also had a mix of very experienced and not so experienced people running the sessions. They were all great.<br />
<br />
For the first few hands-on sessions, keep it simple. Choose a kata, do it yourself a few times, and don't tell anyone which kata you've chosen. All attendees need to bring their own laptops with their favourite languages and testing frameworks installed. Have all attendees in a room and ask them to pair up with someone; preferably someone that they don't know or they never paired before. At least one person in the pair needs to have a laptop configured with their favourite language and testing framework. For people starting with TDD, it helps if they pair with people a bit more experienced. Give them time, between one and two hours, with a few breaks (5 minutes) for sharing, and towards the end, run a retrospective. While the pairs are working on the kata, walk around, observe what the pairs are doing, and help the pairs that are stuck. In the final retrospective, ask the pairs which approach they used, what they've learn, which technologies they used, etc. As you know what the majority of the pairs have done, you can poke people to share what they've done. :)<br />
<br />
There are many different types of things you can do in a hands-on session but I'll leave them to another post.<br />
<br />
<h2 style="text-align: left;">
Rhythm </h2>
<br />
A community needs to have a rhythm. A heartbeat. For example, our Software Craftsmanship Roundtable meetings are always on the second Tuesday of the month, at the same time, in the same place. Our hands-on sessions are always on the last Wednesday of the month. Code & Coffees are always every other Tuesday in the same coffee shop.<br />
<br />
It's important that members of the community know when and where the meetings are going to happen so they can organise themselves to be there. A good rhythm keeps the community alive. When choosing a venue, make sure you can run meetings there every month. Once you run the first meeting in a new venue, it is much easier to run subsequent ones. Finding venues is not always easy, so make sure you don't need to do it every month.<br />
<br />
In case you can't be in the meeting, make sure someone else can facilitate the meeting. Try never to break the rhythm. Having long gaps between the meetings will make people loose interest.<br />
<br />
Make sure that you never have an empty calendar, that means, as soon as the a meeting is finished, you should have the date for the next meeting. People tend not to join a group if there are no meetings scheduled.<br />
<br />
<h2 style="text-align: left;">
Technology Specific vs. Technology Agnostic</h2>
<br />
There are quite a few Software Craftsmanship communities that have many technology specific meetings. By that, I mean, they have a hands-on session to learn Erlang, or to try a JavaScript framework, or a specific NoSQL database. From what I know, that is working well for them.<br />
<br />
In LSCC, we made a commitment from day one that all our meetings would be technology agnostic, and for the past three years we never had a single meeting that was related to a specific technology. There are a few reasons for that:<br />
<br />
<br />
<ol style="text-align: left;">
<li>We didn't want to alienate a single member of our community</li>
<li>We wanted to focus on the foundations of software development and not in specifics of a language or framework.</li>
<ol>
<li>each developer can choose the language they want to use and who they want to pair with.</li>
</ol>
<li>If the community has monthly meetings and you (as a member) are not interested in the technologies chosen for the meetings, you may not attend the meetings for many months; you may even leave the community.</li>
<li>We are fortunate to be in London, a city that has user groups and technical communities for all the main technologies out there. No point in doing what they already do well.</li>
</ol>
<br />
<br />
There is no right or wrong here and you need to use your gut feeling. Listen to the people coming to the meetings and try to provide what they want. However, at the very beginning, they probably won't know what they want, so you will need to make the call. Technology agnostic has better chances to attract more developers, from all sorts of backgrounds, which in turn will make the community more diverse. And that is exactly what we always wanted.<br />
<br />
<h2 style="text-align: left;">
Focus on learning, sharing, and having fun</h2>
<br />
Learning, sharing, and having fun with like-minded people are the most important things in any technical community. As an organiser, make sure that this is your main focus. Growth is not important. Number of people attending the meetings is not important. Whoever comes is the right people. If everyone enjoys the meetings, they will invite their friends, they will tell other developers, so don't focus on growing your community. That will happen as a side effect.<br />
<br />
<h2 style="text-align: left;">
Associates</h2>
<br />
In LSCC we have the <a href="http://www.meetup.com/london-software-craftsmanship/members/?op=leaders" target="_blank">LSCC Associates</a>. Associates are some of the LSCC core members that I invited to help me with the organisation of the community. They are people that come to the vast majority of our meetings, are extremely passionate, talented, and fully understand the Software Craftsmanship ideology. The difference between them and the organiser and the associates is the level of commitment. Associates help whenever they can while the organiser doesn’t really have this option. Some associates will quickly step up and can easily become co-organisers.<br />
<br />
As the community grows, you, as an organiser, will need help. Also, there is a limit for what you can do; the community needs variety. The community should never be about the organiser. The community should be about the community. Having a good group of people sharing the organisation should be one of your priorities as an organiser.<br />
<br />
We have a separate Google group for the Associates where we discuss everything that is related to the community: ideas for a session, who is going to run it, new companies interested in sponsoring (venue, food, etc), new types of meeting, and many other things. At the beginning you may want to have one or two people to help you. As the community grows, you will need quite a few more.<br />
<br />
Associates bring variety and enthusiasm. They keep the community alive and healthy. LSCC would never be so awesome without all the LSCC Associates.<br />
<br />
<h2 style="text-align: left;">
Good neighbours</h2>
<br />
If there is any other user groups or technical communities in your city, go and speak to them. One of the reasons for the LSCC success is our proximity to other communities. The idea for starting LSCC happened during a conversation I had in one of the London Java Community meetings, and from day one we had the support from the LJC organisers. LJC, back then, already had more than 1000 members and they announced many of our events to the LJC members. We also have a good relationship with other local user groups. In the early days, we made sure that none of our meetings would clash with meetings from other user groups so we all could go to each other meetings.<br />
<br />
<h2 style="text-align: left;">
Protect your community</h2>
<br />
It's your responsibility, as an organiser, to protect your community. As the number of developers grows, you will see many recruiters and marketeers approaching your community. They will try to use the community's mailing list to advertise their conferences, products, companies, etc. Protect your members and the community mailing list. At LSCC we don't allow any recruiters or people that are not directly involved with a software project to join. For that, membership is by approval only, and I do my best make sure that just people that can contribute to the community will join. We ask every member to write a brief description about who they are. We don't accept memberships where people don't write anything about themselves. A community is not a community if every person in the community doesn't have a profile. Currently I decline between 5 to 10 memberships a month. They are normally recruiters and people trying to advertise their stuff. Sometimes I even Google people and search them on LinkedIn to make sure they are really developers.<br />
<br />
There is nothing that the community will gain with people spamming our mailing list. The only thing that will happen is that members will leave the community because of spam.<br />
<br />
<h2 style="text-align: left;">
Have fun</h2>
<br />
I know that there is a lot in this post and maybe I made it sound far more complicated than it really is. Organising a community is a lot of fun and has many benefits. You will learn more than you can ever imagine and you will also be helping many other developers to learn as well. That, on its own, is more than enough reason to start a community.<br />
<br />
Keep it simple and get more people involved. If you follow that, you will have a successful community.<br />
<br />
If you start a Software Craftsmanship community, let us know. All of us from LSCC will be more than happy to help. I wish you all the best with your new community and, above all, I hope you have a loads of fun.<br />
<br />
You can email me at sandromancuso at gmail dot com or find me on Twitter <a href="http://twitter.com/sandromancuso">@sandromancuso</a></div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-3322729946619891762013-08-23T03:26:00.000+01:002013-08-23T03:27:48.358+01:00Test Deafness<div dir="ltr" style="text-align: left;" trbidi="on">
A few months ago I was talking to a musician friend of mine. He is also Brazilian, same age as me, and moved to the UK on the same year I did. As we were talking about music, I mentioned I like punk rock. He said he likes punk rock as well, but as a musician, he listens to a bit of everything. The conversation was going well until he asked me what my favourite bands were. "<a href="http://en.wikipedia.org/wiki/Legi%C3%A3o_Urbana" target="_blank">Legiao Urbana</a>" is my favourite Brazilian band I said. "Seriously?" he said with a puzzled face. "They are rubbish, man."<br />
<br />
As he was a friend (he became an enemy after that stupid comment), I thought to myself: How can I make him suffer for the rest of his life? Luck for him, I remembered that I was not a Brazilian savage anymore. I was British now and I had to act like one: "Oh, are they? Thanks for sharing that with me. Would you mind telling me what your favourite bands are? More tea?" He then named a few bands, including some <span style="background-color: white; font-family: sans-serif; font-size: 12.727272033691406px; line-height: 19.190340042114258px;"><a href="http://en.wikipedia.org/wiki/Forr%C3%B3" target="_blank"><b>Forró</b></a></span> bands. Shock! Horror!! Blasphemy!!! I really wanted to kill him right there. Fuck the British citizenship. How could a guy, that also liked punk rock music, say that the band I liked was rubbish and then name some stupid Forro bands as his favourite bands?<br />
<br />
After quite a long list of swear words pronounced in a very loud tone, I asked him to elaborate. All songs of Legiao Urbana, he said, are played with three or four chords maximum. Their lyrics are great, but they are very poor musicians. The Forro bands are totally the opposite. The lyrics suck but no one cares. Their are great musicians that focus on creating music for people to dance.<br />
<br />
That conversation made me realise something really important. If you are a person like me, good music is related to good and strong lyrics. For a musician like my friend, good music is about the techniques used by other musicians when playing their instruments, regardless of the lyrics. For a person that likes to sing, she may appreciate opera, even if she doesn't have a clue about what the words mean.<br />
<br />
<b><span style="font-size: large;">But what does it have to do with tests?</span></b><br />
<br />
You cannot expect to produce quality code just by <i><b>listening to your test</b></i>. If you don't know what good code looks like, you are pretty much <b><i>test deaf</i></b>. Musicians have a trained ear to listen to each instrument individually while the music is playing. They can also imagine, quite precisely, how different instruments could be combined to create new music. <br />
<br />
Walking around asking other developers to listen to their tests, as if this advice alone would make them produce quality code immediately, doesn't work. It may make us look smart (or at least feel smart) but it does not really help the other developers receiving the advice. It's too vague.<br />
<br />
If we want to produce quality code, we should study the concepts and techniques that lead to it: Domain Driven Design, Clean Code, SOLID principles, design patterns, coupling, cohesion, different programming languages and paradigms, architecture, just to name a few. Once we get a good understanding of all these things, we will have an implied knowledge about what constitutes good code. This implied knowledge is what may cure our <b>test deafness</b>, allowing us to <i>listen to our tests</i> in order to produce quality code. </div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com2tag:blogger.com,1999:blog-8424060401701893376.post-10777194809650564002013-07-30T00:46:00.003+01:002013-07-30T00:53:06.765+01:00My birthday wish list<div dir="ltr" style="text-align: left;" trbidi="on">
<div class="p1">
Today is my birthday. Yay! And since today is all about me, I will choose what I want as a present. As a developer, here's what I want:</div>
<div class="p2">
<br /></div>
<div class="p1">
</div>
<ol style="text-align: left;">
<li>I want developers to be empowered to do whatever they need to do to satisfy the real business needs and delight their customers.</li>
<li>I want developers to be accountable for the decisions they make, and not by decisions that are made for them. </li>
<li>I don't want to see developers going through endless meetings trying to prove why they shouldn't use the technologies or architecture defined by an ivory tower architect. In fact, ivory-tower architects should be an extinct species (visit your nearest National History Museum if you want to see one). </li>
<li>I want developers to know the truth. If a decision was made because of political reasons, please tell us that that is the case. We will still be unhappy but at least we will find it easier to digest. </li>
<li>Although we are happy to justify and explain every technical decision we, the development team, make, we don't want to have any person that is not part of the development team making technical decisions. </li>
<li>I don't want to see developers working with <i>technical</i> people that think that their role is to define the architecture of a project. I want developers to work with people that focus on delivering the simplest solution to a problem; satisfying functional and non-functional requirements. If we can achieve that without writing software, even better. And no, that doesn't mean quick and dirty.</li>
<li>In case we need to write software to solve a business problem, I want developers to craft solutions in a way that changes are embraced and the business will never be slowed down by technical incompetence.</li>
<li>I want developers that can build applications that will provide a good return on investment to the business. I don't want to see applications being decommissioned after a few years because they became a pile of crap; the maintenance cost is so high that it is cheaper to rewrite. </li>
<li>I want to work with developers that are passionate and care about what they do. Every single day I want to speak to my colleagues and learn something new from them, the same way they should learn something new from me. </li>
<li>I want to work with people (not just developers) that embrace changes and provide business agility. I don't want to keep embarrassing myself every time I need to tell stakeholders that the small change they want will take a few months to be done (due to the crap application/architecture/process we have). </li>
<li>I want to work in a place where we can choose the best technology or tool for the job; without being told that we cannot do that because our people don't have the skills. "They need to be trained." (sigh)</li>
<li>Instead of being told that we need to build a new feature or even an entire new application using specific technologies, we would appreciate if we were just given the business requirements. I would love to see that developers are trusted to provide the best solution for the problem.</li>
<li>I would like to see the people behind all the bureaucracy and stupid processes being blamed by the damage they are causing. </li>
<li>I would like to see all the 9-to-5 employees being replaced by just a few passionate, talented, well-paid and empowered professionals. </li>
<li>I wish all companies recognised software development as a full career and not as just the initial steps for management. Yes, this is stupid.</li>
<li>I wish that every organisation paying for a software project understood the principles of Software Craftsmanship and the importance to have real software craftsmen working on their projects. </li>
</ol>
<br />
<div class="p2">
<br /></div>
<div class="p1">
You may be thinking that I'm not being reasonable. After all, my birthday is almost over and of course no one will be able to give me all the things I want today, as a birthday present. You are right. I agree. And because of that, I won't add all the many other wishes I have to the list above. I could go on forever. </div>
<div class="p2">
<br /></div>
<br />
<div class="p1">
The good news for me is that I'm really smart and I always have a plan B. Although I'm a disappointed that I won't get all these things for my birthday this year, my plan is to be a good boy for the rest of the year and maybe Santa will bring me some of these for Xmas. </div>
</div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com1tag:blogger.com,1999:blog-8424060401701893376.post-71012515736625605112012-12-18T14:02:00.000+00:002012-12-18T14:04:51.788+00:00Screencast: Testing and Refactoring Legacy Code<div dir="ltr" style="text-align: left;" trbidi="on">
In this screencast I take a small piece of legacy Java code that contains the most common problems found in much larger legacy code bases. The objective is to first write tests to understand what the code does and then refactor it to make it better. The code contains Singletons, static calls and behaviour that does not belong there. It also has some design issues.<br />
<br />
As an advice, I always recommend that we should never "touch" the production code as we retrofit tests, that means, we should not change it typing into the production file. However, as normally legacy code is not written with testing in mind, sometimes we need to change the production code in order to write tests for it. I address this scenario explaining how we can do that in a very safe way.<br />
<br />
A common question when developers want to make legacy code better is "Where do we start?" I also address that explaining the how the approaches for testing and refactoring legacy code are the opposite from each other. <br />
<br />
Besides a few other things, I also cover the use of code coverage tools to help us testing the code, how often we should be committing, how to fix a possible problem with the design in very small steps and how to stay in the green while refactoring our code.<br />
<br />
Last but not least, I show how our tests and production code be easily written in a way that it captures the business requirements.<br />
<br />
Although it is a bit long, I hope you all enjoy it.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<object class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/_NnElPO5BU0/0.jpg" height="266" width="320"><param name="movie" value="http://www.youtube.com/v/_NnElPO5BU0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" /><param name="bgcolor" value="#FFFFFF" /><param name="allowFullScreen" value="true" /><embed width="320" height="266" src="http://www.youtube.com/v/_NnElPO5BU0?version=3&f=user_uploads&c=google-webdrive-0&app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"></embed></object></div>
<br />
There are two minor things I forgot to do while doing this exercise. Let me know if you spot it. :)</div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com5tag:blogger.com,1999:blog-8424060401701893376.post-90938151234813551242012-12-10T23:38:00.002+00:002012-12-10T23:38:21.949+00:00The Wrong Notion of Time<div dir="ltr" style="text-align: left;" trbidi="on">
No one wakes up in the morning and say "Today I'm gonna screw up. Today I'm gonna piss my boss and all my team mates off writing the worst code I could possibly write". Well, there are always exceptions but normally no one does that. If that is the case, how come Agile projects are now failing? How come do we still have the same old problems?<br /><br />
<div style="text-align: left;">
<b><span style="font-size: large;">A Technical Debt Story</span></b></div>
<div style="text-align: left;">
<br />Some time ago I was in this project and one of the developers chose to work on a brand new feature. For the implementation of this new feature, we did not need to touch any of our existing code, besides very few things just to wire the new feature into the application. After a day or so, I offered to pair with him. Naturally, since I had just joined him, I asked him to give me an overview of what the feature was about. He promptly explained it to me and I asked him to show me where he was so we could continue. After he finished showing the code to me I made a few observations since it was not clear to me that his code was reflecting what needed to be done - according to his previous explanation. Basically, the language the he used to explain me the business feature was not in sync with the language that he had used in the code and I could also see some code that was not really necessary for the implementation of that feature. I also noticed that there were no tests. When I asked him about that he said _It is working now and I may need that extra code in the future. Let's add this refactoring you are proposing and the unit test to the technical debt backlog. I need to finish this feature. How crazy is that? That was a brand new feature. We should be reducing technical debt as we went along instead of adding more of it. However, this developer somehow felt that it was OK to do that. At the end of the day we had a technical debt backlog, didn't we? That was supposedly an Agile team with experienced developers but somehow, in their minds, it was OK to have this behaviour. Perhaps one day someone would look at the technical debt and do something about. Possibly. Maybe. Quite unlikely. Nah, will never gonna happen. <br /> </div>
<div style="text-align: left;">
<b>But we want to do the right thing</b></div>
<div style="text-align: left;">
<br />But we all want to do the right thing. We do not do these things on purpose. However, over the time, I realised that we developers have a wrong notion of time. We think we need to rush all the time to deliver the tasks we committed to. Pressure will always be part of a software developer life and when there is pressure, we end up cutting corners. We do not do that because we are sloppy. We normally do that because we feel that we need to go faster. We feel that we are doing a good job, proving the business the features they want as fast as we can. The problem is that not always we understand the implications of our own decisions.<br /> </div>
<div style="text-align: left;">
<b><span style="font-size: large;">A busy team with no spare time</span></b></div>
<div style="text-align: left;">
<br />I joined this team in a very large organisation. There were loads of pressure and the developers were working really hard. First, it took me days to get my machine set up. The project was a nightmare to configure in our IDEs. We were using Java and I was trying to get my Eclipse to import the project. The project had more than 70 maven projects and modules, with loads of circular dependencies. After a few days, I had my local environment set. The project was using a heavyweight JEE Container, loads of queues and had to integrate with many other internal systems. When pairing with one of the guys (pairing was not common there but I asked them if could pair with them) I noticed that he was playing messages in a queue and looking at logs. I asked him what he was doing and he said that it was not possible to run the system locally so he had to add loads of logs to the code, package, deploy the application in the UAT environment, play XML messages into one of the inbound queues, look at the logs in the console and try to figure out what the application was doing. Apparently he had made a change and the expected message was not arriving in the expected outbound queue. So, after almost twenty minutes of changing the XML message and replaying it into the inbound queue, he had an idea of what the problem could be. So he went back to his local machine, changed a few lines of code, added more logs, changed a few existing ones to print out more information and started building the application again. At this point I asked if he would not write tests for the change and if he had tests for the rest of the application. He then told me that the task he was working on was important so he had to finish it quickly and did not have time to write tests. Then he deployed the new version of the application in UAT again (note that no one else could use the UAT environment while he was doing his tests), played an XML message into the inbound queue and started looking at the logs again. That went on for another two days until the problem was fixed. It turned out that there were some minor logical bugs in the code, things that a unit test would have caught immediately. <br /> </div>
<div style="text-align: left;">
<b>We don't have time but apparently someone else does</b></div>
<div style="text-align: left;">
<br />Imagine the situation above. Imagine an application with a few hundred thousand lines. Now imagine a team of seven developers. Now imagine ten of those teams in five different countries working on the same application. Yes, that was the case. There were some system tests (black box tests) but they used to take four hours to run and quite often they were broken so no one really paid attention to them. Can you imagine the amount of time wasted per developer per task or story. Let's not forget the QA team because apparently testers have all the time in the world. They had to manually test the entire system for every single change in the system. Every new feature added to the system was, of course, making the system bigger causing the system tests to be even slower and QA cycles even longer. Debug time was also getting bigger since each developer was adding more code that all the others would need to debug to understand how things work. Now thing about all the time wasted here, every day, every week, every month. This is all because we developers do not have time. <br /><br />Dedicated Quality Assurance teams are an anti-pattern. Testers should find nothing, zero, nada. Every time a tester finds a bug, we developers should feel bad about it. Every bug found in production is an indication of something that we have not done. Some bugs are related to bad requirements but even then we should have done something about that. Maybe we should have helped our BAs or product owners to clarify them. By no means I am saying that we should not have testers. They can be extremely valuable to explore our applications in unexpected ways that just a human could do. They should not waste their time executing test plans that could be automated by the development team. <br /><br />Business want the features as soon as possible and we feel that it is our obligation to satisfy them - and it is. However, business people look at the system as a whole and so should we. They look at everything and not just the story we are working on. It is our job to remove (automate) all the repetitive work. I still remember, back in the 90ies, when debugging skills was a big criteria in technical interviews. Those days are gone. Although it is important to have debugging skills, we should be unpleasantly surprised whenever we need to resort to it and when it occurs, we need to immediately address that, writing tests and refactoring our code so we never need to do that again. </div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<b><span style="font-size: large;">Using time wisely</span></b></div>
<div style="text-align: left;">
<br />Our clients and/or employers are interested in software that satisfy their needs, that works as specified and is easy to change whenever they change their minds. It is our job to provide that to them. The way we go about satisfying their expectations, normally, it is up to us. Although they may mention things like automated testing and Agile methodologies, what they really want is a good value for their money when it comes to the investment that they are making in a software project. We need to use our (their) time wisely, automating whatever we can - being tests or deployment procedures - instead of thinking that we may not have time to do it. We can always quantify how much time we are spending in repetitive tasks and even get to the extend of showing them how much time is being spent over a period of time in those activities. Before implementing any new feature or task, we should spend some time preparing our system to accept the changes in a nice way, so we can just _slide that in_ with no friction, and making sure that whatever we write can be easily tested and deployed. When estimating our work, we should always take this into account as **part of the time** that will take us to do it instead of having the false impression that we will be going faster if we treat them as a separate task since, chances are, they may never get done and the whole time will be slowed down because of that. The less time we waste manually testing (or waiting for a long automated test suite to run), debugging, dealing with a huge amount of technical debt, trying to get your IDE to work nicely with your fucked up project structure, or fighting to deploy the application, the more time we have to look after the quality of our application and make our clients happy. </div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<i>Note: The teams I mentioned above after a lot of hard work, commitment, support from management and a significant amount of investment (time and money) managed to turn things around and are now among the best teams in the organisation. Some of the teams managed to replace (re-write) an unreliable in-house test suite that used to take over three hours to run with a far more reliable one that takes around 20 minutes. One of the teams is very close to achieve a "one-button" deployment and has an extensive test suite with tests ranging from unit to system (black box) that run in minutes and with code coverage close to 100%. </i></div>
</div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com1tag:blogger.com,1999:blog-8424060401701893376.post-70212300771301471572012-11-11T23:54:00.002+00:002012-11-11T23:59:34.271+00:00Testing legacy code with Golden Master<div dir="ltr" style="text-align: left;" trbidi="on">
As a warm up for <a href="http://scna.softwarecraftsmanship.org/" target="_blank">SCNA</a>, the <a href="http://www.meetup.com/ChicagoSC/" target="_blank">Chicago Software Craftsmanship Community</a> ran a hands-on coding session where developers, working in pairs, should test and refactor some legacy code. For that they used the <a href="https://github.com/sandromancuso/Gilded-Rose-Kata" target="_blank">Gilded Rose kata</a>. You can find links to versions in java, C# and ruby <a href="https://github.com/sandromancuso/Gilded-Rose-Kata" target="_blank">here</a> and for clojure <a href="http://blog.8thlight.com/mike-jansen/2012/09/26/welcome-to-the-gilded-rose-in-clojure.html" target="_blank">here</a>. <br />
<br />
We ran the same session for the <a href="http://www.meetup.com/london-software-craftsmanship" target="_blank">London Software Craftsmanship Community (LSCC)</a> early this year and back then I decided to write my tests BDD-style (I used JBehave for that). You can check my solution <a href="https://github.com/sandromancuso/Gilded-Rose-Kata" target="_blank">here</a>. <br />
<br />
This time, instead of writing unit tests or BDD / Spec By Example to test every branch of that horrible code, I decided to solve it using a test style called Golden Master. <br />
<br />
<b>The Golden Master approach</b><br />
<br />
Before making any change to the production code, do the following:<br />
<ol style="text-align: left;">
<li>Create X number of random inputs, always using the same random seed, so you can generate always the same set over and over again. You will probably want a few thousand random inputs. </li>
<li>Bombard the class or system under test with these random inputs.</li>
<li>Capture the outputs for each individual random input</li>
</ol>
When you run it for the first time, record the outputs in a file (or database, etc). From then on, you can start changing your code, run the test and compare the execution output with the original output data you recorded. If they match, keep refactoring, otherwise, revert back your change and you should be back to green.<br />
<br />
<b>Approval Tests</b><br />
<br />
An easy way to do Golden Master testing in Java (also available to C# and Ruby) is to use <a href="http://approvaltests.sourceforge.net/" target="_blank">Approval Tests</a>. It does all the file handling for you, storing and comparing it. Here is an example:<br />
<br />
<br />
<script src="https://gist.github.com/4056675.js?file=GildedRoseTest.java"></script>
For those not familiar with the kata, after passing a list of items to the GildedRose class, it will iterate through them and according to many different rules, it will change their "sellIn" and "quality" attributes.<br />
<br />
I've made a small change in the Item class, adding a automatically generated toString() method to it:<br />
<script src="https://gist.github.com/4056755.js?file=Item.java"></script>
The first time the test method is executed, the line:<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
Approvals.verify(getStringRepresentationFor(items));</div>
<br />
will generate a text file, in the same folder where the test class is, called: <span style="font-family: "Courier New",Courier,monospace;">GildedRoseTest.should_generate_update_quality_output.received.txt</span>. That mean, <testclass>.<testmethod>.received.txt</testmethod></testclass><br />
<br />
ApprovalTests then will display the following message in the console:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">To approve run : mv /Users/sandromancuso/development/projects/java/gildedrose_goldemaster/./src/test/java/org/craftedsw/gildedrose/GildedRoseTest.should_generate_update_quality_output.received.txt /Users/sandromancuso/development/projects/java/gildedrose_goldemaster/./src/test/java/org/craftedsw/gildedrose/GildedRoseTest.should_generate_update_quality_output.approved.txt</span><br />
<br />
Basically, after inspecting the file, if we are happy, we just need to change the <span style="font-family: "Courier New",Courier,monospace;">.received</span> with <span style="font-family: "Courier New",Courier,monospace;">.approved</span> to approve the output. Once this is done, every time we run the test, ApprovalTests will compare the output with the approved file.<br />
<br />
Here is an example of how the file looks like:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">Item [name=Aged Brie, sellIn=-23, quality=-44]</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Item [name=Elixir of the Mongoose, sellIn=-9, quality=45]</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Item [name=Conjured Mana Cake, sellIn=-28, quality=1]</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Item [name=Aged Brie, sellIn=10, quality=-2]</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Item [name=+5 Dexterity Vest, sellIn=31, quality=5] </span><br />
<br />
Now you are ready to rip the GildedRose horrible code apart. Just make sure you run the tests every time you make a change. :)<br />
<b>Infinitest</b><br />
<br />
If you are using Eclipse or IntelliJ, you can also use <a href="http://infinitest.github.com/" target="_blank">Infinitest</a>. It automatically runs your tests every time you save a production or test class. It is smart enough to run just the relevant tests and not the entire test suite. In Eclipse, it displays a bar at the bottom-left corner that can be red, green or yellow (in case there are compilation errors and the tests can't be run).<br />
<br />
With this, approach, refactoring legacy code becomes a piece of cake. You make a change, save it, look at the bar at the bottom of the screen. If it is green, keep refactoring, if it is red, just hit CTRL-Z and you are back in the green. Wonderful. :)<br />
<br />
<b>Thanks</b><br />
<br />
Thanks to <a href="https://twitter.com/roberttaylor426" target="_blank">Robert Taylor</a> and <a href="https://twitter.com/balopat" target="_blank">Balint Pato</a> for showing me this approach for the first time in one of the <a href="http://www.meetup.com/london-software-craftsmanship" target="_blank">LSCC</a> meetings early this year. It was fun to finally do it myself. <br />
<div>
<br /></div>
</div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com5tag:blogger.com,1999:blog-8424060401701893376.post-67983797233098900612012-08-15T04:08:00.001+01:002012-12-04T08:05:49.571+00:00The best approach to software development<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<br />
Today, talking about doing a big design up-front
(BDUF) sounds a bit ridiculous, right? Who would do that? That's not craftsmanship, is it? <br />
<br />
However, in the past, that would be considered the norm. Writing requirement documents, drawing
architectural and very low level detail diagrams was the right thing to do. Well, that’s what very
smart guys proposed on the <a href="http://homepages.cs.ncl.ac.uk/brian.randell/NATO/nato1968.PDF">1968 NATO
Software Engineering Conference</a> and it worked for NASA and the US
Department of Defense. I’m sure they know what they are doing and if it works
for them, it will definitely work for our small CRUD application or one page
website. And then it happened. It became a religion and the majority of projects in the following decades were developed like that.<br />
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
No, but not nowadays. We've learned the lesson, right? We wouldn't make this mistake again. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
After watching a few talks in conferences and <a href="http://www.infoq.com/">InfoQ</a>, we understood that this is not a good thing. We’ve
also read in some books that we should do <a href="http://en.wikipedia.org/wiki/Test-driven_development" target="_blank">TDD</a>. The design should emerge from tests.
</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
And of course, we should adopt an Agile methodology as
well. Let’s adopt <a href="http://en.wikipedia.org/wiki/Scrum_%28development%29" target="_blank">Scrum</a> to start with. There are many books about it,
certifications and even entire conferences dedicated to it. Of course we should
adopt TDD an Scrum because that’s the best approach to manage and develop and software.
</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Oh, but what about all this <a href="http://en.wikipedia.org/wiki/Lean_software_development" target="_blank">lean</a> stuff? Eliminate waste,
limit work in progress, <a href="http://en.wikipedia.org/wiki/System_thinking" target="_blank">system thinking</a>, <a href="http://en.wikipedia.org/wiki/Theory_of_constraints" target="_blank">theory of constrains</a>, <a href="http://en.wikipedia.org/wiki/Kanban" target="_blank">Kanban</a>. I heard
it worked really well for Toyota so we should definitely do that as well. Why? Jesus,
you just don’t get it. Of course that’s best approach to manage and develop
software.</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
God, how could I forget? I was also told that I really should
speak to my customer. We should really discuss the requirements so we can have
a better understanding of what we should build. Are you using <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development" target="_blank">BDD</a>? No!!! Wow!
How can you develop software without that? Why should you use it? The answer is
simple. That’s the best approach to manage and develop software. Don’t tell me
that you thought that BDD was a testing tool. You are so yesterday. That was
version one. <a href="http://dannorth.net/2012/05/31/bdd-is-like-tdd-if/" target="_blank">BDD version three</a> is all about communication. It's about software development done right. Yes, I know it sounds
alien but apparently we are supposed to speak to people. God, how on Earth we haven’t
thought about that before? How did we develop software all these years? If you don’t use BDD, you are just doing it wrong. Why?
Because that’s the best approach to manage and develop software. Duh!</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Outside-In TDD, Inside-Out TDD, ATDD, Classic TDD, <a href="http://codemanship.co.uk/parlezuml/blog/?postid=987" target="_blank">London School TDD</a>? Really?
Are you still discussing that? Don’t tell me that we you are still writing
tests. What? Why are you wasting time writing unit tests? It doesn’t make sense
any more. You should <a href="http://lizkeogh.com/category/spike-and-stabilize/" target="_blank">spike and stabilize</a>. What if you don’t know what you are
doing or where you are going? What if you just want to explore your options?
Why are you writing tests? Oh, I get it. You were told that this was the best approach to manage and develop software. Nah, forget that. Unit tests are for
losers. We write small services and just monitor them. If they are wrong, we
just throw them away and re-write. And THAT is the best way to manage and
develop software. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Architecture and design patterns? What??? Who are you? My
grandfather? Scrap that. That’s for programmers from the 80ies and 90ies. In the real
world we have our design emerging from tests. No, stupid. Not using normal TDD.
God, which planet do you live? We use <a href="http://cumulative-hypotheses.org/2011/08/30/tdd-as-if-you-meant-it/">TDD
As If You Meant It</a>. We use this technique and PRESTO, the design emerges
and evolves nicely throughout the life span of the project regardless of how many developers, teams and design skills. Every one can see code smells, right?</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
And what about <a href="http://en.wikipedia.org/wiki/Domain-driven_design" target="_blank">DDD</a>? Domain Driven what? Nah, never heard about it. Hmm.. hold on. I think I heard something about it many years ago, but probably it was not important enough otherwise we would have more people today saying that DDD is the best approach to manage and develop software. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Noooo. No no no no. No, I didn't hear that. Get out of here. Did you just say that you are still using an Object-Oriented language? <a href="http://en.wikipedia.org/wiki/Statically_typed#Static_typing" target="_blank">STATICALLY-TYPED</a>???? No, sorry. This conversation is a waste of my time. It's because of people like you that our industry is shit. The only way for this conversation to get even worse is if you tell me that you still use a relational database. Haven't you heard that functional programming is a MUST DO and just retards and programmers from the 80ies and 90ies use relational databases. <a href="http://en.wikipedia.org/wiki/Functional_programming" target="_blank">Functional languages</a>, <a href="http://en.wikipedia.org/wiki/NoSQL" target="_blank">NoSQL databases</a>... Repeat with me. Functional languages, NoSQL databases. What a douche bag. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Ah, trying to be a smart ass? Yeah, functional programming appeared long ago in the 50ies and developers in the 60ies and 70ies preferred to use OO instead. But you don't know why, do you? DO YOU? They did use OO because they were a bunch of hippies that didn't take anything seriously. They were that sort of people that went to <a href="http://en.wikipedia.org/wiki/Woodstock" target="_blank">Woodstock</a>, got high on LSD and had brain damage after that. No, don't take this whole OO stuff seriously. We are finally getting back to reality now. Functional programming and NoSQL databases are definitely the best approach for software development.</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
<b>Dogmatism, religion, context, curiosity, inquiring mind and pragmatism</b></div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Before I conclude, I just want to clarify that by no means I'm criticizing any person or group of people behind some of the methodologies, technologies or techniques mentioned above. These people have done an amazing job thinking, practicing and sharing their own ideas of how software development could be done in a better way and for that we should all be grateful. Our industry if definitely better with their contribution.</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
My main criticism here is about how the vast majority of developers react to all these things. It is not just because someone, somewhere wrote a book, recorded a video or gave a talk in a conference about something that it will make that thing right, in all contexts. Quite often, we fail to question things just because the people promoting it are relatively well known. We fail to understand the context where a methodology, technology or technique should be best suitable for. We fail, quite often, to use our own judgement because of the fear to be ridiculed by our colleagues. We should stop being dogmatic and religious about things. This just leads to stupid decisions. Doing things for the sake of doing or because someone else said so is just plain wrong and stupid. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Being a good developer means to be inquisitive, curious and pragmatic. Never religious. Never dogmatic. Curious means that we should be eager to learn about all the things mentioned above and many many more. Inquisitive means that we should investigate and question all the things we learn. Pragmatic means that we should choose the right tools, being technologies, methodologies or techniques, for the job.</div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Context matters. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Whenever you see people saying that we should or shouldn't do something, ask them why. Ask them about the context where they tried to do (or not to do) what they are saying. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Software development is not the same thing of producing cars. Once the car is ready, you don't go back to the manufacturer and ask them to add another wheel or put the engine somewhere else. Developing software for expensive hardware is not the same thing as developing a simple web application with two pages. Hardware has an specification that you need to code against. Quite often, you don't even have access to the hardware because it is just not built yet. The cost of a bug in production is not the same for all applications. The cost of a few bugs in a social networking or cooking website can be very different from the cost of a few bugs in a trading or financial system processing millions of transactions per day. Working with a small team, every one co-located and with easy access to customers is very different from working on a project with 10+ teams spread in 5 countries and different timezones. </div>
<div class="MsoPlainText">
<br /></div>
<div class="MsoPlainText">
Read and learn as much as you can. However, don't assume that everything you read or watch applies in every context. Make informed decisions and trust your instincts.<br />
<br />
The bad news is that there is no best approach to software development. Maximum we could say is that there are certain technologies, methodologies and techniques that are more suitable to a specific context.<br />
<br />
In case you are really trying to find the best approach to software development in general, I hope you don't get too frustrated and good luck with that. If you ever find it, please let us know. It's always interesting to know about different approaches. Maybe unicorns really exist. Who knows?<br />
<br />
<br />
<br />
<i>This post was inspired by conversations during many <a href="http://www.meetup.com/london-software-craftsmanship" target="_blank">London Software Craftsmanship Community (LSCC)</a> Round-table meetings, conversations during <a href="http://www.socrates-conference.de/" target="_blank">SoCraTes 2012</a> and also conversations with colleagues at work. Thanks everyone for that.</i></div>
</div>
Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com27tag:blogger.com,1999:blog-8424060401701893376.post-51808944291870186622012-06-09T23:05:00.000+01:002012-06-09T23:05:09.821+01:00Test-driving Builders with Mockito and Hamcrest<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div class="p1">
A lot of people asked me in the past if I test getters and setters (properties, attributes, etc). They also asked me if I test my builders. The answer, in my case is it depends.</div>
<div class="p2">
<br /></div>
<div class="p1">
When working with legacy code, I wouldn’t bother to test data structures, that means, objects with just getters and setters, maps, lists, etc. One of the reasons is that I never mock them. I use them as they are when testing the classes that uses them.</div>
<div class="p1">
For builders, when they are used just by test classes, I also don’t unit test them since they are used as “helpers” in many other tests. If they have a bug, the tests will fail.</div>
<div class="p1">
In summary, if these data structures and builders already exist, I wouldn’t bother retrofitting test for them.</div>
<div class="p2">
<br /></div>
<div class="p1">
But now let’s talk about doing TDD and assume you need a new object with getters and setters. In this case, yes, I would write tests for the getters and setters since I need to justify their existence writing my tests first.</div>
<div class="p2">
<br /></div>
<div class="p1">
In order to have a rich domain model, I normally tend to have business logic associated with the data and have a richer domain model. Let’s see the following example.</div>
<div class="p2">
<br /></div>
<div class="p1">
In the real life, I would be writing on test at a time, making them pass and refactor. For this post, I’ll just give you the full classes for clarity’s sake. First let’s write the tests:</div>
<div class="p2">
<br /></div>
<div class="p1">
<script src="https://gist.github.com/2902641.js?file=TradeTest.java">
</script></div>
<div class="p2">
<br /></div>
<div class="p1">
Now the implementation:<br />
<br />
<script src="https://gist.github.com/2902653.js?file=Trade.java">
</script><br />
This case is interesting since the <span style="font-family: 'Courier New', Courier, monospace;">Trade</span> object has one property called <span class="s1" style="font-family: 'Courier New', Courier, monospace;">inboundMessage</span> with respective getters and setters and also uses a collaborator (<span class="s1" style="font-family: 'Courier New', Courier, monospace;">reportabilityDecision</span>, injected via setter) in its <span class="s1" style="font-family: 'Courier New', Courier, monospace;">isReportable</span> business method.<br />
<br />
A common approach that I’ve seen many times to “test” the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">setReportabilityDecision</span> </span>method is to introduce a <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">getReportabilityDecision</span> </span>method returning the <span class="s2" style="font-family: 'Courier New', Courier, monospace;">reportabilityDecision</span><span class="s3"> </span>(collaborator) object.<br />
<br />
<div class="p1">
This is definitely the wrong approach. Our objective should be to test how the collaborator is used, that means, if it is invoked with the right parameters and if whatever it returns (if it returns anything) is used. Introducing a getter in this case does not make sense since it does not guarantee that the object, after had the collaborator injected via setter, is interacting with the collaborator as we intended.<br />
<br />
<i>As an aside, when we write tests that are about how collaborators are going to be used, defining their interface, is when we are using TDD as a design tool and not just simply as a testing tool. I’ll cover that in a future blog post.</i><br />
<br />
<div class="p1">
OK, now imagine that this trade object can be created in different ways, that means, with different reportability decisions. We also would like to make our code more readable and we decide to write a builder for the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">Trade</span></span> object. Let’s also assume, in this case, that we want the builder to be used in the production and test code as well. </div>
<div class="p1">
In this case, we want to test drive our builder. </div>
<div class="p2">
<br /></div>
<div class="p1">
Here is an example that I normally find when developers are test-driving a builder implementation.<br />
<br />
<script src="https://gist.github.com/2902698.js?file=TradeBuilderTest_v1.java">
</script><br />
<div class="p1">
Now let’s have a look at these tests. </div>
<div class="p1">
The good news is, the tests were written in the way developers want to read them. That also means that they were “designing” the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeBuilder</span></span> public interface (public methods). </div>
<div class="p1">
The bad news is how they are testing it.</div>
</div>
<br />
<br />
<div class="p1">
If you look closer, the tests for the builder are almost identical to the tests in the <span style="font-family: 'Courier New', Courier, monospace;">TradeTest</span> class. </div>
<div class="p2">
<br /></div>
<div class="p1">
You may say that it is OK since the builder is creating the object and the tests should be similar. The only different is that in the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeTest</span></span> we instantiate the object by hand and in the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeBuilderTest</span></span> we use the builder to instantiate it, but the assertions should be the same, right? </div>
<div class="p2">
<br /></div>
<div class="p1">
For me, firstly we have duplication. Secondly, the <span style="font-family: 'Courier New', Courier, monospace;">TradeBuilderTest</span> doesn’t show it’s real intent. </div>
<div class="p2">
<br /></div>
<div class="p1">
After many refactorings and exploring different ideas, while pair-programming with one of the guys in my team we came up with this approach:</div>
<div class="p1">
<br /></div>
<div class="p1">
<script src="https://gist.github.com/2902713.js?file=TradeBuilderTest_v2.java">
</script></div>
<div class="p1">
So now, the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeBuilderTest</span></span> express what is expected from the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeBuilder</span></span>, that means, the side effect when the <span class="s1">build</span> method is called. We want it to create a <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">Trade</span></span> and set its attributes. There are no duplications with the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeTest</span></span>. It is left to the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeTest</span></span> to guarantee the correct behavior of the <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">Trade</span></span> object.</div>
<div class="p2">
<br /></div>
<div class="p1">
For completion’s sake, here is the final <span class="s1"><span style="font-family: 'Courier New', Courier, monospace;">TradeBuider</span></span> class:<br />
<br />
<script src="https://gist.github.com/2902728.js?file=TradeBuilder.java">
</script><br />
<br />
The combination of <a href="http://code.google.com/p/mockito/" target="_blank">Mockito</a> and <a href="http://code.google.com/p/hamcrest/" target="_blank">Hamcrest</a> is extremely powerful, allowing us to write better and more readable tests.</div>
<br /></div>
</div>
</div>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com2tag:blogger.com,1999:blog-8424060401701893376.post-88874175469442173512012-05-18T17:29:00.000+01:002012-05-18T22:31:17.768+01:00Testing multiple properties with single assertion<div dir="ltr" style="text-align: left;" trbidi="on">
Every time I was trying to test an object's properties I was neither satisfied writing very verbose tests nor in using some of the out of the box hamcrest matchers. Although using the matchers was a big help, I never managed to make them read the way I wanted. <br />
<br />
Another thing that was very important to me, I wanted to have a single assertion per method and a very descriptive description if the test did not pass.<br />
<br />
I've decided to write my own matcher and hopefully it will be useful to other people. So, that's what I've done:<br />
<h2>
<a href="https://github.com/sandromancuso/bean-property-matcher" target="_blank">BeanMatcher </a></h2>
Hamcrest matcher to match multiple attributes of an object within a single assertion.<br />
<h2>
<a class="anchor" href="https://github.com/sandromancuso/bean-property-matcher#how-to-use-it" name="how-to-use-it"></a>How to use it</h2>
<br />
<script src="https://gist.github.com/2725577.js?file=BeanMatcher_example1.java">
</script><b>NOTE</b>: Make sure you are using <span class="n" style="font-family: "Courier New",Courier,monospace;">org</span><span class="o" style="font-family: "Courier New",Courier,monospace;">.</span><span class="na" style="font-family: "Courier New",Courier,monospace;">hamcrest</span><span class="o" style="font-family: "Courier New",Courier,monospace;">.</span><span class="na" style="font-family: "Courier New",Courier,monospace;">MatcherAssert</span><span class="o" style="font-family: "Courier New",Courier,monospace;">.</span><span class="na" style="font-family: "Courier New",Courier,monospace;">assertThat</span><span class="o"> instead of the JUnit one.</span><br />
<br />
If you run this test, you will get a message like<br />
<script src="https://gist.github.com/2725741.js?file=BeanMatcher_error1.java">
</script>
<br />
Now, change the age check to
<br />
<blockquote class="tr_bq">
<pre> property("age", <b>greaterThan(60)</b>)
</pre>
</blockquote>
And you should get:<br />
<br />
<script src="https://gist.github.com/2725730.js?file=gistfile1.txt">
</script>
<br />
<h2 style="text-align: left;">
Testing object graphs</h2>
You can also do this<br />
<br />
<script src="https://gist.github.com/2725613.js?file=BeanMatcher_example2.java">
</script>I use a combination of two matchers to do that:<br />
- <a href="https://github.com/sandromancuso/bean-property-matcher/blob/master/src/main/java/org/craftedsw/beanpropertymatcher/matcher/BeanMatcher.java" target="_blank">BeanMatcher</a>: Provides the "<span style="font-family: "Courier New",Courier,monospace;">has</span>" method responsible to group all the property matchers. <br />
- <a href="https://github.com/sandromancuso/bean-property-matcher/blob/master/src/main/java/org/craftedsw/beanpropertymatcher/matcher/BeanPropertyMatcher.java" target="_blank">BeanPropertyMatcher</a>: Provides the "<span style="font-family: "Courier New",Courier,monospace;">property</span>" method.<br />
<br />
I expect to make more changes to them, so for the most up-to-date version, please check <a href="https://github.com/sandromancuso/bean-property-matcher" target="_blank">BeanMatcher</a> on <a href="https://github.com/sandromancuso" target="_blank">my github account</a>. <br />
<br />
Enjoy!!!</div>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-38522906763343956132012-03-26T16:42:00.000+01:002012-03-26T16:48:38.046+01:00Extract, Inject, Kill: Breaking hierarchies (part 3)<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<i>In <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking.html">part one</a> I explain the main idea behind this approach and in <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_06.html">part two</a> I start this example. Please read parts <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking.html">one</a> and <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_06.html">two</a> before reading this post </i><br />
<br />
Although the main ideas of Extract, Inject, Kill is already expressed, it's good to finish the <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_06.html">exercise</a> just for completion's sake.<span style="font-size: small;"> Here is where we stopped:</span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-lHrDKs7xC5k/T24Ub4EE6LI/AAAAAAAAAOA/zSSo5Ho4jk0/s1600/hierarchies_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="http://1.bp.blogspot.com/-lHrDKs7xC5k/T24Ub4EE6LI/AAAAAAAAAOA/zSSo5Ho4jk0/s640/hierarchies_2.png" width="640" /></a></div>
<span style="font-size: small;">Let's have a look at the <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span>, that now
is the only concrete class at the bottom of our hierarchy. </span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<script src="https://gist.github.com/2184846.js?file=VoucherPricingService.java">
</script>
<br />
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Note that it uses the <span style="font-family: 'Courier New', Courier, monospace;">VoucherService</span> class to calculate
the voucher value. </span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<script src="https://gist.github.com/2184900.js?file=VoucherService.java">
</script>
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Before anything, let's write some tests to
<span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span>.<span style="font-family: 'Courier New', Courier, monospace;">java</span></span><br />
<br /></div>
<script src="https://gist.github.com/2184972.js?file=VoucherPricingServiceTest.java">
</script>
<br />
<div style="margin-bottom: 0cm; text-decoration: none;">
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br />
<br />
<span style="font-size: small;">Once thing to notice is that the <span style="font-family: 'Courier New', Courier, monospace;">User</span> parameter is not
used for anything. So let's remove it.</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Now it is time to user the Extract, Inject, Kill on the
<span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span>. Let's <b>Extract</b> the content of the
<span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService.applyAdditionalDiscounts(double, String)</span> method
and add it to a class called <span style="font-family: 'Courier New', Courier, monospace;">VoucherDiscountCalculation</span>. Let's call
the method <span style="font-family: 'Courier New', Courier, monospace;">calculateVoucherDiscount()</span>. Of course, let's do that
writing our tests first. They need to test exactly the same things
that are tested on
<span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService.applyAdditionalDiscounts(double, String)</span>. We
also take the opportunity to pass the <span style="font-family: 'Courier New', Courier, monospace;">VoucherService</span> object into the
constructor of <span style="font-family: 'Courier New', Courier, monospace;">VoucherDiscountCalculation</span>.</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal;">
<script src="https://gist.github.com/2185062.js?file=VoucherDiscountCalculationTest.java">
</script>
</div>
<div style="font-weight: normal;">
<script src="https://gist.github.com/2185082.js?file=VoucherDiscountCalculation.java">
</script>
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">If you noticed, when doing the extraction, we took the
opportunity to give proper names to our new classes and methods and
also to pass their essential dependencies to the constructor instead
of using method injection.</span></div>
<div style="margin-bottom: 0cm; text-decoration: none;">
<div style="font-weight: normal;">
<span style="font-size: small;"> </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Let's now change the code in the <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span>
to use the new <span style="font-family: 'Courier New', Courier, monospace;">VoucherDiscountCalculation</span> and see if all the tests
still pass.</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal;">
<script src="https://gist.github.com/2185141.js?file=VoucherPricingService_v2.java">
</script>
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="margin-bottom: 0cm; text-decoration: none;">
<div style="font-weight: normal;">
<span style="font-size: small;">Cool. All the tests still pass, meaning that we have the
same behaviour, but now in the <span style="font-family: 'Courier New', Courier, monospace;">VoucherDiscountCalculation</span> class, and
we are ready to move to the <b>Inject</b> stage. </span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Let's now <b>inject</b> <span style="font-family: 'Courier New', Courier, monospace;">VoucherDiscountCalculation</span> into
<span style="font-family: 'Courier New', Courier, monospace;">PricingService</span>, that is the top class in the hierarchy. As always, let's add a test that will test this new
collaboration.</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal;">
<script src="https://gist.github.com/2185171.js?file=PricingServiceTest_v2.java">
</script>
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">And here is the changed <span style="font-family: 'Courier New', Courier, monospace;">PriningService</span>.</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
</div>
<div style="font-weight: normal;">
<br /></div>
<div style="font-weight: normal;">
<script src="https://gist.github.com/2185185.js?file=PricingService_v2.java">
</script>
</div>
<div style="margin-bottom: 0cm; text-decoration: none;">
<div style="font-weight: normal;">
<span style="font-size: small;">Now it is time to <b>kill</b> the <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span> class
and <b>kill</b> the <span style="font-family: 'Courier New', Courier, monospace;">PricingService.applyAdditionalDiscounts(double total,
String voucher)</span> template method, since it is not being used anymore.
We can also <b>kill</b> the <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingServiceTest</span> class and fix the
<span style="font-family: 'Courier New', Courier, monospace;">PricingServiceTest</span> removing the <span style="font-family: 'Courier New', Courier, monospace;">applyAdditionalDiscounts()</span> method
from the testable class. </span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">So now, of course, we don't have a concrete class in our
hierarchy anymore, since the <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span> was the only one.
We can now safely promote <span style="font-family: 'Courier New', Courier, monospace;">UserDiscountPricingService</span> to concrete. </span>
</div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">That is now how our object graph looks like:</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div class="separator" style="clear: both; font-weight: normal; text-align: center;">
<a href="http://1.bp.blogspot.com/-mL333NK2Wj4/T24SM3PZrlI/AAAAAAAAAN4/te0Q8t2IyoA/s1600/class_hierarchies_v4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="285" src="http://1.bp.blogspot.com/-mL333NK2Wj4/T24SM3PZrlI/AAAAAAAAAN4/te0Q8t2IyoA/s400/class_hierarchies_v4.png" width="400" /></a></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small; font-weight: normal;">Our hierarchy is another level short. The only thing we need to do now is to apply </span> <b style="font-weight: normal;">Extract, Inject, Kill </b>once again, <b>extracting</b> the logic inside <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">UserDiscountPricingService</span> into another class (e.g. <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">UserDiscountCalculation</span>), <b>inject</b> <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">UserDiscountCalculation</span> into <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">PricingService</span>, finally <b>kill</b> <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">UserDiscountPricingService</span> and the <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">calculateDiscount(User user)</span> template method. <span style="font-family: 'Courier New', Courier, monospace; font-weight: normal;">UserDiscountPricingService</span>, </div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Since the approach was described before, there is no need to go step by step anymore. Let's have a look at the final result.</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">Here is the diagram representing where we started:</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br /></div>
<div class="separator" style="clear: both; font-weight: normal; text-align: center;">
<a href="http://1.bp.blogspot.com/-u9OQ7OgLTic/T24VFbKDpmI/AAAAAAAAAOI/82EUFtwoXAM/s1600/hierarchies.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="http://1.bp.blogspot.com/-u9OQ7OgLTic/T24VFbKDpmI/AAAAAAAAAOI/82EUFtwoXAM/s640/hierarchies.png" width="640" /></a></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;"> After the last Extract, Inject, Kill refactoring, this is what we've got:</span></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://3.bp.blogspot.com/-peXBqjyk22k/T3CL90EnatI/AAAAAAAAAOQ/6CK_S_-n0xQ/s1600/hierarchies_classes_final.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="371" src="http://3.bp.blogspot.com/-peXBqjyk22k/T3CL90EnatI/AAAAAAAAAOQ/6CK_S_-n0xQ/s640/hierarchies_classes_final.png" width="640" /></a></div>
<br /></div>
<div style="font-weight: normal; margin-bottom: 0cm; text-decoration: none;">
<span style="font-size: small;">The cool thing about the final model pictured above is that now we don't have any abstract classes anymore. All classes and methods are concrete and every single class is independently testable. </span><br />
<span style="font-size: small;"><br /></span><br />
<span style="font-size: small;">That's how the final PricingService class looks like:</span><br />
<script src="https://gist.github.com/2206012.js?file=PricingService_final.java">
</script>
<span style="font-size: small;"><br /></span><br />
For a full implementation of the final code, please look at <a href="https://github.com/sandromancuso/breaking-hierarchies">https://github.com/sandromancuso/breaking-hierarchies</a><br />
<br />
<i>Note: For this three part blog post I used three different approaches to drawing UML diagrams. By hand, using <a href="http://argouml.tigris.org/">ArgoUML</a> and <a href="http://astah.net/editions/community">Astah community edition</a>. I'm very happy with the latter. </i></div>
</div>
</div>
</div>
<div style="font-weight: normal;">
<span style="font-size: small;"><span style="font-family: 'Courier New', Courier, monospace;"> </span></span></div>
</div>
</div>
</div>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-55425039231275692592012-03-06T20:26:00.003+00:002012-03-26T16:59:27.198+01:00Extract, Inject, Kill: Breaking hierarchies (part 2)<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<i>In <a href="http://craftedsw.blogspot.com/2012/03/extract-inject-kill-breaking.html">part 1</a> of this post I explain the problems of using the template method in deep class hierarchies and how I went to solve it. Please <a href="http://craftedsw.blogspot.com/2012/03/extract-inject-kill-breaking.html">read it</a> before reading this post.</i><br />
<br />
Here is a more concrete example in how to break deep hierarchies using the Extract, Inject, Kill approach. Imagine the following hierarchy.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://1.bp.blogspot.com/-8cDWuDHaiog/T1ZV4Vdxw3I/AAAAAAAAANM/V3gAkhLzVyg/s1600/hierarchies.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="http://1.bp.blogspot.com/-8cDWuDHaiog/T1ZV4Vdxw3I/AAAAAAAAANM/V3gAkhLzVyg/s640/hierarchies.png" width="640" /></a></div>
</div>
<script src="https://gist.github.com/1987930.js?file=Original_hierarchy.java">
</script></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div style="margin-bottom: 0cm;">
Let's start with the
<span style="font-family: 'Courier New', Courier, monospace;">StandardPricingService</span>. First, let's write some tests:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<script src="https://gist.github.com/1988024.js?file=StandardPricingServiceTest.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
Note that I used a small trick here, extending the <span style="font-family: 'Courier New', Courier, monospace;">StandardPricingService</span> class inside the test class so I could have access to the protected method. We should not use this trick in normal circumstances. Remember that if you feel the need to test protected or private methods, it is because your design is not quite right, that means, there is a domain concept missing in your design. In other words, there is a class crying to come out from the class you are trying to test.<br />
<br />
<div style="margin-bottom: 0cm;">
Now, let's do the step one in our
Extract, Inject, Kill strategy. <b>Extract</b> the content of the
<span style="font-family: 'Courier New', Courier, monospace;">calculateProductPrice</span>() method into another class called
<span style="font-family: 'Courier New', Courier, monospace;">StandardPriceCalculation</span>. This can be done automatically using
IntelliJ or Eclipse. After a few minor adjusts, that's what we've
got.
<br />
<br /></div>
</div>
<script src="https://gist.github.com/1988339.js?file=StandardPriceCalculation.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
And the <span style="font-family: 'Courier New', Courier, monospace;">StandardPriceService</span> now looks
like this:<br />
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988369.js?file=StandardPricingService_v2.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
All your tests should still pass.<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
As we create a new class, let's add
some tests to it. They should be the same tests we had for the
<span style="font-family: 'Courier New', Courier, monospace;">StandardPricingService</span>.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988383.js?file=StandardPriceCalculationTest.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Great, one sibling done. Now let's do
the same thing for the <span style="font-family: 'Courier New', Courier, monospace;">BoxingDayPricingService</span>.<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988400.js?file=BoxingDayPricingServiceTest.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
Now let's extract the behaviour into
another class. Let's call it <span style="font-family: 'Courier New', Courier, monospace;">BoxingDayPricingCalculation</span>.<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988420.js?file=BoxingDayPriceCalculation.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
The new <span style="font-family: 'Courier New', Courier, monospace;">BoxingDayPriceService</span> is now<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988466.js?file=BoxingDayPricingService_v2.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
We now need to add the tests for the
new class.<br />
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988493.js?file=BoxingDayPriceCalculationTest.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
Now both
<span style="font-family: 'Courier New', Courier, monospace;">StandardPricingService</span> and <span style="font-family: 'Courier New', Courier, monospace;">BoxingDayPricingService</span> have no
implementation of their own. The only thing they do is to delegate
the price calculation to <span style="font-family: 'Courier New', Courier, monospace;">StandardPriceCalculation</span> and
<span style="font-family: 'Courier New', Courier, monospace;">BoxingDayPriceCalculation</span> respective. Both price
calculation classes have the same public method, so now let's extract
a <span style="font-family: 'Courier New', Courier, monospace;">PriceCalculation</span> interface and make them both implement it.<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988534.js?file=PriceCalculation.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
<br />
<div style="margin-bottom: 0cm;">
Awesome. We are now ready for the Inject part of Extract, Inject, Kill approach. We just need to <b>inject</b> the desired behaviour into the parent (class that defines the template method). The
<span style="font-family: 'Courier New', Courier, monospace;">calculateProductPrice</span>() is defined in the <span style="font-family: 'Courier New', Courier, monospace;">PricingService</span>, the class
at the very top at the hierarchy. That's where we want to inject the
<span style="font-family: 'Courier New', Courier, monospace;">PriceCalculation</span> implementation. Here is the new version:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<br /></div>
</div>
<script src="https://gist.github.com/1988584.js?file=PricingService_v2.java">
</script>
<br />
<div style="margin-bottom: 0cm;">
Note that the template method <span style="font-family: 'Courier New', Courier, monospace;">calculateProductPrice</span>() was removed from the <span style="font-family: 'Courier New', Courier, monospace;">PricingService</span>, since its behaviour is now being injected instead of implemented by sub-classes.<br />
<br />
<div style="margin-bottom: 0cm;">
As we are here,
let's write some tests for this last change, checking if the PricingService is invoking the PriceCalculation correctly. </div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Great. Now we are
ready for the last bit of the Extract, Inject, Kill refactoring.
Let's <b>kill</b> both <span style="font-family: 'Courier New', Courier, monospace;">StandardPricingService</span> and
<span style="font-family: 'Courier New', Courier, monospace;">BoxingDayPricingService</span> child classes. </div>
</div>
<div style="margin-bottom: 0cm;">
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
The <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span>, now the deepest class in the hierarchy, can be promoted to concrete class. Let's have
another look at the hierarchy:</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://2.bp.blogspot.com/-bqgvpc4HbFw/T1ZuokAaBjI/AAAAAAAAANk/3Xgi_CzJeQA/s1600/hierarchies_2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="478" src="http://2.bp.blogspot.com/-bqgvpc4HbFw/T1ZuokAaBjI/AAAAAAAAANk/3Xgi_CzJeQA/s640/hierarchies_2.png" width="640" /></a></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
And that's it. Now it is just to repeat the same steps for <span style="font-family: 'Courier New', Courier, monospace;">VoucherPricingService</span> and <span style="font-family: 'Courier New', Courier, monospace;">UserDiscountPricingService</span>. <b>Extract</b> the implementation of their template methods into classes, <b>inject</b> them into <span style="font-family: 'Courier New', Courier, monospace;">PricingService</span>, and <b>kill</b> the classes.<br />
<br />
In doing so, every time you extract a class, try to give them proper names instead of calling them <span style="font-family: 'Courier New', Courier, monospace;">Service</span>. Suggestions could be <span style="font-family: 'Courier New', Courier, monospace;">VoucherDiscountCalculation</span> and <span style="font-family: 'Courier New', Courier, monospace;">PrimeUserDiscountCalculation</span>.<br />
<br />
There were a few un-safe steps in the re-factoring described above and I also struggled a little bit to describe exactly how I did it since I was playing quite a lot with the code. Suggestions and ideas are very welcome.<br />
<br />
For the <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_26.html">final solution</a>, please check the <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_26.html">last part</a> of this blog post.<br />
<br />
<i>NOTE</i><br />
<i>If you are not used to use builders in your tests and is asking yourself where the hell <span style="font-family: 'Courier New', Courier, monospace;">aProduct</span>() and <span style="font-family: 'Courier New', Courier, monospace;">aShoppingBasket</span>() come from, check the code in here:</i><br />
<br />
<span style="font-family: 'Courier New', Courier, monospace;"><a href="https://gist.github.com/1988792">ProductBuilder.java</a></span><br />
<span style="font-family: 'Courier New', Courier, monospace;"><a href="https://gist.github.com/1988805">ShoppingBasketBuilder.java</a></span><br />
<br />
<i>For more information about the original problem that triggered all this, please read <a href="http://craftedsw.blogspot.com/2012/03/extract-inject-kill-breaking.html">part 1</a> of this blog post.</i><br />
<i>In <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_26.html">part 3</a> I finish the exercise, breaking the entire hierarchy. Please have a look at it for the <a href="http://craftedsw.blogspot.co.uk/2012/03/extract-inject-kill-breaking_26.html">final solution</a>. </i></div>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-32750231538623780422012-03-06T18:15:00.000+00:002012-03-06T20:38:06.599+00:00Extract, Inject, Kill: Breaking hierarchies (part 1)<div dir="ltr" style="text-align: left;" trbidi="on">
<br />
<div style="margin-bottom: 0cm;">
Years ago, before I caught the TDD bug,
I used to love the <a href="http://en.wikipedia.org/wiki/Template_method_pattern">template method pattern</a>. I really thought that it
was a great way to have an algorithm with polymorphic parts. The use
of inheritance was something that I had no issues with. But yes, that
was many years ago.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Over the years, I've been hurt by this
"design style". That's the sort of design created by
developers that do not TDD.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<b>The situation</b></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Very recently I was working on one part of our legacy code and found a six level deep hierarchy of classes.
There were quite a few template methods defined in more than one of
the classes. All classes were abstract with the exception of the
bottom classes, that just implemented one or two of the template
methods. There were just a single public method in the entire
hierarchy, right at the very top.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
We had to make a change in one of the
classes at the bottom. One of the (protected) template method implementations had
to be changed.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<b>The problem</b></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
How do you test it? Goes without saying
that there were zero tests for the hierarchy.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
We know that we should never test
private or protected methods. A class should "always" be
tested from its public interface. We should always write tests that
express and test "what" the method does and not "how".
That's all well and good. However, in this case, the change needs to
be done in a protected method (template method implementation) that
is part of the implementation of a public method defined in a class
six level up in the hierarchy. To test this method, invoking the
public method of its grand grand grand grand parent we will need to
understand the entire hierarchy, mock all dependencies, create the
appropriate data, configure the mocks to have a well defined
behaviour so that we can get this piece of code invoked and then
tested.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Worse than that, imagine that this class at the bottom has siblings overriding the same template
method. When the siblings need to be changed, the effort to write tests for
them will be the same as it was for our original class. We will have
loads of duplications and will also need to understand all the code
inside all the classes in the hierarchy. The ice in the cake:
There are hundreds of lines to be understood in all parent classes.
</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<b>Breaking the rules</b></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Testing via the public method defined
at the very top of the hierarchy has proven not to be worth it. The
main reason is that, besides painful, we already knew that the whole
design was wrong. When we look at the classes in the hierarchy, they
didn't even follow the <a href="http://en.wikipedia.org/wiki/Is-a">IS-A rule</a> of inheritance. They inherit from
each other so some code could be re-used.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
After some time I
thought: Screw the rules and this design. I'm gonna just directly test
the protected method and then start breaking the hierarchy.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
</div>
<div style="margin-bottom: 0cm;">
<b>The approach: Extract, Inject, Kill</b></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
The overall idea is:</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
1. <b>Extract</b> all the behaviour from the
template method into a class.
</div>
<div style="margin-bottom: 0cm;">
2. <b>Inject</b> the new class into the parent
class (where the template is defined), replacing the template method invocation with the invocation
of the method in the new class.</div>
<div style="margin-bottom: 0cm;">
3. <b>Kill</b> the child class (the one that
had the template method implementation).</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
Repeat these steps until you get rid of
the entire hierarchy.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
This was done writing the tests first, making the <i>protected</i> template method implementation <i>public</i>.</div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
<i>NOTES</i></div>
<div style="margin-bottom: 0cm;">
<i>1. This may not be so simple if we have
methods calling up the stack in the hierarchy.</i></div>
<div style="margin-bottom: 0cm;">
<i>2. If the class has siblings, we have
to extract all the behaviour from the siblings before we can inject
into the parent and kill the siblings.</i></div>
<div style="margin-bottom: 0cm;">
<br /></div>
<div style="margin-bottom: 0cm;">
This probably is too complicate to
visualise, so in <a href="http://craftedsw.blogspot.com/2012/03/extract-inject-kill-breaking_06.html">part 2</a> of this post I'll be giving a more concrete <a href="http://craftedsw.blogspot.com/2012/03/extract-inject-kill-breaking_06.html">example</a>. </div>
<div style="margin-bottom: 0cm;">
<br /></div>
<br />
<div style="margin-bottom: 0cm;">
<br /></div>
<br />
<br />
<br /></div>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-75851464664897392752012-02-06T22:11:00.000+00:002012-02-06T22:11:27.232+00:00Code coverage is a side effect and not an end goal<br />
<div class="p1">
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%.</div>
<div class="p2">
<br /></div>
<div class="p1">
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. </div>
<div class="p2">
<br /></div>
<div class="p1">
More recently, I've seen a similar behaviour. Keeping a close eye on the metrics provided by <a href="http://www.sonarsource.org/">Sonar</a>, 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 <a href="http://en.wikipedia.org/wiki/Scrum_(development)#Sprint">sprint</a> and developers are asked to increase the code coverage. The intention behind it is good, right? Bit by bit the application get better. Awesome. </div>
<div class="p1">
<br /></div>
<div class="p1">
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. </div>
<div class="p2">
<br /></div>
<div class="p1">
<b><span style="font-size: large;">What does code coverage measure?</span></b></div>
<div class="p2">
<br /></div>
<div class="p3">
It measures the percentage of the code <i>exercised</i> by code written inside test methods. It does not measure the percentage of code <i>tested</i> by testing code. Having a test method that just invokes a public method in a class and <i>does not</i> test (assert/verify) anything, will make the code coverage go up but <i>will not</i> 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.</div>
<div class="p2">
<br /></div>
<div class="p3">
<b><span style="font-size: large;">Why do we invest time in writing tests?</span> </b>(In no particular order)</div>
<div class="p3">
<br /></div>
<div class="p3">
</div>
<ul>
<li>Make sure we understand what the application does, according to the executable requirements (tests); </li>
<li>Make sure that the application still does the right thing after we make changes to it or indicates possible areas of conflicts (failing tests);</li>
<li>Make sure we have regression test; </li>
<li>Make sure that in a click of a button we can know if the application is working correctly; </li>
<li>Make sure that we have a quick and small feedback loop in terms of quality and correctness of our application; </li>
<li>Make sure the application is simplified and easily maintainable, via testing and refactoring; </li>
<li>Make sure the complexity of the application is spread thin instead of having localised big balls of mud that we are scared to touch;</li>
<li>Make sure that we can easily add new features quickly; </li>
<li>Make sure that we extend the ROI in our software, extending its lifespan; </li>
<li>Make sure that our software does not rot, impeding and/or slowing down business progress; </li>
<li>Make sure that our clients are happy with the software;</li>
</ul>
<br />
<div class="p3">
<br /></div>
<div class="p3">
By the way, when I mention test, I mean all types/levels of tests, not just unit.</div>
<div class="p3">
<br /></div>
<div class="p3">
<span style="font-size: large;"><b>What should we focus on?</b></span></div>
<div class="p2">
<br /></div>
<blockquote class="tr_bq">
<span style="background-color: white; color: #333333; font-family: HelveticaNeue, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 18px;"><i>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.</i></span></blockquote>
<div class="p2">
<br /></div>
<div class="p3">
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. </div>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com2tag:blogger.com,1999:blog-8424060401701893376.post-36395470217229575732011-10-28T00:19:00.000+01:002011-10-28T00:37:15.310+01:00Mentorship in Software Craftsmanship - part 3In previous posts I covered:<br />
Part 1: <a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html">Mentor and mentee roles, gains and sacrifices, mutual respect</a><br />
Part 2: <a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html">How to choose mentors and mentees and mentorship misconceptions</a><br />
<br />
<b><span class="Apple-style-span" style="font-size: large;"><br /></span></b><br />
<b><span class="Apple-style-span" style="font-size: large;">Walking the long road together (or at least part of it)</span></b><br />
<br />
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 <a href="http://ofps.oreilly.com/titles/9780596518387/walking_the_long_road.html">long road</a>. Both mentor and mentees will be learning while they share part of their journey with each other.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">What mentors and mentees should do during the mentorship?</span></b><br />
<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">Establishing goals and tracking progress</span></b><br />
<br />
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.<br />
<br />
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.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">How long a mentorship should last?</span></b><br />
<br />
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.<br />
<br />
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.<br />
<br />
I, personally, would never try to define that upfront. Just enjoy the journey and let time tell when the mentorship should terminate.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">How and when does it terminate?</span></b><br />
<br />
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.<br />
<br />
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. <br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">Professionalism, Reputation and Public recognition</span></b><br />
<br />
Software craftsmanship is <a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html">all about professionalism</a> and it is almost impossible to talk about professionalism without talking about reputation.<br />
<br />
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.<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">Raising the bar</span></b><br />
<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
<br />
For previous parts of this blog post, please check:<br />
<br />
Part 1: <a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html">Mentor and mentee roles, gains and sacrifices, mutual respect</a><br />
Part 2: <a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html">How to choose mentors and mentees and mentorship misconceptions</a>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-11103509894912112722011-10-23T02:15:00.000+01:002011-10-23T02:18:02.014+01:00Installing Io language on UbuntuSince I'm new to Ubuntu and I had a hard time installing <a href="http://iolanguage.com/">Io language</a>, 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.<br />
<br />
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 <a href="https://github.com/lloyd/yajl">yajl</a> and <a href="http://libevent.org/">libevent</a><br />
<br />
If you've got then installed, you can skip the next steps.<br />
<br />
<b>NOTE</b>: You will need to have cmake and make. You can install them running the following commands from the terminal:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo apt-get install cmake</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo apt-get install make</span><br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">Installing yajl</span></b><br />
<br />
<ol>
<li>Download yajl from here: <a href="https://github.com/lloyd/yajl/downloads">https://github.com/lloyd/yajl/downloads</a></li>
<ol>
<li>In my case it was: lloyd-yajl-2.0.1-0-gf4b2b1a.zip</li>
</ol>
<li>Extract it into a folder.</li>
<li>Open the terminal and go to the folder you extracted yajl</li>
<li>Run the following commands</li>
<ol>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">mkdir build</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cd build</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cmake ..</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo make install</span></li>
</ol>
</ol>
<br />
For more information, please check:<br />
<a href="https://github.com/lloyd/yajl">https://github.com/lloyd/yajl</a><br />
<a href="https://github.com/lloyd/yajl/blob/master/BUILDING">https://github.com/lloyd/yajl/blob/master/BUILDING</a><br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">Installing libevent</span></b><br />
<br />
<ol>
<li>Download libevent from here: <a href="http://libevent.org/">http://libevent.org/</a></li>
<ol>
<li>In my case it was: libevent-2.0.15-stable.tar.gz</li>
</ol>
<li>Extract it into a folder</li>
<li>Open the terminal and go to the folder you extracted libevent</li>
<li>Run the following commands</li>
<ol>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">./configure</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">make</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo make install</span></li>
</ol>
</ol>
<br />
For more information please check:<br />
<a href="http://libevent.org/">http://libevent.org/</a><br />
Also check the README file inside the .tar.gz for your version<br />
<br />
<b><span class="Apple-style-span" style="font-size: large;">Installing Io language</span></b><br />
<br />
You can go to the <a href="http://iolanguage.com/">Io language website</a> and download the language or click <a href="http://github.com/stevedekorte/io/zipball/master">here</a> 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 <a href="https://github.com/stevedekorte/io">Steve Dekorte's version</a>. I ended up downloading <a href="https://github.com/jeremytregunna/io">Jeremy Tregunna's version</a>. It should work the same. Check each one is the most up-to-date.<br />
<br />
<ol>
<li>Download the Io version here: <a href="https://github.com/jeremytregunna/io/zipball/master">https://github.com/jeremytregunna/io/zipball/master</a></li>
<li>Extract it into a folder.</li>
<li>Open the terminal and go to the folder you extracted Io</li>
<li>Run the following commands:</li>
<ol>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">mkdir build</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cd buil</span>d</li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cmake ..</span></li>
<li><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo make install</span></li>
</ol>
</ol>
<br />
<b>IMPORTANT</b>: When running '<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">cmake ..</span>', you may get a few errors. Even then, try to run '<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo make install</span>'. Some libraries may fail to compile because they are OS specific.<br />
<br />
For mode information please check:<br />
<a href="http://iolanguage.com/">http://iolanguage.com/</a><br />
<a href="https://github.com/stevedekorte/io">https://github.com/stevedekorte/io</a><br />
<a href="https://github.com/jeremytregunna/io">https://github.com/jeremytregunna/io</a><br />
<b><br /></b><br />
<b><span class="Apple-style-span" style="font-size: large;">Updating ld.so.conf</span></b><br />
<br />
Now we just need to update ld.so.conf so Io can be accessed from anywhere in your computer.<br />
<br />
<ol>
<li>From the terminal, type the following command: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo gedit /etc/ld.so.conf</span></li>
<li>Add the following line to the file: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">include /usr/local/lib</span></li>
<li>Save and close the file</li>
<li>From the terminal run the following command: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo ldconfig</span></li>
</ol>
<br />
<b><span class="Apple-style-span" style="font-size: large;">Running Io</span></b><br />
<br />
That's it. Hopefully now you will be able to open a terminal window and type: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">io</span><br />
You should see the Io runtime environment: <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">Io> _</span>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com3tag:blogger.com,1999:blog-8424060401701893376.post-39718273913977103122011-10-10T02:14:00.000+01:002011-10-30T17:00:50.757+00:00Mentorship in Software Craftsmanship - part 2<br />
<div style="text-align: justify;">
In <a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html">part one</a> 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.</div>
<br />
<b><span class="Apple-style-span" style="font-size: large;">How do we find mentors or mentees?</span></b><br />
<br />
That's probably the most difficult question to answer. I can think in three possibilities (in no particular order):<br />
<br />
<ol>
<li>Try to find someone that works with you in a daily basis. It will make the approach easier.</li>
<li>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.</li>
<li>Via indication: A friend could recommend/introduce you to someone. </li>
</ol>
<b><span class="Apple-style-span" style="font-size: large;"></span></b><br />
<div>
<b><span class="Apple-style-span" style="font-size: large;"><b><span class="Apple-style-span" style="font-size: large;"><br /></span></b></span></b></div>
<b><span class="Apple-style-span" style="font-size: large;">
Choosing a mentor</span></b><br />
<div>
<br /></div>
<div>
<div style="text-align: justify;">
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 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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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. </div>
<br />
<b><span class="Apple-style-span" style="font-size: large;">Choosing a mentee</span></b><br />
<br />
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The first thing to look for in a mentee is <i>passion</i>. 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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Choosing a mentee is a very personal thing and different mentors will have completely different criteria. 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:</div>
<br />
<ul>
<li style="text-align: justify;">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.</li>
<li style="text-align: justify;">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.</li>
<li style="text-align: justify;">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. </li>
</ul>
<br />
<div style="text-align: justify;">
The mentor, if going down this route, should set the challenges according to the level of seniority he is expecting from the mentee. 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.</div>
<br />
<b><span class="Apple-style-span" style="font-size: large;">Mentorship common misconceptions</span></b><br />
<br />
<div style="text-align: justify;">
<b style="font-weight: bold;"><i>The mentor is not better than the mentee.</i></b> 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.</div>
<br />
<div style="text-align: justify;">
<i style="font-weight: bold;"><b>Mentors should not be looking for themselves a few years younger.</b></i><b> </b>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.</div>
<br />
<div style="text-align: justify;">
<b style="font-weight: bold;"><i>Mentees should not expect that mentors will change their lives.</i></b><b> </b>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. </div>
<br />
<div style="text-align: justify;">
<i>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.</i></div>
<br />
<i><a href="http://craftedsw.blogspot.com/2011/10/mentorship-in-software-craftsmanship.html">Part 3: What mentors and mentees should do, how long it should last, how does it end public recognition and reputation</a></i><br />
<br />
<i><a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship.html">Part 1: A bit of history, roles of the mentors and mentees, gains and sacrifices and mutual respect</a></i><br />
<div>
<b><br /></b></div>
<br />
<b>
</b></div>
<b>
</b>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-57035278841148851472011-10-05T00:45:00.000+01:002011-10-30T16:57:26.788+00:00Mentorship in Software Craftsmanship - part 1<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: x-large;"><b>How's mentorship seen in Software Craftsmanship?</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b>First, a little bit of background and metaphor</b> </span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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.</div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b><br /></b></span></div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b>Back to the present</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b>The role of the mentor</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b>The role of the mentee</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b>Gains and sacrifices</b></span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Mentors have the opportunity to perpetuate their knowledge since they need to organise their ideas to teach someone. Mentors will also need to be studying and 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.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
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). 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. </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
</div>
<div style="text-align: justify;">
<span class="Apple-style-span" style="font-size: large;"><b>Mutual Respect</b></span></div>
<div>
<br /></div>
<div>
Both mentors and mentees should respect each other. In order to have a healthy and prosperous relationship, there must be a commitment from both parts. This commitment is the mutual respect. The mentor shows respect with regular interactions with the mentee and time commitment. 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. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<i>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.</i><br />
<i><br /></i><br />
<i><a href="http://craftedsw.blogspot.com/2011/10/mentoring-in-software-craftsmanship_09.html">Part 2: Choosing a mentor and a mentee and also common mentorship misconceptions </a></i><br />
<i><a href="http://craftedsw.blogspot.com/2011/10/mentorship-in-software-craftsmanship.html">Part 3: What mentors and mentees should do, how long it should last, how does it end public recognition and reputation</a></i></div>
<div>
<br /></div>
<br />Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-6335498228025512232011-09-20T09:59:00.000+01:002011-09-23T01:40:28.036+01:00LSCC's First Code RetreatOn September 10th we had the London Software Craftsmanship Community's <a href="http://www.meetup.com/london-software-craftsmanship/events/27600561/">First Code Retreat</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<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;"><img border="0" height="240" src="http://4.bp.blogspot.com/-Lsl8mfpVWMQ/TnvUSzkbV8I/AAAAAAAAAMY/l-KZrJMJhyw/s320/coderetreat01.jpg" width="320" /></a></div>
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.<br />
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:<br />
<br />
"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". <br />
<br />
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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="http://4.bp.blogspot.com/-cY1fqDBVpk8/TnhRPsHkJSI/AAAAAAAAAMI/sYlqzPRGwHs/s1600/PerfectCode_Gap.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="217" src="http://4.bp.blogspot.com/-cY1fqDBVpk8/TnhRPsHkJSI/AAAAAAAAAMI/sYlqzPRGwHs/s320/PerfectCode_Gap.jpg" width="320" /></a></div>
<br />
<br />
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. :)<br />
<br />
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. "<br />
<br />
<blockquote>
It's not practice that leads to perfection, it's perfect practice that leads to it. </blockquote>
<br />
I also explained the four rules of simple design:<br />
- All tests need to pass;<br />
- No duplication;<br />
- Reveals intention (good naming)<br />
- Small<br />
<br />
<blockquote>
I have made this letter longer than usual, only because I have no time to make it shorter. <br />
<div style="text-align: right;">
<i>Blaise Pascal (sometimes also attributed to </i><i>Mark Twain</i><i>)</i></div>
</blockquote>
<br />
<span style="font-size: large;"><b>Format of the day</b></span><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<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;"><img border="0" height="240" src="http://2.bp.blogspot.com/-YXd0AQq2ink/TnvSe1Rp8BI/AAAAAAAAAMQ/PDDfXXsYCx8/s320/coderetreat04.jpg" width="320" /></a></div>
<br />
After a good breakfast, developers formed pairs and worked on the <a href="http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life">Conway's Game of Life</a>. 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. <br />
<br />
<ul>
<li><b>First session</b>: It was free. Basically the pairs worked with no constraints just to make themselves familiar with the problem.</li>
<li><b>Second session</b>: As a challenge, they were asked to use different data structure other than arrays and we introduced the concept of "primitive obsession".</li>
<li><b>Third session</b>: Developers were asked not to use flags and use polymorphism instead. This was to promote the exploration of abstractions.</li>
</ul>
<ul>
<li><b>Lunch</b>: 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.</li>
</ul>
<ul>
<li><b>Fourth session</b>: 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;<ul>
<li>Maximum 3 lines of code per method;</li>
<li>Object-Oriented Programming to extreme.</li>
<li>No getters / setters / properties</li>
<li>Every line must start with "return" or "final" (Java/C# - functional style)</li>
</ul>
</li>
<li><b>Fifth session</b>: TDD as if you meant it, that means, all code needs to be written inside the test method and then refactored out.</li>
<li><b>Sixth session</b>: Developers were free to do whatever they wanted again but many decided to use some of the challenges from sesson four. </li>
<li><b>Pub</b></li>
</ul>
<br />
<div class="separator" style="clear: both; text-align: center;">
<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;"><img border="0" height="240" src="http://2.bp.blogspot.com/-WEJi5aGYe5Y/TnvSgI0WjUI/AAAAAAAAAMU/lTwLG1JckgE/s320/coderetreat11.jpg" width="320" /></a></div>
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. <br />
<br />
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.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<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;"><img border="0" height="240" src="http://2.bp.blogspot.com/-SWijxD3WSjE/TnvUT2_5kTI/AAAAAAAAAMc/5pkN-iFn3-U/s320/coderetreat15.jpg" width="320" /></a></div>
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. <br />
<br />
I would like to thank <a href="http://valtech.co.uk/">Valtech</a> for providing the venue and for the full sponsorship. They provided us everything we needed for this event and were key for its success. <br />
<br />
For the full list of attendees, details about the event and more photos, please check <a href="http://www.meetup.com/london-software-craftsmanship/events/27600561/">http://www.meetup.com/london-software-craftsmanship/events/27600561/</a>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-44568375718252448582011-08-20T01:03:00.000+01:002011-08-20T01:11:44.725+01:00One year of London Software Craftsmanship Community (LSCC)<blockquote><span class="indquote_link"> <i>Without a sense of caring, there can be no sense of community.</i></span><i><span class="author_text"> - Anthony Burgess</span></i></blockquote><br />
<span style="font-size: large;"><b>Happy Birthday, LSCC!!!! </b></span><br />
<br />
On 18th of August 2011, the <a href="http://www.londonswcraft.com/">London Software Craftsmanship Community</a> completed one year. And what a great year we had! <br />
<br />
<span style="font-size: large;"><b>How did it all start?</b></span><br />
<br />
<a href="http://twitter.com/activelylazy">David Green</a> 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.<br />
<br />
By then, I was very into the whole <a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html">Software Craftsmanship</a> 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.<br />
<br />
I had been involved with the <a href="http://www.meetup.com/Londonjavacommunity/">London Java Community</a> (LJC) even before its existence. At some point I managed to bring David along to one of the <a href="http://www.meetup.com/Londonjavacommunity/">LJC</a>'s social events. On that evening, David and I had a chat with <a href="http://twitter.com/barryclearview/">Barry Cranford</a>, founder of the LJC, and with <a href="http://twitter.com/karianna/">Martijn Verburg</a> and <a href="http://twitter.com/JR0cket/">John Stevenson</a>, 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 <a href="http://craftedsw.blogspot.com/2010/09/software-craftsmanship.html">Software Craftsmanship</a> 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. <br />
<br />
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?<br />
<br />
When I got home that night, I went to the <a href="http://www.meetup.com/">meetup.com</a> website and created the <a href="http://www.meetup.com/london-software-craftsmanship/">London Software Craftsmanship Community</a>. <br />
<br />
<span style="font-size: large;"><b>Summary of our first year</b></span><br />
<br />
We had our <a href="http://www.meetup.com/london-software-craftsmanship/events/14862535/">first meeting</a> on 6th of October, 2010 (<a href="http://skillsmatter.com/podcast/design-architecture/what-is-software-craftsmanship">video</a>). 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<br />
<br />
<span style="font-size: small;"><b>The Round-table meetings</b></span><br />
<br />
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.<br />
<br />
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.<br />
<br />
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. <br />
<br />
<b>Other meetings</b><br />
<br />
During the year we also had a few other great meetings. One was the Software Craftsmanship Panel Discussion - <a href="http://www.meetup.com/london-software-craftsmanship/events/16879836/">How can craftsmanship move the industry forwards?</a> | <a href="http://skillsmatter.com/podcast/agile-testing/how-can-craftsmanship-move-the-industry-forwards">video</a> - when we had the pleasure to have <a href="http://twitter.com/ade_oshineye">Ade Oshineye</a>, <a href="http://twitter.com/chrismdp">Chris Parsons</a>, <a href="http://twitter.com/tastapod">Dan North</a> and <a href="http://twitter.com/redsquirrel">Dave Hoover</a> in the panel. It was great to see them giving their views about many topics relevant to the future of our industry. We had <a href="http://twitter.com/hugs">Jason Huggins</a>, creator of <a href="http://seleniumhq.org/">Selenium</a>, giving a talk to us about "<a href="http://www.meetup.com/london-software-craftsmanship/events/15118493/">how to test 'untestable' applications</a>" | <a href="http://skillsmatter.com/podcast/home/painless-product-demos-how-to-test-untestableapplications">video</a>.<br />
<br />
We also cross-promoted the <a href="http://www.meetup.com/london-software-craftsmanship/events/16695974/">Code Retreat Winchester</a>, organised by <a href="http://twitter.com/despo">Despo</a> and <a href="http://twitter.com/sermoa">Aimee</a>, and the first <a href="http://www.meetup.com/london-software-craftsmanship/events/21919121/">Cambridge Dojo Day</a>, organised by <a href="http://twitter.com/alastairs">Alastair Smith</a>, organiser of the <a href="http://www.camdug.com/">Cambridge User Group - CAMDUG</a>.<br />
<br />
<span style="font-size: large;"><b>Future meetings</b></span><br />
<br />
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 <a href="http://www.meetup.com/london-software-craftsmanship/events/28321981/">Crafting Object-Oriented Code</a>, 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. <br />
<br />
We are also very happy to be having <a href="http://www.meetup.com/london-software-craftsmanship/events/27600561/">LSCC's First Code Retreat</a> on 10th of September. <br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>Community</b></span><br />
<br />
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. <br />
<br />
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.<br />
<br />
<span style="font-size: large;"><b>The future of LSCC</b></span><br />
<br />
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.<br />
<br />
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.<br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>A big thanks</b></span><br />
<br />
I would like to thank our sponsors - <a href="http://www.youdevise.com/">YouDevise</a>, <a href="http://twitter.com/skillsmatter">SkillsMatter</a> and <a href="http://twitter.com/valtech">Valtech</a> - 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.<br />
<br />
A big thanks to all the <a href="http://ofps.oreilly.com/titles/9780596518387/accurate_self_assessment.html#kindred_spirits">kindred spirits</a> 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!<br />
<br />
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.Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com2tag:blogger.com,1999:blog-8424060401701893376.post-91059714342728635422011-07-26T02:47:00.000+01:002011-07-26T02:58:56.892+01:00SRP: Simplicity and Complexity<blockquote><span class="body">Simplicity does not precede complexity, but follows it.</span> <span class="bodybold">- Alan Perlis</span> </blockquote><br />
The Single Responsibility Principle (SRP) - one of the <a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html">SOLID</a> 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 <a href="http://craftedsw.blogspot.com/2010/06/object-oriented-design-principles-part.html">wrote about it</a> 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.<br />
<br />
<b><span style="font-size: large;">The outside view</span></b> <br />
<br />
<blockquote><span style="font-size: small;"> </span><i><span style="font-size: small;">Every class and method should have just one responsibility</span></i></blockquote><br />
This is what I call <i>outside view</i> and naming plays a big role here.<br />
<br />
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 <i>outside view</i> when reading code. When looking at a class or method name, it should be clear to us what they do.<br />
<br />
I don't think anyone ever had a problem understanding this principle. <br />
<br />
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. <br />
<br />
<b><span style="font-size: large;">The inside view</span></b><br />
<br />
<blockquote><i><span style="font-size: small;">Classes and methods should have one, and only one, reason to change</span></i></blockquote><br />
This is what I call <i>inside view</i> and it is the other (often forgotten) side of the Single Responsibility Principle.<br />
<br />
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. <br />
<br />
However, it is much easier to adhere to the SRP when we keep the <i>inside view</i> in mind instead of the <i>outside view</i>. That means, always think about the number of reasons to change a class or method instead of thinking purely in their responsibilities. <br />
<br />
<b><span style="font-size: large;">So, when and where do things go wrong?</span></b><br />
<br />
<i>NOTE: In general I find more SRP violations in systems where developers are not doing TDD and refactoring. </i><br />
<br />
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. <br />
<br />
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. <br />
<br />
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 "<span style="font-family: "Courier New",Courier,monospace;">processTrade(tradeXML)</span>", located in a <span style="font-family: "Courier New",Courier,monospace;">TradeService</span> 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 <span style="font-family: "Courier New",Courier,monospace;">processTrade</span>. <br />
<br />
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 <span style="font-family: "Courier New",Courier,monospace;">placeOrder(order)</span>. Fair, right?<br />
<br />
<b><span style="font-size: large;">Developing an idea</span></b><br />
<br />
<blockquote>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. </blockquote><br />
In both examples above, by their names, you can argue that the methods <span style="font-family: "Courier New",Courier,monospace;">processTrade</span> and <span style="font-family: "Courier New",Courier,monospace;">placeOrder</span> have a single responsibility. One processes the incoming trade and the other places a customer order. So, when developers take into account <b>just</b> the <i>outside view</i> of the SRP, they feel comfortable to add as much code as they need to satisfy these responsibilities. <br />
<br />
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.<br />
<br />
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.<br />
<br />
<blockquote>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.</blockquote><br />
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. <br />
<br />
<span style="font-size: large;"><b>Asking a different question</b></span><br />
<br />
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 <i>outside view</i> as an argument sometimes is not enough to convince some developers that the code is doing too much. That's why I find the <i>inside view</i> 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.Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com0tag:blogger.com,1999:blog-8424060401701893376.post-19284707138790253722011-07-18T02:12:00.000+01:002011-07-18T02:12:08.747+01:00Testing legacy: Hard-wired dependencies (part 2)In <a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html">part one</a>, 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:<br />
<br />
<script src="https://gist.github.com/1087417.js?file=TripService.java">
</script><br />
How many problems can you see? Take your time before reading the ones I found.. :-)<br />
<br />
<span style="font-size: large;"><b>Refactoring</b></span><br />
<span style="font-size: large;"><i><span style="font-size: small;">NOTE</span><b><span style="font-size: small;">: </span></b><span style="font-size: small;">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</span></i>. </span><br />
<br />
<span style="font-size: large;"><span style="font-size: small;">The first thing I noticed is that the <span style="font-family: "Courier New",Courier,monospace;">tripList </span>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 <a href="http://c2.com/cgi/wiki?GuardClause">guard clause</a>. </span></span><br />
<span style="font-size: large;"><span style="font-size: small;"> </span><b><br />
</b></span><br />
<script src="https://gist.github.com/1087435.js?file=TripService_refactor1.java">
</script><br />
<b><span style="font-size: large;">Feature Envy</span></b><br />
<br />
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 <i>envies </i>the other class. This is called <a href="http://c2.com/cgi/wiki?FeatureEnvySmell">Feature Envy (code smell)</a> 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. <br />
<br />
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:<br />
<br />
<script src="https://gist.github.com/1087914.js?file=UserTest.java">
</script><br />
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.<br />
<br />
<script src="https://gist.github.com/1088245.js?file=gistfile1.txt">
</script><br />
After a few refactoring steps, here is the new code in the TripService<br />
<br />
<script src="https://gist.github.com/1088251.js?file=gistfile1.java">
</script><br />
Right. This is already much better but it is still not good enough.<br />
<br />
<b><span style="font-size: large;">Layers and dependencies</span></b><br />
<br />
Some of you may still be annoyed by the protected methods we created in <a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html">part one</a> 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.<br />
<br />
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?<br />
<br />
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.<br />
<br />
<b><span style="font-size: large;">Naming</span></b><br />
<br />
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.<br />
<br />
So here is the final code:<br />
<br />
<script src="https://gist.github.com/1088277.js?file=TripServiceFinal.java">
</script><br />
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. :-)<br />
<br />
<b><span style="font-size: large;">Conclusion</span></b><br />
<br />
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.<br />
<br />
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 <a href="http://craftedsw.blogspot.com/2010/09/bad-code-invisible-threat.html">business starts slowing down</a> because we cannot adjust the software quick enough.<br />
<br />
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.<br />
<br />
We should treat our code base as if it was a <a href="http://craftedsw.blogspot.com/2010/09/bad-code-invisible-threat.html">big garden</a>. If we want it to be pleasant and maintainable, we need to be constantly looking after it .<br />
<br />
If you haven't read it yet, check the <a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies.html">part one</a> of this post. If you want to give this code a go or find more details about the implementation, check: <a href="https://github.com/sandromancuso/testing_legacy_code">https://github.com/sandromancuso/testing_legacy_code</a>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com4tag:blogger.com,1999:blog-8424060401701893376.post-17949768147378680462011-07-17T00:42:00.000+01:002011-07-18T02:14:08.580+01:00Testing legacy: Hard-wired dependencies (part 1)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 - <b>Singletons</b> and <b>static calls</b>. <br />
<br />
Let's look at this piece of code:<br />
<br />
<pre class="brush: java">public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
List<Trip> tripList = new ArrayList<Trip>();
User loggedUser = UserSession.getInstance().getLoggedUser();
boolean isFriend = false;
if (loggedUser != null) {
for (User friend : user.getFriends()) {
if (friend.equals(loggedUser)) {
isFriend = true;
break;
}
}
if (isFriend) {
tripList = TripDAO.findTripsByUser(user);
}
return tripList;
} else {
throw new UserNotLoggedInException();
}
}
</pre><br />
Horrendous, isn't it? The code above has loads of problems, but before we change it, we need to have it covered by tests.<br />
<br />
There are two challenges when unit testing the method above. They are:<br />
<br />
<pre class="brush: java">User loggedUser = UserSession.getInstance().getLoggedUser(); // Line 3
tripList = TripDAO.findTripsByUser(user); // Line 13
</pre><br />
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 <a href="http://craftedsw.blogspot.com/2011/07/working-with-legacy-code.html">rule</a>, remember? <br />
<br />
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. <br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>Overcoming the hard-dependencies problem</b></span><br />
<br />
<span style="font-size: x-small;"><i>NOTE: In real life I would be writing tests first and making the change just when I needed but </i><i>in order to keep the post short and focused</i></span><i><span style="font-size: x-small;"> I will not go step by step here </span>.</i><br />
<br />
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:<br />
<br />
<pre class="brush: java">UserSession.getInstance().getLoggedUser()
</pre><br />
Go to your IDE's refactoring menu, choose extract method and give it a name. After this step, the code will look like that:<br />
<br />
<pre class="brush: java">public class TripService {
public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
...
User loggedUser = loggedUser();
...
}
protected User loggedUser() {
return UserSession.getInstance().getLoggedUser();
}
}
</pre><br />
Doing the same thing for TripDAO.findTripsByUser(user), we will have: <br />
<br />
<pre class="brush: java">public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
...
User loggedUser = loggedUser();
...
if (isFriend) {
tripList = findTripsByUser(user);
}
...
}
protected List<Trip> findTripsByUser(User user) {
return TripDAO.findTripsByUser(user);
}
protected User loggedUser() {
return UserSession.getInstance().getLoggedUser();
}
</pre><br />
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:<br />
<br />
<pre class="brush: java">private TripService createTripService() {
return new TripService() {
@Override protected User loggedUser() {
return loggedUser;
}
@Override protected List<Trip> findTripsByUser(User user) {
return user.trips();
}
};
}
</pre><br />
And this is it. Our TripService is now testable. <br />
<br />
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 <a href="http://www.eclemma.org/">eclEmma plugin</a> 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.<br />
<br />
So here is the my final test class:<br />
<br />
<pre class="brush: java">public class TripServiceTest {
private static final User UNUSED_USER = null;
private static final User NON_LOGGED_USER = null;
private User loggedUser = new User();
private User targetUser = new User();
private TripService tripService;
@Before
public void initialise() {
tripService = createTripService();
}
@Test(expected=UserNotLoggedInException.class) public void
shouldThrowExceptionWhenUserIsNotLoggedIn() throws Exception {
loggedUser = NON_LOGGED_USER;
tripService.getTripsByUser(UNUSED_USER);
}
@Test public void
shouldNotReturnTripsWhenLoggedUserIsNotAFriend() throws Exception {
List<Trip> trips = tripService.getTripsByUser(targetUser);
assertThat(trips.size(), is(equalTo(0)));
}
@Test public void
shouldReturnTripsWhenLoggedUserIsAFriend() throws Exception {
User john = anUser().friendsWith(loggedUser)
.withTrips(new Trip(), new Trip())
.build();
List<Trip> trips = tripService.getTripsByUser(john);
assertThat(trips, is(equalTo(john.trips())));
}
private TripService createTripService() {
return new TripService() {
@Override protected User loggedUser() {
return loggedUser;
}
@Override protected List<Trip> findTripsByUser(User user) {
return user.trips();
}
};
}
}
</pre><br />
<b>Are we done?</b><br />
<br />
Of course not. We still need to refactor the TripService class. Check the <a href="http://craftedsw.blogspot.com/2011/07/testing-legacy-hard-wired-dependencies_17.html">part two</a> of this post.<br />
<br />
If you want to give it a go, here is the full code: <a href="https://github.com/sandromancuso/testing_legacy_code">https://github.com/sandromancuso/testing_legacy_code</a>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com4tag:blogger.com,1999:blog-8424060401701893376.post-45536858602200552572011-07-03T23:37:00.000+01:002011-07-03T23:56:56.653+01:00Working with legacy code<span style="font-size: large;"><b>Context</b></span><br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>The Rule</b></span><br />
<br />
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. <br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>Problem</b></span><br />
<br />
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.<br />
<br />
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. :-) <br />
<br />
<span style="font-size: large;"><b>Why are we "under-performing"?</b></span><br />
<br />
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.<br />
<br />
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. So they leave that to QA.<br />
<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
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.<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-M27DSWj4Qd0/ThCw0dKhkUI/AAAAAAAAALs/GUf0d4JEJtg/s1600/Legacy_velocity.jpg" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="146" src="http://1.bp.blogspot.com/-M27DSWj4Qd0/ThCw0dKhkUI/AAAAAAAAALs/GUf0d4JEJtg/s400/Legacy_velocity.jpg" width="400" /></a></div><br />
<br />
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. <br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>Drifting away and losing focus</b></span><br />
<br />
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. <br />
<br />
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.<span style="font-size: large;"><b> </b></span><br />
<br />
<span style="font-size: large;"><b>A more positive side effect</b></span><br />
<br />
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.<br />
<br />
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.<br />
<br />
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. <br />
<br />
<span style="font-size: large;"><b>Quality is a long term investment</b></span><br />
<br />
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? <br />
<br />
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.<br />
<br />
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. <br />
<br />
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.Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com1tag:blogger.com,1999:blog-8424060401701893376.post-79300629369737838582011-06-21T03:31:00.000+01:002011-06-21T03:31:59.736+01:00A change in attitude - Legacy code<blockquote><span style="font-family: Arial; font-size: small;">Attitude is a little thing that makes a big difference. ~Winston Churchill </span></blockquote><span style="font-family: Arial; font-size: small;"> </span> <br />
<span style="font-size: small;"> </span><span style="font-family: Arial; font-size: small;">Not long ago, I gave a <a href="http://skillsmatter.com/podcast/design-architecture/what-is-software-craftsmanship/js-1956">talk</a> 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. </span><br />
<span style="font-family: Arial; font-size: small;"> </span> <span style="font-size: small;"><br />
</span><span style="font-family: Arial; font-size: small;">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.</span><br />
<span style="font-family: Arial; font-size: small;">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. </span><br />
<br />
<span style="font-size: small;"><span style="font-size: large;"><b><span style="font-family: Arial;">A change in attitude</span></b></span> </span><br />
<span style="font-size: small;"> </span><br />
<blockquote><span style="font-family: Arial; font-size: small;">If you don't like something change it; if you can't change it, change the way you think about it. ~Mary Engelbreit</span><span style="font-size: small;"><br />
</span></blockquote><span style="font-family: Arial; font-size: small;"> </span> <span style="font-size: small;"><br />
</span><span style="font-family: Arial; font-size: small;">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. </span><br />
<span style="font-size: small;"> </span><span style="font-family: Arial; font-size: small;"> </span> <span style="font-size: small;"><br />
</span><span style="font-family: Arial; font-size: small;">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. </span><br />
<span style="font-family: Arial; font-size: small;">As my friend <a href="http://twitter.com/activelylazy">David Green</a> 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. </span><br />
<br />
<span style="font-family: Arial; font-size: small;">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 </span><span style="font-family: Arial; font-size: small;">nonetheless some </span><span style="font-family: Arial; font-size: small;">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).</span><br />
<br />
<span style="font-family: Arial; font-size: small;">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.</span><b><span style="font-family: Arial; font-size: small;"> </span></b><br />
<br />
<b><span style="font-family: Arial; font-size: small;">Different challenges</span></b><span style="font-family: Arial; font-size: small;"> </span><br />
<br />
<span style="font-family: Arial; font-size: small;">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.</span><br />
<br />
<b><span style="font-family: Arial; font-size: small;">The professional side</span></b><span style="font-family: Arial; font-size: small;"> </span><br />
<br />
<span style="font-family: Arial; font-size: small;">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.</span><br />
<br />
<span style="font-family: Arial; font-size: small;"><b>Conclusion</b></span><br />
<br />
<span style="font-family: Arial; font-size: small;">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. </span>Sandro Mancusohttp://www.blogger.com/profile/02110812790722611225noreply@blogger.com6