Jupiter Moonbeam & the Geeks from Cyberspace
Wednesday, 8 July 2009
Value Driven Development
The concept focuses around one very simple idea: the primary objective of a project is to deliver value. The more value we deliver the more successful the project is. If you agree with this then my next idea shouldn't be too hard to grasp: the primary measure of a project is value. Not velocity, not story points, flow, throughput, cycle time, capacity, cyclic complexity, code quality, but value, pure and simple. Of course we can use the other measurements to help us discover more effective ways of delivering value but on their own they tell little about how much value is being delivered.
Strangely, despite the fact that agile and Lean and Kanban and all of it's derivatives tell us how important value is none of them propose explicitly measuring it. Agile proponents often argue that it is their focus on delivering value early and often which makes them unique over conservative methodologies but how do they know? I've never picked a story off the wall and been able to tell what worth the customer gains by delivering it - ten, a hundred, a thousand, a millions pounds? Hell, who knows? The BA? The PM? The product owner? And how many projects out there can raise their hands to the question "How much value has your project delivered in the last week/month/year?" So if we're all so very value focused in our lean and agile worlds how are we not answering these simple questions? Are the statements about delivering more value pure assumption? How do we know that when we make 'improvements' to our processes the effect is to deliver more value? Or is at case of substituting value with story points mapped against velocity? If so how do you know that twenty-five story points to improve online advertising generated any revenue? Or is it a case of take the points and run?
Before we can confidently improve the amount of value we deliver we need to be measuring the value we are delivering. The first problem that presents itself is how do we do this? Value is hard to quantify and even harder to estimate. Which sound awfully similar to the problems with size so why not transfer the techniques used to estimate of story size to estimating value. Start simple, use relative sizes, but instead of t-shirts maybe use precious metals (aluminium, bronze, silver, gold, platinum etc.) or any other metaphor that helps the team visualize features in relative worth and as with size estimation it's an estimate, it doesn't have to be exact, the important thing is that we have some sort of gage and that we track it and refine it.
Once stories have value estimates they can go through the normal delivery process: estimate size, queue them up, stick them in iterations (or do some funky Kanban pulling on them). Except now every story card has it's most important piece of information branded to it: it's value. During prioritisation the platinum card which is the size of a small T-Shirt should obviously be delivered before the XXL bronze one. When stories are worked on people know that it's worth putting that extra effort into putting the plating on the platinum one but perhaps the aluminium story requires a more pragmatic approach than spending two days of cross functional refactoring to perfect it's design. During standups if someone says a platinum card is blocked the whole team knows it's important to get this sorted and coming up to a release with three gold stories complete but a stubborn bronze proving difficult to get across the line you may be more tempted to make the call to leave it out this time and hell to the size points. Very quickly every part of the process focuses around the amount of value being delivered, every decision is being influenced by the value of the story, not by it's size, not by how cool it is, not how much can be crammed into an iteration, but by how much value this piece of functionality is actually going to bring to the customer. Now that's being agile!
The purpose of putting values on stories is to measure how much value has been delivered. Now let's be clear about what delivered means: out there, in production, available to everyone who should have it, in full use. Basically, not dev complete, not in UAT, not in live pilot to a handful of select users, but out there live and in concert, fully functional, fully delivered, bringing value. Until then the functionality is worthless; until it is delivering value then you ain't delivered any value. Once it is though start totting it up: add the value points onto the delivery (note: delivery not iteration - iterations cannot deliver value unless they release), repeat for the next delivery plotting the value delivered on a chart and voila: the project's true velocity: how much value, for each delivery, it has been delivering.
But what if the value didn't quite get delivered? What if the functionality was released but with a bug which somehow hindered it's full capability? Maybe it is too slow, too difficult to use, doesn't do quite the right thing etc. Anything that prevents the application from delivering all of the value it promised is an issue (regardless of whether it is a bug or 'a feature'). However by resolving the issue the lost value can be reclaimed. By fixing the bug, performance or usability problems, the project claws back the value it lost when it didn't get it quite right first time.
It's important the project's value velocity reflects this. So when a fix is raised it is given a value which is then deducted from the velocity: this is because the full value of that feature was not delivered. Once the fix is in use and active then the value points go back on. Personally I find this one of the most powerful ideas behind measuring the velocity of value as the bad habits of delivering bug ridden functionality iteration after iteration by dismissing fixes in order to keep earning the points will not get you anywhere as the value velocity either struggles to move or even, in extreme cases, goes backwards.
I think there are many other benefits to be gained from using value as the primary measure that are yet to be discovered (possibly placing value onto technical debt? Though I'm not yet convinced of that one). Explicitly placing value at the forefront of the project gives teams the power to optimize themselves and discover new ways to improve their efficiency. And it isn't necessarily limited to individual teams: projects themselves should be measured in this way with teams 'contributing' to value - not simply earning points for delivering 'their part' - breaking down silo attitudes by finding ways to effectively work as a whole so value can be delivered.
I think it's pretty exciting stuff. Of course all the other metrics out there may or may not find use, dependant on whether they are contributing to the delivery of value or not, and holes will be found in the technique, but overall I think it shifts the debate and discussion forward to a entirely new level of thinking. It will allow us to reach a whole new level in the Value Enlightenment.
Wednesday, 28 January 2009
Getting the measure of Value
The idea behind measuring velocity in terms of value is simple and, at its core, doesn't greatly differ from the way in which we measure velocity now. Functionality is still broken up into stories (or MMFs if you prefer the Kanban approach) and they are still assigned points. The subtle change comes from what the points represent: not the size of the story but instead the value of delivering it.
The first problem with this is how to assign points of value to a story? Value is something that can be hard to define, that is variable and may be measuring different things (monetary value, visitors to a web site, time saved). Story sizing has similar difficulties so it makes sense that the solution is the same: estimation. Value can be estimated by having the team discuss a story and assign points to it. It doesn't have to be accurate - it's an estimate - but it does have to be representative and the more the project goes on the better it will get. The important thing is to decide on what a unit of value represents and as a team (customer, users etc.) agree to it. But guess what? Estimating the value of something is a core activity of most businesses and they should be both used to it and good at it to.
Which begs the question what should a unit of value be? This is highly dependent on the domain and type of business. In most domains value could simply be represented in terms of money: a story to allow people to purchase your widget online is the profit of the widget * the increase in the number of sales. In some domains it might be different, for example a web site (wikipedia for example) may measure value in terms of how many visitors it gets. Some domains may be more complex and have a combination of the two (or more): number of visitors and the money raised in advertising. In these cases the solution would be to find a common representation: maybe one visitor is worth £10 in advertising revenue (for example). Some domains may even express value in a way entirely different (schools: exams passed, hospitals: lives saved etc.). The important thing is that what the unit of value represents is consistent and meaningful.
Now stories have been assigned points which represent their potential value how does a team earn (or realize) them? If you read my last post you may remember that I started by explaining that in Lean you don't earn value until a customer receives it. This rule is extremely important and velocity should work the same way. Until the customer (or end user) has the functionality out there, working and in use the team does not get the points. Functionality not delivered, only partially delivered (delivered only to a pilot group etc.) or released but unused is not considered delivered - it is inventory - and therefore does not realize its value. Until the customer has realized the value then it is not recorded on the velocity.
Recording velocity in this way ensures that it represents the reality as perceived by the customer and aligns it with the rules of Lean. It should also change the way teams are measured and motivated: their focus switches from getting functionality out of the door to genuinely delivering value into the hands of the end user.
Thursday, 22 January 2009
Measure for measure (why we're doing it wrong)
One tenet of Lean is that the core activity of production is to deliver value to your customer. A second tenet of Lean is that something is not finished until the customer receives it. Only then do you record it on your balance sheet. Combining the two is a simple statement: the purpose is to deliver value to the customer; it is not delivered until the customer receives it.
Everything else is unimportant. Anything that is not contributing to the first tenet is waste (muda) anything that is produced but isn't delivered to the customer is inventory and inventory is also waste.
The relationship between productivity and value in Lean is fundamental. If something which is produced yet not delivered doesn't have any value then we have not produced. Regardless of how many hours worked, how many items output, how much blood, sweat and tears, if all you have created is inventory then you have as good as done nothing.
Measuring productivity has been a holy grail of software development. It sits at the heart of many of Agile methodologies. Thanks to essays such as The Mythical Man Month and with tools such as estimation, iterations, velocity and burn down charts Agile has moved us beyond measuring productivity with the highly flawed method of counting hours worked. Instead it breaks projects into units of functionality (stories) which are given sizes (points) relative to their complexity/effort. Productivity is then measured by totaling up the measure of effort once the functionality is completed and 'signed off'.
Using velocity to measure progress and productivity has resulted in a revolution in thinking. Using velocity teams are better placed to manage and schedule workload (scope) and much more able to accurately report what has been done and what is left to do. The result has been much more predictable and achievable project timelines.
However there is a disconnect between the customer (and user) and the producing team. The producing team is measuring its productivity based on how much effort is realized into working software. The customers success will be ultimately measured (whether they are aware of it or not) on how much value they have delivered (note the tense: not how much they potentially will/may deliver but HAVE delivered).
The result of this disconnect is that teams responsible for production are working within a model which is not based on reality. The real value of what they are producing is nowhere to be seen in any of the measurements or reports output by the team. The result is their measure of success being out of line with that of the customers. The team ends up working to its goal to maximize output of functionality but not to producing value.
Teams need to change the way they measure productivity to bring it inline with the way the customer is measured. To achieve this is simple: measure velocity in terms of value, not effort. And by keeping with the Lean tenet to only record value when it is delivered to the end user.
Monday, 1 December 2008
Examples as tests
To demonstrate this I am going to take a very simple function from MSDN on the C# ++ operator . Here is the extract of MS' example:
The increment operator (++) increments its operand by 1. The increment operator can appear before or after its operand:
RemarksThe first form is a prefix increment operation. The result of the operation is the value of the operand after it has been incremented.
The second form is a postfix increment operation. The result of the operation is the value of the operand before it has been incremented.
Numeric and enumeration types have predefined increment operators. User-defined types can overload the ++ operator. Operations on integral types are generally allowed on enumeration.ExampleOutput
// cs_operator_increment.cs
using System;
class MainClass
{
static void Main()
{
double x;
x = 1.5;
Console.WriteLine(++x);
x = 1.5;
Console.WriteLine(x++);
Console.WriteLine(x);
}
}
2.5
1.5
2.5
Although we are accustomed to these types of examples have a think about how hard you have to work to undertand it. The example on it's own gives no indication of what behaviour it is demonstrating (which is explained in complex english in the preceding text) and the call and the result are nowhere near each other - how often do my eyes have to refocus (look at the first Console.Writeline, then the first line of the output, then the explanation, match them up, look at the second Console.Wr... phew)? And this is just a simple example with a few behaviours.
Here is the same thing using tests (I've tried to closely match MS' own text for test names):
using NUnit.Framework;
[TestFixture]
public class IncrementOperatorBehaviour
{
[Test]
public void IncrementAsPostfixIncrementsValueByOne
{
double x = 1.5;
x++;
Assert.AreEqual(2.5, x);
}
[Test]
public void IncrementAsPrefixIncrementsValueByOne
{
double x = 1.5;
++x;
Assert.AreEqual(2.5, x);
}
[Test]
public void IncrementAsPrefixGivesResultAfterIncrement
{
double x = 1.5;
Assert.AreEqual(2.5, ++x);
}
[Test]
public void IncrementAsPostfixGivesResultBeforeIncrement
{
double x = 1.5;
Assert.AreEqual(1.5, x++);
}
}
How much clearer is that? You even have the satisfaction of seeing it all go green when you run them!
Sunday, 23 November 2008
Agile welcomes friendly aliens
Anyone who did philosophy or sociology - or was simply a sixth form socialist revolutionary - would probably have looked at Marx's theory of alienation. Whilst most people tend to think of Marx's economic theories the problem of alienation was of primary importance to Marx; to quote Ernesto "Che" Guevara:
"One of the fundamental objectives of Marxism is to remove interest, the factor of individual interest, and gain, from people’s psychological motivations"
Marx believed that all humans are naturally motivated by the creation of value and self development, thriving on challenges, regardless of class or situation. For example, take the stereotype of a football obsessed couch potato in a dead end job. Despite lacking in motivation in their work they seek pleasure from a study of football which is shared and developed with like minded friends. This study is so intense and focused it would put the most dedicated of academics to shame. How comes, under his own steam he can achieve so much yet is so despondent in his employment?
Marx argues the reason is that capitalism's methods of maximizing productivity actually create a system which alienates the worker and therefore fails in its aims. Inversely an environment without alienation is productive and produces value for all.
Marx described four types of alienation in labour:
1) From our product: we are separated from what we produce and its value.
2) From our productive activity: the product is outside of our control so work simply becomes a meaningless activity.
3) From other human beings (or other workers): we are isolated from each other, made to work independently, despite the fact that productivity is social in nature.
4) From our species being (or species essence): we are forced to specialize which removes the freedom to develop our capabilities therefore we loose stimulation and fail to be challenged.
Agile and Lean (though I am not sure if intentionally) recognize the problems of alienation and have strategies for removing them:
From our product
The importance of our role in providing value and creating a successful product are fundamental to Agile and Lean. Many practices focus directly on reducing the gap between the team and the end product such as keeping the customer close, delivering regularly and maintaing constant feedback. AgileLean is also focused on our role in creating value rather than simply meeting a set of personal objectives.
From our productive activity
AgileLean places us in control of the process and the system. Lean emphasis the importance we all have in the productive activity and empowers us to improve the process and eliminate waste. In Agile we are responsible and involved in all productive activities from planning and estimation, to picking up stories, to delivery and improving the agile process itself.
From other human beings
Agilists have always been keen on the social nature of development believing it to be imperative to the success of the project. Communication, knowledge sharing and working together is actively encouraged with techniques such as pairing, stand-ups etc. AgiLean environments are made up of people working closely together as a team rather than individuals in a group.
From our species being:
AgileLean is often critical of specialization. Instead agilean prefers cross-functional teams made up of multi (highly) skilled generalists. This creates an environment were people are challenged and are free to develop, on a day to day basis, in the directions they choose and not reduced to the criteria their performance management chart dictates.
The S and M labels often make people feel nervous, in some cases to the point of rejecting ideas completely because of the connotations. Socialism isn't short of its critics but agile and lean prove how we can address some of the most important concerns Marx had with the capitalist system in a way that makes business stronger (just look a Toyota's huge success in a very aggressive capitalist market compared to its more communist fearing cousins in the States). The success of agile and lean prove how much more productive we can be when we tackle the problems of alienation. This is why many of us find it so frustrating to see teams labelled agile who still operate in an alienated way.
Agile and lean teaches us that teams who recognize alienation and address it are ultimately more successful. By explicitly seeking to address alienation we can create healthier working environments which offer greater value at a higher rate of productivity. Now what right minded capitalist wouldn't want that?
Wednesday, 19 November 2008
That's right: blame Agile
There has been a great debate happening over the airwaves of the blogosphere recently. Sparked of by James Shore's post The Decline and Fall of Agile it has gotten to some people declaring the death of agile and others calling for the rejection of the term altogether [link]. It's as if the Nazi party has just announced that the Third Reich was built on Scrum and suddenly everyone is trying to distance themselves: "no we never agreed with that agile stuff, what we were talking about is something completely different".
Around the same time another debate is picking up steam started by Roy Osherove's post Goodbye Mocks, Farewell Stubs. Apparently people find testing too difficult to grok so we need to reject terms like mocks and stubs ('cos though accurate they are apparently confusing) and replace it with another: Fakes. Oh the glaring irony as one side of the movement is rejecting marketing terms because too many people who use it don't know what it means while the other side try to introduce more marketing language to attract the people who don't know what it means.
Uncle Bob has dropped in like Batman at the Jokers party and delivered his direct, powerful blow: "the problem is you're all f*ing lazy". Although I feel that Uncle Bob is much closer to the truth than many other commentators he's not really offering a realistic solution out of the mess.
So what exactly is the problem we've got here? Both of these posts have something in common. James Shore's issue stems from teams picking up words like Scrum and Sprint and forgetting that they have to write decent code as well. Roy Osherove's post stems from the fact that getting teams to even write tests is met with constant failure. Both posts talk about a general lack of engineering skill in IT. In reaction different parties are offering up different solutions but they all fail to address the core issue.
For those jumping the agile ship and getting onto the next coolest speedboat what exactly is that going to prove? Rather than improving the industry it leaves it helpless and sinking. This is a rotten attitude that resolves nothing: when every PHP and VB programmer converts to Ruby what you gonna do then? Oh it's OK Ola's writing Ioke and if that doesn't work we've always go Lisp (they'll never get that). Roy Osherove's solution of lowering barriers to entry is more commendable but will achieve just as little and is guilty of another great crime: dumbing down (though he's spot on about tool support). I don't think the solution to poor engineering skills are to withdraw important technical terms: can you imagine the Bar rebranding legal terms because, y'know Lawyers just find it too difficult to understand this stuff or Doctors calling for less names for the organs 'cos med students these days just can't get the point of having the terms stomach and intestine and they keep operating on the wrong one. Why can't we just call it the food processor? Jay Fields' novel idea is to ask them all to politely leave (50% of them in fact). And if they don't? Well then I guess we'll all get together and go around with a big seal club and sort it out that way (it's what I refer to as "The Great Culling" - there's those Nazi's marching past again).
The real problem, the root cause to all this is simple (and on this most agree especially Uncle Bob and Jay): the gross under valuing of the skills which enable you to do your job. The thing is it's nothing new. It was there before agile and TDD had the impact they do today (they just laughed then). Remember those not so long ago days when people thought the solution to delivering software wasn't skills or focus on quality but getting some glorified secretary to type up several hundred pages of requirements and then handing them to some supposed genius to design everything for the monkeys to punch in? Well we're still there people: it's just they thought the solution to the mess that disaster caused was to do something called iterations, standing up and getting the monkeys to skip around the genius guy wrapping him in his own ribboned UML diagrams chanting "architect, architect, architect".
Nothing's changed, agile or not. The majority of the industry still doesn't value the basic, fundamental skills it takes to write software of acceptable quality. It didn't before and it still doesn't now. Instead it's obsessed with solving the problem by bringing in the right highly paid manager with the right powerpoint presented methodology. Until the industry gets that ain't the way it will drag every shining beacon of light (agile, Ruby whatever) down into Hades with it.
Writing software is about people People! That's what agile and Lean and all their friends tell you again and again. The fundamental principles are about people, not iterations, continuous integration and story boards. Go check out the Agile Manifesto and tell me where you see any of that stuff? This bastard form of agile which only talks about tools and processes is like someone got the manifesto and spun it round (People OVER Process read it Again). The practices and tools are there to actively encourage developers who are skilled, committed and know what they're doing and make them more empowered and productive and ultimately deliver MORE value and success, they are not there to replace them.
So what is the solution? The simple truth is that those of us who understand the problem have got to keep doing a great job, we've got to help those who want to do a great job but aren't sure how to do a great job and we've got help those who don't understand how to do a good job and may never will and may not even want to. Sure it's depressing sometimes, it's frustrating but we can't just give up on the industry and jump away on the next term or simply dumb the whole thing down so the next generation can get it a little more but ultimately still fail to get it.
Agile was never, is never going to be an quick, faultless success forever preserving an eternal purity. Our industry is sick, real sick. It's a beer guzzling, chain smoking, couch potato who's been told by his doctor to eat healthily, give up smoking and booze and get some exercise but instead just swallows the agile pill and hopes that's enough to save his sorry fat arse. And surprise surprise when the casualties start coming in their gonna blame those pills.
We have generation after generation bought up on bad practices and incorrect assumptions (smoking isn't bad for you, exercise gives you heart attacks) and what's worse most of them don't even know how bad things are: they think this is NORMAL (sadly because IT IS), they've adjusted to a certain degree of failure. IT projects are like lifts: sure your pissed off there broken down but your not surprised, you even kinda expected it.
The mess is big and it's gonna take years to sort it out and a lot of hard work. And yes, along the way people are going to buy the agile weight loss pill from some dodgy site on the Internet without seeking professional advice, get it wrong. And why? Because they're desperate!
It was totally delusional to think agile was going to result in everyone suddenly rejecting their bad habits and come crawling on their knees and go XP Kosher. And when that didn't work well there's always the prophesy of the True agile warriors standing in the post-apocolyptic world looking down on the dying as the last breath of those Tragic Lost sigh the now infamous regretful words "we wish we'd read our Domain Driven Designs". Well don't worry because to become agile all you have to do is close your eyes and say "please Kent forgive us our hacks and deliver us not into Waterfall" and mean it, really mean it, and wait, above the mountain there what's that? is it who I think it is? It is: the heavens are open and Martin Fowler is ascending into them.
Let's get real here: developers who have never come across TDD before, who've never experienced it's value first hand, who've spent years doing things a certain way are struggling to grasp the concept and oh sorry that's surprising why? I guess you were doing TDD from that first Hello World in Pascal? And those people who go in and try Scrum for the first time and find they are riddled with technical debt because gave into pressure and didn't invest in quality. Now stand up and be counted all you who never made that mistake.
I'm not saying that we should just let these things go, hold our noses, ignore the smells and step over the shit. Quite the opposite. But we've got to accept that we're not going to walk into a room of professionals and get them to convert overnight (or year or possibly even decade). How many years did it take before doctors accepted germ theory and started washing their hands?
Though there is hope: the most effective weapon we have is success. By being successful and then telling people about why and how we were successful. That's how this whole agile thing started, that's how it built up it's great reputation and that's how it's going to survive and get better. The more success the more people will start to realize that what they're doing now isn't as good as they think. Right now not testing, not caring about quality, high technical debt: that's the norm, that's expected. Keep being successful and people will start asking the others those awkward questions: why does this application crash when my last team were virtually bug free, why does it take a weekend to get a release out when my last team did it in a few minutes? Why does it take six months to implement a new feature when my last team took a week? What do you mean there are ramifications and complications? The more we deliver quality software the less room people will have to worm out of those questions and then the tipping point will come.
Let's not be mistaken, it's going to be hard work: but isn't that the whole point? Writing software is hard, agile doesn't change that and at first TDD certainly doesn't. Yes it's frustrating and somedays you really want to scream and kick in the can but what's the alternative IT ghettos sucking in grads and with no way out?
If, in the years to come, we want to work in a different industry then we've got to take some responsibility for helping create it.
Thursday, 6 November 2008
Make me Whole
This is one of my favourite refactoring patterns and one I find I use a great deal so I thought I'd share it. The basic premise of this refactoring is to encapsulate logic into its own class using small, easy steps. The trick is each step should always leave the code in good working order i.e. the tests should always pass.
To help explain I'm going to walk through the refactoring by encapsulating some simple procedural logic and by making the concept explicit by giving it it's own class. Here's our starting point:
def say_hello()
if @friend == "Jeff" || @friend == "Robert" do
put "Hello my good friend #friend"
else
put "Hello #friend"
end
end
The first thing we notice is there is some behaviour which depends on the state of friend (is the value "Jeff" or "Robert"). This is a good sign that there's a concept called Friend which needs encapsulating. So here's how:
Step One: Extract method
The first step is easy: extract the logic into it's own method like so:
def say_hello()
if is_good_friend do ...
end
def is_good_friend
@friend == "Jeff" || @friend == "Robert"
end
This is good, now the code is clearer to read and we've encapsulated the logic (albeit only in a method). That's already a big improvement.
Step Two: Introduce parameter
The problem is our method is dependent on its class for the @friend variable. We need to sever this connection so the method can stand on its own two feet. The simple way is to pass friend through as a parameter.
def say_hello()
if is_good_friend(friend) do ...
end
def is_good_friend(friend)
friend == "Jeff" || friend == "Robert"
end
That's better: is_good_friend is decoupled from the class. Its free!
We still need to get that method onto a new class. The problem is it can't be done in one easy non-breaking step. So we're going to have to take a tiny intermediate step to get there:
Step Three: Make method static
By making the method static it severs all connections to the original class: it is explicitly non-dependant on any instance variables the original class has.
def say_hello()
if self.is_good_friend(friend) do ...
end
def self.is_good_friend(friend) ...
Making the method static is also a good safety check to ensure that you've not got any references to the original class and it is properly isolated before moving it.
Step Four: Move method
Now the method is static move it to the new class:
def say_hello()
if Friend.is_good_friend(friend) do ...
end
class Friend
def self.is_good_friend(friend) ...
end
Excellent, we're really getting somewhere! Though now we've got a static method sitting on a helper class. Yuk: let's get that sorted before someone copies us and that nasty anti-pattern starts to proliferate through our code base:
Step Five: Create instance
This is where the real magic starts to happen: we create an instance of our new class and use it to store the value of friend:
class Friend
@value
def self.is_good_friend(old_friend)
friend = Friend.new(old_friend)
friend.value == "Jeff" || friend.value == "Robert"
end
end
Still, this is a bit ugly. What we really need to do is get the client to do the work of creating the instance.
Step Six: Introduce parameter
Rather than have our static method new up Friend get the client to do it and pass it across:
def say_hello()
if(Friend.is_good_friend(@friend, Friend.new(@friend)) ...
end
class Friend
...
def self.is_good_friend(old_friend, friend)
friend.value == "Jeff" || friend.value == "Robert"
end
end
Step Seven: Remove parameter
The old_friend parameter is redundant and ugly: let's get rid of it!
def say_hello()
if(Friend.is_good_friend(Friend.new(@friend)) ...
end
class Friend
...
def self.is_good_friend(friend) ...
end
Excellent, this is starting to look a lot better now. Though look at that repetition: the static method on Friend passes an instance of it's own class! Only one way to sort that out:
Step Eight: Make method non-static
Now the beauty of this is that if you are using a modern IDE it will work out that the method is being passed an instance of its own type and it will magically do this:
def say_hello()
if(Friend.new(@friend).is_good_friend) ...
end
class Friend
def is_good_friend
@value == "Jeff" || @value== "Robert"
end
end
Brilliant: Friend is now nicely encapsulated and ready to grow into a responsible object with a bright future. From here we can start pushing more behaviour onto the object and eventually make @friend reference an instance of the Friend class.
Overall the pattern is very simple: extract the logic into its own method then work to detach it from the class by making in static, then simply move the static method and reattach it to the new class by returning it to an instance. It is also possible to handle more complex behaviour with several variables involved, simply pass them through as parameters and then push them onto the new instance.
Although this example is simple the pattern can be repeated again and again to build up classes into a number of methods (sometimes these classes can again be refactored into smaller classes still).
Blog Archive
About Me
- Peter Gillard-Moss
- West Malling, Kent, United Kingdom
- I am a ThoughtWorker and general Memeologist living in the UK. I have worked in IT since 2000 on many projects from public facing websites in media and e-commerce to rich-client banking applications and corporate intranets. I am passionate and committed to making IT a better world.