Sunday 19 June 2016

The Scientific Method



Agile is made up of many aspects and means different things to different people.
I believe one of the things it teaches us is that we can't control the environment our software will be used in, our predictions are educated guesses and we must have an acceptance that we may be wrong in part or entirely.
In this aspect Agile development shares much with the scientific method, as developers we are conducting experiments with the goal of discovering what it is our users really want.
Constructing an Hypothesis
Whether were planning the release of an entirely new piece of software or adding a new feature to something already existing.
The need we are trying to fulfil might seem obvious, it may be based on feedback from our users or it may be an idea of our own invention. Either way whether or not users end up thanking us for its addition is not just about the idea but also the execution.
We should prepare to make changes after we ship, these changes may be big or small, we may be close to the mark of whats reuired or a distance away.
The important aspect is that we anticipate the need for refinement and give ourselves somewhere to go in the code.
Conducting the Experiment
The only people that can conduct our experiment are our users, they are the ones we are trying to provide value to and it is they who will judge if this value is being derived.
However feedback directly from users is often difficult to extract and interpret.
We therefore need a way to monitor their behaviour, a way in which we can measure the interactions and reactions people are having with and to our software.
For this reason analytics and instrumentation need to be a core part of what we ship.
Analytics to observe what users are doing, or not doing, with what we have given them and instrumentation to gauge the performance of our implementation.
Thought is required in what these key measures should be to avoid ambiguity but the data we collect represents the results of our experiment.
Interpreting the Result
We started with an hypothesis of how we thought we could please our users and add some value.
We put software in their hands and ensured we were collecting data on how it was being used.
Now we need to analyse the results of our endeavours and here we must not be afraid of a negative frame of mind.
It is all too easy in these situations to have a bias towards proving we were right. We knowingly or unknowingly construct our analytics platform to provide measures that will cast us in a positive light.
We should instead always be fearful that we may have missed something or not quite nailed it.
If we approach our analysis in this frame of mind and yet still the results prove that what we delivered was a hit with users we will truly know we got it right.
The flip side to this must be that we are accepting when the data proves we were wrong in part or wholly. This doesn't have to be seen as a negative, we've gained understanding of what doesn't work and this can feed a better approach.
Agile should all be about continual iteration and regular deployment of something new to users, if we get it wrong this time the next release is just round the corner and we will be better next time. 

Sunday 5 June 2016

Abstract Defence



The proper application of abstraction is potentially the most important skill an engineer can develop.
When correctly applied abstraction leads to loose coupling which in turns increases the possibilities for you code base.
However abstraction sometimes gets a bad name and is blamed for adding complexity, while this can be true when its badly applied we shouldn't let this blind us to the immense benefits it can bring.
Bad Code is Bad Code
The main criticisms of abstraction are related to it taking more time to implement and it adding more complexity.
No matter how your approach the problem you have to write code to solve it, by introducing abstraction all you are doing is taking time to think about the interface to that solution.
Thinking about how your code is used should not be considered an onerous task, time saved by not thinking about things is paid back in full when unintended consequences are encountered further down the line.
When the use of abstraction adds complication this is usually either because the architecture and implementation of the code is already complex or because abstraction is being badly applied.
Quite often this is because the abstraction won't hold up over time, the most common cause of this being the abstraction leaks implementation detail. Rather than being constructed from the point of view of the caller it screams details about what is happening under the hood.
When these details change the abstraction breaks and people get confused.
Why Abstract?
So how do we make sure we do apply abstraction properly, firstly why are we applying abstraction:
  • To reduce the surface area of change.
  • To control the interface to functionality.
  • Testability.
All three could be summed up by saying we want to remove dependency on detail.
Details change and we therefore want to reduce the code that gets re-written when the change occurs.
When we interact with a piece of code we don't want to interact with the detail we want to interact with the functionality.
When I'm testing my code I don't want to be testing the detail of a dependency.
If there is no detail we don't need abstraction, a class modelling a customer contains no implementation detail, its purely data driven with no secrets to hide. 
Where ever you see detail think about the functionality being offered that could be represented by an abstraction.
What to Abstract?
If we are to achieve this de-coupling of detail what are the kinds of things that we should be abstracting:
  • Technology.
  • Code we didn't write.
  • Code we might lift and shift.
The technology being used to save data, send data or work with data is detail with a high propensity for change and also has very little to do with the functionality being offered.
Its bad enough when change in code you wrote causes widespread change in your code base, the impact is felt even more when change in code written by a 3rd party causes the same disruption. In this instance you not only don't control the change you don't control its impact either.
Obviously a dose of realism is required here, I'm not suggesting you try and abstract yourself from the OS your code is running on. Instead you need to make a call, can I realistically protect myself from these guys making changes, sometime the answer will be yes sometimes no.
Finally as I've said many times, a good developer is a lazy developer who is always looking for opportunities to not write more code.
Code re-use is a much easier prospect when the wiring and plumbing aren't exposed. When you have a clearly defined junction between code requiring functionality and code providing it you will find all sorts of new ways to write once and run everywhere.
As with many techniques in development over using abstraction will degrade a code base, however the opportunities for abstraction to improve your code base are numerous and plentiful you just need to develop a keen eye for spotting them.