Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!
Software Development Blogs: Programming, Software Testing, Agile Project Management
Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!
Writing code is all about working at multiple levels of abstraction concurrently. But as well as working at multiple levels of abstraction there are also multiple levels of awareness of the code.
The most basic level of code awareness is just making the code work. Does this line of code compile, run and do what I intended it to do? While learning to code this lowest level of awareness consumes almost all our capacity: it is difficult to focus on anything else other than just typing in the correct syntax.
Once we’ve mastered typing in code that works there is another level of awareness: is the intent of this line of code clear? Will another human being be able to understand this? Hell, willÂ I be able to understand it in a month’s time? This is where code readability begins. While writing code we expend some of our mental capacity on making sure that the code will be readable.
Code legibility though is about more than just each single line of code in isolation. We alsoÂ need to consider whether this line makes sense in the context of the rest of this method, maybe we should extract a new method? Does this line of code make sense in the context of the rest of this class? Does the behaviour belong somewhere else? Does the design that I’m discovering actually make sense? Is it consistent? Is the pattern I’m implementing consistent with the rest of the application?Â Besides making each line of code compile there are numerous higher levels – rising through each of the larger structures in the application: the method, the class, the module, the component, the system.
Besides code legibility there are other factors to be aware of: will failures in this code be easy to understand, will exceptions help me get to the right part of the code quickly, what happens if things I depend on fail? Will this code perform well, in what scenarios and with what frequency will it be called? Is this code secure, are there ways for an attacker to take advantage of this code?
Writing good code requires developers to be aware of these levels all the time. However, if we’re tired, hungover or fed up we probably won’t give much time to these concerns. We’ll just make the code work that’s in front of us and ignore the bigger picture. When we’re lacking mental capacity, we tend to stop worrying about the higher levels and focus on the lower level, easier problems. “I’ll come back later and fix the design”, we tell ourselves.
This is where pairing can help. I don’t think it’s true that the pairing partner isÂ only thinking about the bigger picture; but the non-driving partner certainly has spareÂ capacity to think about these things and act as a conscience against the driver missing something or getting tired.
I like to use hands-on coding exercises in interview situations because it helps highlight how much awareness a developer has. Generally I’m looking for developers that, for a given problem, have enough capacity to solve the problem quickly and well. Less capable developers will generally take longer and/or solve the problem badly. In an interview situation though, there are extra levels of awareness, besides just solving the problem: is what I’m doing creating a good impression? Am I solving the problem in the right way (e.g. using TDD)? Is the way I’m solving the problem showing off the right skills?
For example a while back I interviewed a candidate who used “yield return”. This is an unusual thing to see, so I asked why use it? “To start a discussion about whether or not you should ever use it”. This I found quite impressive: a candidate with enough mental capacity to not only solve the problem at hand, in a good way; but still withÂ enough spare capacity left to realise that there was an opportunity to use an unusual construct purely to provoke a discussion of it – effectively driving the interview through code, to show off the depth of their knowledge and experience. This is the kind of person you want on your team: someone with enough spare mental capacity to make sure the code is clean and the design correct.
I think this lack of capacity is why the code we write when we’re tired or when we’re learning a new language or learning a new framework is bad: all our capacity is focused on just making the code work, we don’t have spare capacity to also think about whether the code is readable or whether the design makes sense. When we’re struggling to just make the code do what we want, to just keep the compiler happy, is it any wonder the outcome is a mess?
If you want to see how much mental capacity I can bring to your company, why not hire me? I’m looking for new roles right now – so drop me a line firstname.lastname@example.org.
So, if there is something simple I can do to help people feel better, and it does not require me to tell a lie, then I am willing to do so.
I want people to excel at their craft and be happy. That’s actually what is motivating me, underneath all my arguing.
In 1983, my boss, Dale Disharoon, designed a little game called Alphabet Zoo. My job was to write the Commodore 64 and Apple II versions of that game. Alphabet Zoo is a game for kids who are learning to read. The child uses a joystick to move a little character through a maze, collecting letters to spell words.
We did no user testing on this game until the very day we sent the final software to the publisher. On that day, we discovered that our target users (five year-olds) did not have the ability to use a joystick well enough to play the game. They just got frustrated and gave up.
We shipped anyway.
This game became a bestseller.
It was placed on a list of educational games recommended by the National Education Association.
So, how to explain this?
Some years later, when I became a father, I understood. My son was able to play a lot of games that were too hard for him because I operated the controls. I spoke to at least one dad who did exactly that with Alphabet Zoo.
I guess the moral of the story is: we don’t necessarily know the value of our own creations.
How best to organise your code? At one end of the scale there is a god class – a single, massive entity that stores all possible functions; at the other end of the scale are hundreds of static methods, each in their own class. In general, these two extremes are both terrible designs. But there is a continuum of alternatives between these two extremes – choosing where along this scale your code should be is often difficult to judge and often changes over time.Why structure code at all?
It’s a fair enough question – what is so bad about the two extremes? They are, really, more similar to each other than any of the points between. In one there is a single class with every method in it; in the other, I have static methods one-per class or maybe I’m using a language which doesn’t require me to even group by classes. In both cases, there is noÂ organisation. No structure larger than methods with which to help organise or group related code.
Organising code is about making it easier for human beings to understand. The compiler or runtime doesn’t care how your code is organised, it will run it just the same. It will work the same and look the same – from the outside there is no difference. But for a developer making changes, the difference is critical. How do I find what I need to change? How can I be sure what my change will impact? How can I find other similar things that might be affected? These are all questions we have to answer when making changes to code and they require us to be able toÂ reason about the code.
Bounded contexts help contain understanding – by limiting the size of the problem I need to think about at any one time I can focus on a smaller portion of it, but even within that bounded context organisation helps. It is much easier for me to understand how 100 methods work when they are grouped into 40 classes, with relationships between the classes that make sense in the domain – than it is for me to understand a flat list of 100 methods.An Example
Let’s imagine we’re writing software to manage a small library (for you kids too young to remember: a library is a place where you can borrow books and return them when you’re done reading them; a book is like a physically printed blog but without the comments). We can imagine the kinds of things (methods) this system might support:
This toy example is small enough that written in one-class it would probably be manageable; pretty horrible, but manageable. How else could we go about organising this?Horizontal Split
We could split functionality horizontally: by technical concern. For example, by the database that data is stored in; or by the messaging system that’s used. This can work wellÂ in some cases, but can often lead to more god classes because your class will be as large as the surface area of the boundary layer. If this is small and likely to remain small it can be a good choice, but all too often the boundaryÂ is large or grows over time and you have another god class.
For example, functionality related to payments might be grouped simply into a PaymentsProvider – with only one or twoÂ methods we might decide it is unlikely to grow larger. Less obviously, we might group printing related functionality into a PrinterManager – while it might only have two methods now, if we later start printing marketing material or management reports the methodsÂ become less closely related and we have the beginnings of a god class.Vertical Split
The other obvious way to organise functionality is vertically – group methods that relate to the same domain concept together. For example, we could group some of our methods into a LendingManager:
Even in our toy example this class already has six public methods. A coarse grained grouping like this often ends up being called a SomethingManager or TheOtherService. While this is sometimes a good way to group methods, the lack of clear boundary means new functionality is easily addedÂ over time and we grow ourselves a new god class.
A more fine-grained vertical grouping would organiseÂ methods into the domain objects they relate to – the recognisable nouns in the domain, where the methods are operations on those nouns. The nouns in our library example are obvious: Catalog, Title, Copy, User. Each of these has two or three public methods – but to understand the system at the outer level I only need to understand the four main domain objects and how they relate to each other, not all the individual methods they contain.
The fine-grained structure allows us to reason about a larger system than if it was unstructured. The extents of the domain objects should be relatively clear, if we add new methods to Title it is because there is some new behaviour in the domain that relates to Title – functionality should only grow slowly, we should avoid new god classes; instead new functionality will tend to add new classes, with new relationships to the existing ones.What’s the Right Way?
Obviously there’s no right answer in all situations. Even in our toy example it’s clear to see that different structures make sense for different areas of functionality. There are a range of design choices and no right or wrong answers. Different designs will ultimately all solve the same problem, but humans will find some designs easier to understand and change than others. This is what makes design such a hard problem: the right answer isn’t always obvious and might not be known for some time. EvenÂ worse, the right design today can look like the wrong design tomorrow.
After attending the #TAD2013 as it was on Twitter I saw a huge interest in better testing, faster testing, even cheaper testing by using tools to industrialize. Test automation has long been seen as an interesting option that can enable faster testing. it wasnât always cheaper, especially the first time, but at least faster. As I see it itâll enable better testing. âBetter?â you may ask. Test automation itself doesnât enable better testing, but by automating regression tests and simple work the tester can focus on other areas of the quality.
And isnât that the goal? In the end all people involved in a project want to deliver a high quality product, not full of bugs. But they also tend to see the obstacles. I see them less and less. New tools are so well advanced and automation testers are becoming smarter and smarter that they enable us to look beyond the obstacles. I would like to say look over the obstacles.
At the Test Automation Day I learned some new things, but it also proved something I already know; test automation is here to stay. We donât need to focus on the obstacles, but should focus on the goal.
After WWII Toyota started developing its Toyota Production System (TPS); which was identified as âLeanâ in the 1990s. Taiichi Ohno, Shigeo Shingo and Eiji Toyoda developed the system between 1948 and 1975. In the myth surrounding the system it was not inspired by the American automotive industry, but from a visit toÂ American supermarkets, Ohno saw the supermarket as model for what he was trying to accomplish in the factor and perfect the Just-in-Time (JIT) production system. While accomplishing this low inventory levels were a key outcome of the TPS, and an important element of the philosophy behind its system is to work intelligently and eliminate waste so that only minimal inventory is needed.
As TPS and Lean have their own principles as outlined by Toyota:
As these principles were summed up and published by Toyota in 2001, by naming it âThe Toyota Way 2001â. It consists the above named principles in two key areas: Continuous Improvement, and Respect for People.
The principles for a continuous improvement include establishing a long-term vision, working on challenges, continual innovation, and going to the source of the issue or problem. The principles relating to respect for people include ways of building respect and teamwork. When looking at the ALM all these principles come together in the âfirst time rightâ approach already mentioned. And from Toyotaâs view they were outlined as followed:
As the economy is changing and IT is more common sense throughout ore everyday life the need for good quality software products has never been this high. Software issues create bigger and bigger issues in our lives. Think about trains that cannot ride due to software issues, bank clients that have no access to their bank accounts, and people oversleeping because their alarm app didnât work on their iPhone. As Capers Jones [Jones, 2011] states in his 2011 study that âsoftware is blamed for more major business problems than any other man-made productâ and that âpoor quality has become one of the most expensive topics in human historyâ. The improvement of software quality is a key topic for all industries.Â Right the first time vs jidoka
In both TPS and Lean autonomation or jidoka are used. Autonomation can be described as âintelligent autonomationâ, it means that when an abnormal situation arises the âmachineâ stops and fix the abnormality. Autonomation prevents the production of defective products, eliminates overproduction, and focuses attention on understanding the problem and ensuring that it never recurs; a quality control process that applies the following four principles:
In other words autonomation helps to get quality right the first time perfectly. With IT projects being different from the Toyota car production line, âperfectlyâ may be a bit too much, but the process around quality assurance should be the same:
The defect should be found as early as possible to be fixed as early as possible. And as with Lean and TPS the reason behind this is to make it possible to address the identification and correction of defects immediately in the process.
I just came back from vacation and when I started again I noticed a slight change in resource requests I now see coming by; as almost all requests are with a statement around test automation. In the last two days I had two separate sessions around test automation tools. Has test automation all of a sudden become more important? Did people follow up on my last post, where I state that tools are a prerequisite in testing today, or actually: yesterday!
If you missed the latest cycle in new tools for test automation youâre either an ostrich with your head in the ground (âsorry vacation was in Southern Africaâ), or you just simply still afraid. Afraid of change that test automation would cannibalize your manual test execution.
Test automation is not anymore that it takes over test execution in a very complex and unmanageable way. No it offers higher efficiency on test design, test execution, but also more options to test certain non-functional parts of applications â that could not be done without those tools – like security and performance, and virtual environments to do end-2-end tests without test environments that are down all the time. Tools are now also offering more support for testing mobile solutions. Tools are everywhere!
Test automation offers us testers the opportunity to do more, faster, les risky, and cheaper. I set these words specifically in that order. Test automation is often seen as a way to do test cheaper. You can, but you also can do more, for instance:
There are enough reasons to work on test automation and I don’t see why not. I think now it is even time for the next step in test automation. What that is time will tell, but I look forward to hearing that at the Test Automation Day in June. Where Bryan Bakker will tell more on this next step in his presentation âDesign for Testability â the next step in Test Automationâ. After the congress Iâll post my ideas here.