Posts Tagged ThoughtWorks
Rule 3: Wrap All Primitives and Strings
This is the third part of a series of articles starting here.
Wrapping primitives (ints, floats etc) and strings is an easy way to increase maintainability and readability of your code. Also, as Abinesh TD Consider for example the following pseudo-javacode:
public class Contact { private String emailAddress; public void setEmail(String emailAddress) throws InvalidEmailException { if (! validateEmail(emailAddress)) { throw new InvalidEmailException("Uhm, that's not a valid mail address..."); } this.emailAddress = emailAddress; } public String getEmail() { return emailAddress; } private Boolean validateEmail(String emailAddress) { // TODO: validation regexp etc } }
A very simple class, containing a single field intended to hold an email address. It looks good enough, but imagine that you have other places where you would need to validate and store email addresses. You would have a tendency for code duplication right there.
Worst case would be that you would have a validation function in every email container class. It would be better to wrap the string intended to hold the email address in its own class, even if it only holds one field, the potential for code reuse increases exponentially.
A better implementation could look like this:
public class Contact { private EmailAddress emailAddress; public void setEmail(EmailAddress emailAddress) { this.emailAddress = emailAddress; } public void setEmail(String emailAddress) { try { this.emailAddress = new EmailAddress(emailAddress); } catch (InvalidEmailException e) { // Oh lord something went wrong here... :) } public String getEmail() { return emailAddress; } }
The benefits should be immediately clear. Suddenly the class EmailAddress requires the email address string to be valid to be instantiated at all. This would make it much easier to quickly zero in on bugs and also increases the potential reuse of your code.
Pretty much any variable you want to store, whether it is a primitive or a string – WILL need some sort of validation. This is a major reason for wrapping them. But other than that, consistently wrapping gives your object oriented code a higher degree of encapsulation.
Previous « Rule 2: Don’t Use the Else Keyword
Next » Rule 4: Only Use One Dot Per Line
Rule 2: Don’t Use the Else Keyword
This is the second part of a series of articles starting here.
The second rule of the “Nine Ways to Better Software Today” is to stop using
elseThis builds on top of rule 1, to decrease the level on indentation by again focusing on minimizing complex conditionals. Within the object oriented paradigm, polymorphism is a powerful model to handle this. Regardless of programming model, this exercise forces you as developer to find alternatives to using the else keyword and thus considerably beautifying your code.
Consider the following Python code
def set_member_status(member, status): """ Spot the else keyword """ if is_active(member): do_something(member, status) else: do_something_else(member, status)
There are several ways to simplify this method. For simple cases use early returns, as below. Early returns only work in methods which are short and lacking in complexity (keeping down the level of indentation helps with this). Once a method is long and contains many levels of abstraction, early returns can of course not be used. But by then you’ve failed at this exercise anyway.
def set_member_status(member, status): """ Example of using early returns """ if is_active(member): do_something(member, status) return # here is the early return :) do_something_else(member, status)
In many languages it is possible to use the ternary operator. That would look something like this (in javascript):
/** Wrong */ function drowned() { if (timeInWater < SURVIVABLE_TIME) { return false; } else { return true; } } /** Right */ function drowned() { return timeInWater < 10 ? false : true; }
Guard clauses is another way of increasing readability. The following example is taken from here
double getPayAmount() { double result; if (_isDead) result = deadAmount(); else { if (_isSeparated) result = separatedAmount(); else { if (_isRetired) result = retiredAmount(); else result = normalPayAmount(); }; } return result; }; double getPayAmount() { if (_isDead) return deadAmount(); if (_isSeparated) return separatedAmount(); if (_isRetired) return retiredAmount(); return normalPayAmount(); };
Previous « Rule 1: Only Use One Level of Indentation
Next » Rule 3: Wrap All Primitives and Strings
Nine Steps to Better Software Design Today: Thoughtworks Exercise
There are few companies out there more exiting to me than Thoughtworks. They sport a fantastic set of values, and have some of todays most brilliant programmers and software thinkers on board. But what strikes me as most wonderful about them is the way they communicate with programmers around the world. They really have an interest in good software, whether it is their own, or somebody else’s.
On reading their book, the Thoughtworks Anthology there was one chapter (Object Calisthenics by Jeff Bay) which struck me as extremely fun to read, it contained an exercise called “Nine Steps to Better Software Design Today”. An exercise completely focused on object oriented design quality with all that that entails, like encapsulation and appropriate use of polymorphism.
It is really a very simple exercise in many aspects, it simply provides nine rules, and asks me as a developer to do my absolute best to abide by those rules. What Thoughtworks does is so ingenious. Instead of just preaching the holy grail of object oriented programming, they ask me to be a part of the sermon. On reading the whole exercise I was instantly revving my engine to actually do the exercise. So I started up a small GWT project and forced myself to actually try and comply with the nine rules.
I’ve never had so much fun programming! And the process truly changed the way I will write code from now, whether it is in a purely object oriented language or not.
Said and done. I will start with the first rule:
Rule 1 : Use only one level of indentation per method
No matter which language you are working with, this is something that is very important. Check out the class, that thoughtworks uses as an example, below. It contains one function with several levels of indentation.
class Board { String board() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) buf.append(data[i][j]); buf.append("\n"); } return buf.toString(); } }
Now consider that after some refactoring the code could look like this:
class Board { String board() { StringBuffer buf = new StringBuffer(); collectRows(buf); return buf.toString(); } void collectRows(StringBuffer buf) { for (int i = 0; i < 10; i++) collectRow(buf, i); } void collectRow(StringBuffer buf, int row) { for (int i = 0; i < 10; i++) buf.append(data[row][i]); buf.append("\n"); } }
What basically has happened here is that methods have been extracted for each level of indentation. The whole class is so much more readable, unit testable, understandable… you name it. Or as the authors of the chapter puts it:
Try to ensure that each method does exactly one thing. One control structure, or one block of statements per method. [Heavy indentation] in a method [is] a signal that you’re working at multiple level of abstraction, and that means you’re doing more than one thing.
…
Working with methods that do exactly one thing, and classes doing exactly one thing, your code begins to change, [...] increasing exponentially the level of reuse.
Next time I will talk about rule 2: Don’t use the else keyword
ThoughtWorks conference on Scaling Agile
Posted by Ram Sundararajan in Innovation, Social, Values on June 9, 2009
As some of you might know, four of us here in Bangalore went to a conference/seminar at ThoughtWorks on ”Scaling Agile”. For those of you who do not know much about ThoughtWorks, they are a successful company with over 1000 employees in six countries. They are the fore-runners when it comes to Agile project management. ThoughtWorks also sells an Agile project management software called Mingle.
During the conference, it was very exciting to see how similar our work framework was to theirs. Does this mean that we are on the right track? Oh yes; not only by following one of the Agile principles of “reach the customer faster” but also by following some of our core values very effectively.
Right, below is what ThoughtWorks had to say about how someone whom they call an Iteration Manager should try to establish in his/her team (this role is bundled in the role that Lena and Jojo are doing at present…)
Iteration Manager should work toward a professional and accountable work environment. Such environments exhibit proper behaviors and mannerisms, such as the following:
- Mutual respect is displayed for self, others and customers
- Successes are celebrated
- Mistakes are treated as learning experiences
Strikingly relevant to what we already have, isn’t it? I will post you this book today.
Okay, going back to the conference, below are the key points we learned from there
- Programming is an art and software development is a social activity – Improve the conversation and you improve the software
- Embrace change – Dare to make a difference
- Rapid feedback – Develop to make your MUST HAVE work faster. Get rapid feedback from the customer. In our case, UxD and Test
- Continuous Integration – Check-in your code often. Create a test harness like Unit test and functional test simultaneously
- Face to face communication is a must – ThoughtWorks does it using video conference, chats, etc
- Make yourself easily accessible
- Make dev. Environments close to Production.
Apart from these, ThoughtWorks stresses on the importance of graphing out our project activities so that the Project Team and the stakeholders can find out the bottlenecks in the project now and then. I do not think that we do it today but they talked about the importance of maintaining charts which can be discussed on a weekly basis. This chart becomes more interesting especially during the retrospectives, if not immediately.
It was interesting to see how they keep track of the number of check-ins a day through a graph. At ThoughtWorks they say that they have a general rule that whenever a developer checks in a code, s/he is responsible for the aftermaths. If a bug is found in the recently checked-in code, it’s the developer’s responsibility to see to it that the bug is fixed or the code is rolled back within 5 hours.
When it comes to practicality, I would like to jot some things on the Continuous Integration part. I think that we have completely missed out on this part when we moved to the new Harvest model. ThoughtWorks has MOSCOW requirements in the product backlog. When the project is under implementation, the development team discusses the design aspects and implements the most important MUST have ASAP. They check-in their code (they said 20 times a day) to the main branch, and write unit test and functional test simultaneously and make sure the automation test passes really at the beginning. The test and the design team then picks up the task and works with them. Thus overcoming the “continuous waterfall” pitfall in the development cycle. The dev, design and test team work simultaneously on the tasks. Fantastic!!
We tried something similar to what they suggest here May sprint and it seems to have worked well for us. But again, we all in our roles need to make ourselves more accessible, else we will end up in the continuous waterfall.
Below are what ThoughtWorks thinks are challenges and options to overcome when it comes to scaling Scrum
|
Challenges |
Options |
|
Limited face to face |
Formal and scheduled communication channels like meetings chats, video conference |
|
Consistent view of big picture |
Scrum of Scrums |
|
Lack in clarity of responsibility/ownership |
Information radiation
|
|
Decision making |
Improve escalation points |
|
Knowledge sharing |
Communities and forums |
Below are the key take-aways from the presentation ThoughtWorks did during the conference.
- Program plan and governance – By governance they mean communication
- Continuous Integration
- Trigger points for structural changes – We need to get red hot at things that work less good and burn to improve it ASAP
- It takes more time to change
- Focus on Objectives, Principles and ADAPT!
Oosch! You know what? I think that the next time you guys come down here, we should make a visit to ThoughtWorks. They really have an open, flat, motivated and a smart work environment!