March – 3rd Agile Principle

Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.

You might wonder how the third agile principle differs from the first. The first principle talks about “early and continuous delivery” of software. This sounds a bit similar to “delivering software frequently”. However, there is a significant difference. The first principle is all about customer satisfaction. It is realised by continuously delivering value to customers. The third principle is all about method. The principal method used to achieve the goals of the first principle is development in iterations. An iteration is a defined time span during which the entire software development life cycle (SDLC) is traversed. An iteration starts with requirements analysis and ends with software delivery. It can be modeled as a closed and repeating cycle.

If we recall the waterfall model, there are some major differences. Mot importantly, the waterfall model traverses the software development cycle only once. This usually takes a much longer time. It is common that the duration of this long-term traversal cannot be predicted exactly. For that reason, deadlines are often postponed. Another major difference is that roll out/deployment and maintenance phases are periods at the end of the waterfall SDLC, whereas agile methods do not stipulate predetermined phases for these activities at all. Agile teams carry out maintenance “on the go”; it is part of the normal development work.

The time frame of an agile iteration is more rigid, by contrast. It is commonly fixed and takes anywhere between a few weeks and a few months. For example, teams that use Scrum often work in cycles of 2-4 weeks. There is no delay or postponement. Instead, if a feature is not ready, it is moved to the next iteration. The quantity of work completed within this relatively short amount of time is of course much smaller. So, at the beginning of each cycle, the team continues to build upon the foundation laid in the previous cycles. The process is therefore also incremental. This has certain advantages for both developers and clients.

Let’s state again that the agile process is both iterative and incremental. This is important. At the end of each iteration, new features and fixes are demonstrated to the stakeholders. In many cases, the iteration also results in a release, which means that software is deployed to production at the end of a single iteration. However, this is not written in stone. For example, a team may decide to work in 2 weeks iterations while adopting a release cycle of 4 weeks to match maintenance windows. Another team may prefer a continuous delivery model where features are released to production as soon as they become available.

It does not matter, as the iteration is not strictly coupled to the release plan. What matters is that software is delivered frequently and that the time span of an iteration is kept as short as practicably possible. This makes for a short feedback loop which allows stakeholders to intervene quickly. It increases the control of business stakeholders and allows for an amount of flexibility that is impossible to attain with the traditional waterfall process. For example, change requests and bug fixes can often be implemented and released within a single iteration making for a time to market that can simply not be achieved with any other method.

From what has been said, it follows that the agile process is also evolutionary and adaptive. Because large scale features are built incrementally over the span of multiple iterations, developers build on the foundation of existing architecture and functions. New blocks of software are added to existing blocks. Existing blocks are sometimes refactored or changed. It is therefore possible to test concepts in practice before a feature is completed. It is also possible to improve concepts and functions over the span of multiple iterations. The end result is always working software.

This means that software features, especially large scale features (called “epic” in Scrum methodology), are not typically conceived at the drawing board. Instead, prototypes and proof-of-concepts make their way into working software long before the planning and implementation of a large scale feature is completed. This is another major difference to the waterfall model. The key advantage provided by a short feedback loop is that bugs, logical errors and flawed concepts can be spotted and corrected early. This keeps the cost of such improvements to a minimum.

Because the evolutionary and adaptive nature of the agile software development process, planning and design is often restricted to a relatively small time frame and is open to change. For example, the requirements for implementing an epic could change midway during one of the many iterations it takes to complete the epic. In some cases, these requirement changes necessitate rethinking and altering existing features or even rethinking architecture. Code refactoring, the restructuring and improvement of existing code without changing its functionality, is therefore very important in agile development. Without continuous refactoring, agile projects are in danger of accumulating technical debt.

Continuous refactoring is perhaps the price that has to be paid for the extreme flexibility and quick time to market that agile development affords. A team that follows an adaptive approach must guard against code smells and software entropy. Only with sustained attention to these problems, software will stay maintainable and extensible in the long run.

The Open Closed Principle Revisited

An interesting discussion came up in a recent code review. Looking over the OOP implementation of a menu class, a colleague remarked that classes should always be designed open for extension and closed for modification. Sounds right, as it reflects generally accepted OOP practices. The open-closed principle, the “O” in SOLID, is an essential principle of sound object-oriented design. You probably already knew that. Here is the initial design of that class.

class Menu {
private constructor()

static createForUser(user: User) : Menu
static createForLegacyUser(user: LegacyUser): Menu

public getThisMenu(): MenuData
public getThatMenu(): MenuData
public getAnotherMenu(): MenuData
}

The menu class can be instantiated in two different ways, either with a regular user or with a legacy user. Both user objects provide authorization via ACL. The menu class has several getters that return different menus. The dynamically created MenuData contains only the menu options the user has access to. The private implementation methods are omitted. These perform authorization using the user objects and also translate the menu items into the user’s UI language. The menus themselves are configured in external YAML files and their structure can be changed as long the expected YAML format is maintained.

As you can gather from the design, this class is not designed with extension in mind. It is possible to add other menus, but only by extending it and adding a getYetAnotherMenu() method. Unfortunately, inheritance is not very practicable here. Extending for other types of users isn’t possible at all, because the respective authorisation code would have to be added to the implementation. Let’s summarise:

  1. Very easy: adding or removing menu options and sub menus to the existing menus
  2. Possible, but not that easy: adding or removing menus
  3. Not possible: adding other types of users

An obvious weakness of the above design is the redundancy in the getters and the fact that the menus themselves are fixed. This can be improved quite easily:

class Menu {
private constructor()
static createForUser(user: User) : Menu
static createForLegacyUser(user: LegacyUser): Menu

public getMenu(menuIdentifier: string): MenuData
}

Instead of invoking it with menu = Menu.createForUser(user).getThisMenu() to obtain menu data, this class is now invoked with menu = Menu.createForUser(user).getMenu(‘thisMenu’). The identifier is associated with the respective YAML file from which the menu data structure is created. Let’s summarise again:

  1. Very easy: adding or removing menu options and sub menus to the existing menus
  2. Very easy: adding or removing menus
  3. Not possible: adding other types of users

At this point, I was quite happy with the simplicity and flexibility of the design. We’ve made it both easy to extend menu options as well as menus themselves. My colleague, however, wasn’t happy. He insisted that the open-closed principle must also be applied to user types. And this is where it gets philosophical. Of course, it is possible to do that. But it requires significant changes and a further abstraction. We need to remove the authorisation implementation from the menu class, create an Authoriser interface and provide Authoriser classes for regular users and legacy users that implement Authoriser.

class Menu {
static create(authoriser: Authoriser) : Menu
public getMenu(menuIdentifier: string): MenuData
}

interface Authoriser {
boolean authorise(role: AclRole)
}

class RegularUserAuthoriser implements Authoriser {
constructor(user: User)
authorise(role: AclRole)
}

class LegacyUserAuthoriser implements Authoriser {
constructor(user: LegacyUser)
authorise(role: AclRole)
}

Why philosophical? Because, while this is a textbook implementation of the open-closed principle, we have never added any other user types in years. The system has only two types of users: regular users and legacy users. The likelihood of having other types of users in future is almost nil. This raises two questions: First, is the cost of extensibility and extra abstraction justified? This change obviously makes the code more complex. Second, how do you know what kind of extensibility will be required in future?

I would answer the first question with “no”. It is not worthwhile complicating the design to achieve extensibility if this extensibility is not needed. Doing so would constitute a YAGNI antipattern. YAGNI stands for “you aren’t gonna need it” and originates from the core principles of extreme programming (XP). According to XP, features should be implemented as simple as possible and without making unwarranted assumptions about future use cases. This is very much related to the KISS principle, which in turn has its foundation in philosophy: Occam’s razor and the law of parsimony. In practical terms: the simplest implementation for a given requirement is the best implementation.

If you paid attention, you might already see the dilemma. There seems to be a contradiction between YAGNI and the open-closed principle. If we design a class that is open for extension and closed for modification, this usually means we have to define additional interfaces that formalise the extensible behaviour. This is to say, the open-closed principle results in increased complexity, contradicting KISS, YAGNI and Occam’s razor. So, what should we do?

Consider the second question we have asked before: how do you know what kind of extensibility will be required in future? Simply speaking, if you don’t know, then don’t build it. Classes usually contain more than a sinlgle dependency and a single behaviour. Designing extensibility into each dependency and behaviour is a very bad idea, because it would make the design extremely complex. The open-closed principle should be applied in situations where the need for extensibility is either established or very likely. The “O” in SOLID must not be applied indiscriminately..

Contemplate the following quote of former US secretary of defense, Donald Rumsfeld:

There are known knowns. There are things we know that we know. There are known unknowns. That is to say, there are things that we now know we don’t know.. But there are also unknown unknowns. There are things we do not know we don’t know.

At first, this statement sounds a bit perplexing, but it makes perfect sense. It can be applied to our OOP problem as follows:

The known knowns are the features described in the functional and technical specifications. They are spelled out unambiguously and can therefore be translated directly into concrete implementations. The known unknowns are the features that we can predict, but their concrete implementation is unknown. This is where the open-closed principle applies. For example, if we write a printer spooler, we know that the spooler should work with all sorts of printers, although we don’t know the concrete printer models. Therefore, we provide an interface that can be implemented for any concrete printer model which he spooler then uses to perform its function. Finally, the unknown unknowns are the sort of features that we cannot predict at all.

As mentioned, designing extensibility for unknown unknowns results in unneeded complexity. The same is true for the known knowns since they are fixed. There is no need to design an interface for a class if we already know that there will be only one concrete implementation. Hence, the open-closed principle makes sense only for the known unknowns, namely the situations where feature extensions can be predicted with some degree of certainty.

February – 2nd Agile Principle

Welcome changing requirements, even late in development. Agile processes harness change for the customer’s competitive advantage.

The second agile principle can be expressed in two words: embrace change. It is an appeal in opposition to the traditional fixed cost waterfall model. The waterfall model makes change as hard as possible. Every time a requirement changes, the waterfall model prescribes that specifications are rewritten, the estimate is updated and the contract renegotiated. As this involves considerable administrative effort, there is a high barrier to change. This barrier is intentional, because change is considered detrimental. The waterfall model attempts to eliminate uncertainties and perceives change a risk to project success.

However, if you have worked in project management for any length of time, you will know that change is inevitable. Organisations and businesses are not static. They grow and evolve. Their external environment puts them under constant pressure. Markets, competitors, changing regulations, and new technologies force organisations to respond and adapt. Likewise, internal changes happen all the time. When an organisation expands or takes on new projects, for example, internal structures and procedures often require overhaul. This in turn means that software requirements change. Because the degree to which organisations are computerised is increasing, the rate of software requirements change is also increasing. Consequently, we can expect that change is a constant and that the pace of change accelerates.

This is were the second agile principle comes in. The agile philosophy accepts change and uncertainty as “facts of life” so to speak instead of creating an artificial bulwark against it. The very meaning of agility is defined by this principle and this is a major departure from traditional project management. It is important to understand the implications of embracing change. What does this mean for the software development lifecycle and how does it affect the planning process? One can’t deny that welcoming change implies welcoming uncertainty, because change is hardly ever predictable. The farther one tries to look into the future, the less predictable it becomes. But how do you welcome uncertainty in project planning? The agile answer to this question is temporal focus.

In agile frameworks such as Kanban and Scrum, project goals are well defined only for the present and for the immediate future. For example, Kanban is like a pipeline where the focal point is narrowed on the tasks that are currently flowing through it. These tasks are described in detail, whereas the tasks that are queued receive less attention. Scrum is an iterative framework where the focus is on the current iteration (Sprint), whereas the backlog is out of focus. This means that tasks in the intermediate future are less defined. The degree of detail is limited and the time and effort estimations are rough. Tasks in the farther future are even more fuzzy. There may be large scale goals, roadmaps and ballpark estimates, but these are open to change. So, an important difference to the waterfall model is that projects are not determined from beginning to the end.

The fuzziness of long-term and indefinite future projects is not necessarily a disadvantage. It is the price of agility, so to speak. It affords nimbleness and the ability to harness change, which brings us back to the phrasing of the second agile principle. What exactly does it mean to “harness” change? Wasn’t change something that traditional project management tries to avoid? At the basic level, harnessing change means not being overwhelmed or overrun by external events. This is something that happened all too often in the past. Because agile methods are lightweight by definition, the agile team can respond and adapt to external changes quicker and more gracefully, even if such changes entail undesirable aspects.

At a more advanced level, change is proactive and initiated by the project team. For example, the project team might decide to adopt a new technology, or it may decide to include new features, or it may respond to a specific competitive challenge. The possibilities are endless. Because the cost of rethinking and overturning things is low in comparison with traditional project management, agile methods excel in responsiveness. This is especially relevant in environments that develop at a fast pace, such as emerging markets and technologies. Which brings us to the last term of the second principle: the customer’s competitive advantage. A competitive advantage is created when an organisation gets ahead of its competitors. Being the first to release a new feature or a new technology, for example, creates a competitive advantage. Agile project management is uniquely suited to such achievements.

January – 1st Agile Principle

Our highest priority is to satisfy the customer through early and continuous delivery of valuable software.

The year has 12 months and agile development is based on 12 principles. Today, let’s start with the first agile principle. It is about customer orientation, perhaps the main motivation for agile development. Some of you might know, that it is now 18 years ago since a group of software engineers came together in Snowbird, Utah for a brief winter conference on project management. The result of that meeting was the well-known Agile Manifesto. It had a big and lasting impact on the software industry. Somewhat later the Agile movement started out and today, agile methods can be considered mainstream. However, back then things were different.

At university and during the early years of my career I learned that software development is divided into six stages. It starts with requirements analysis followed by three production phases, followed by deployment and maintenance. It was understood that the software development lifecycle (SDLC) phases are strictly linear and sequential. One is completed after the other. The customer is only involved in the first and the two last of these phases. Software companies spent enormous efforts on analysis, planning and documentation in order to get cost and time estimates right. Customers had to be enormously patient to wait for functioning software and they had no say in its production.

This process carried significant risks and turned out to be frustrating for both parties. Although customers initially received detailed contract specifications and a fixed price offer, the product was regularly late and below expectations. Even worse, some requirements changed during implementation and thus the software was already outdated at the time of delivery. Another costly change order was then inevitable. Things weren’t much better for developers. Unforeseen events and technical difficulties led to exceedance of cost and time estimates. In the worst case scenario, these circumstances left the developer unable to fulfill the contract and pushing towards bankruptcy. The client received either no product, or an unusable product for their investment.

In 2001, I was managing my second startup company and had no intention of repeating past mistakes in project management. Like many others at the time, I used a homegrown set of lightweight methods for SDLC management. I had acquired these during the late nineties in my practical work with different clients. I knew nothing about the Agile Manifesto at the time, but I found that the traditional waterfall approach didn’t work for us. Instead, I visited my clients every two weeks. During a long meeting which often took the larger part of a day, I would first present the new features that my team and I had developed. I would then install the update on my clients’ servers (this was well before the time of Internet-based deployments). Finally, I would discuss the most-wanted features and changes for the next cycle. There was an understanding that if the client found any bugs, they would be fixed immediately within a single release cycle.

Why did this work so well? Because the customer was always kept in the loop. They received usable software every two weeks that provided actual business value. They could control and even participate in the design process. They could correct mistakes early. Last but not least, their financial commitment wasn’t burdened by huge risk, because they paid monthly installments. This way of working puts the client in control and keeps them happy. And this is exactly what the first agile principle is about. I learned about agile project management only some years later and I found it to be an excellent fit for what we were doing. It confirmed our practice as a development company and it also broadened and enhanced our methods.

The reason why the this principle is the first, is given in the beginning clause: our highest priority is to satisfy the customer. Fundamentally, the agile methodology is about customer satisfaction. Normally, the customer is thought of as a third party outside the software company, but it could very well be the same company doing in-house development. It doesn’t matter. In the latter case, the customer role is filled by another department within the organisation. It is important to note that neither technical goals, nor abstract principles of management provide the foundation for agile development, but business goals. The middle part of the sentence mentions early and continuous delivery. This makes perfect sense from the perspective of developers, because software artefacts evolve and grow in small incremental steps. It also makes sense from the perspective of the customer, because they can begin using individual features before the entire package is completed.

Even more benefits are reaped by early and continuous delivery. The customer can control and prioritise the development of individual components. Mistakes can be corrected cost-efficiently at an early stage. The customer can verify or invalidate concepts in practical application. Developers are able to create proof-of-concepts without committing to a specific design or technology too early. Finally, the first agile principle speaks of the delivery of valuable software. The value of software is what clients and developers ultimately aim to realise together. This always translates into some sort of business value. For example, the software might enable the client to respond faster to their own clients. Or it may automate some task which previously had to be done in a tedious manual way. Or it may enable the client to gain deeper insights into markets, opportunities, and risks. The possibilities are endless. The sooner the software enters production stage, the earlier the customer can reap its benefits.

In summary, the first principle encapsulates the motivation and mission for agile development. It’s all about customer satisfaction and providing business value through software.

Coding interviews – rad or fad?

As a developer, you probably have gone through one or more coding interviews. When applying for a developer job, you are expected to demonstrate some level of programming chops by solving algorithmic problems on a whiteboard or in an online code editor. This practice is not new. My first coding interview took place more than 25 years ago sitting at a lovely green text terminal. However, it has recently proliferated and became an integral and often time-consuming part of the interview process. Especially big American tech companies like Amazon, Apple, Facebook, Google and Microsoft are pushing the envelope. To land a developer job at one of these companies, you are now expected to be able to recite the finer points of an algorithm manual and produce solutions with O log(n) time complexity in a trice.

Does that sound just slightly ridiculous to you? Perhaps it is. The question one must ask is whether having candidates produce algorithms is actually a good indicator for success in the software development profession. I have been sitting at both ends of the interviewer’s table many times, and I am quite ready to doubt this implication. There isn’t much empirical evidence to support the thesis that people who score high on coding interviews also do well in their jobs. Actually, there is none. Even Google’s own study concluded that interview scores don’t correlate with job performance. Gayle Laakmann Mc Dowell, the author of the book “Cracking the Coding Interview” says: “No one really knows, but it’s very reasonable to assume that there is a link,” and “Absence of evidence isn’t evidence of absence.”

Sorry, that’s not good enough for me. Let’s be a little more scientific.

Perhaps we begin by determining what is actually measured by solving an algorithmic problem. The coding interview is akin to a school exam. It measures how good you are at applying textbook solutions to a given task. Just as in an exam situation, you can improve your score by studying hard. The domain is broad enough to provide sufficient variation in different fields from number theory and graph theory to combinatorics and set theory. Yet, algorithms themselves are very narrow as they deal with a specific solution to a specific problem. A successful coding interview demonstrates three things: 1. the candidate can write code, 2. the candidate has a grasp of algorithms and can memorize textbook solutions, 3. the candidate can reproduce and explain these solutions.

At first glance, this seems useful. These traits are surely expedient in typical development work. They’re kind of expected from developers. But does the coding interview also measure how well pronounced these traits in a particular applicant are? Can standardised interviews establish a framework for comparison? The answer is sadly no. One applicant might receive a familiar problem that he can solve and pass with flying colours. Another more talented applicant might have never before encountered the same problem and fails to solve it. A third applicant may get bogged down by anxiety. Yet another applicant may solve the problem, but produces bugs because of using an unfamiliar language. The result is influenced by many factors and it is notoriously unreliable.

This is not the only problem. There is a more serious one: the coding interview only probes a very narrow set of skills. Being able to produce algorithms is not sufficient to become a successful developer. For example, a developer also has to read and interpret requirements, communicate within a team and with business people, have knowledge of technologies and best practices, perhaps also have an understanding of certain industries. In this light, being able to memorise textbook algorithms seems somewhat less relevant. After all, you can always look up a manual when in need of an optimised algorithm for a specific problem. This is probably what most developers would do in their day-to-day work.

I remember a peculiar coding interview that took place 10 years ago on the phone before shared online code editors became a thing. I was asked to spell out an algorithm that produces the series of prime numbers. “No problem,” I said, “just let me google the sieve of Eratosthenes.” “No no, let’s just improvise,” said the interviewer, “it doesn’t have to be perfect.” So I scribbled down some similar, yet doubtlessly inferior code that mimicked Eratosthenes’ idea and read it out loud (awkwardly) on the phone. Something I would never do in an actual work situation. Yet, I passed the interview and got the assignment.

Is this a good predictor of professional performance? No, it isn’t. It is way too arbitrary and readily produces false negatives as well as false positives. There is a considerable amount of HR management literature that has identified good and bad predictors for work performance. Among the worst predictors are first impressions, school grades, and brain teaser questions, such as “how many golf balls can you fit into a phone booth?” Finding the answer to that is a lot like devising an algorithm for a geometry problem. You get the clue. Case in point: Max Howell, the author of the popular “Homebrew” package manager for macOS was (infamously) rejected in a Google interview, because he was not able to produce an algorithm for inverting a binary tree. Howell’s software is used by millions of Mac users and is now maintained by a team of 21 people. Yet, he wasn’t good enough for Google.

One of the best predictors for future job performance is past performance. Duh. It’s kind of obvious and also backed up by evidence in the form of empirical studies in management. Had Google considered past performance instead of algorithms, the company would now be richer by one accomplished engineer, who according to his own words cares more about user experience than about computer science. People often have special talents that evade the standardised interview process. They will not escape an experienced interviewer, however. The only problem with past performance is that data is not always available. For example, what about grad students, career changers, and people with little work experience? Well, the second most reliable predictor for job performance is cognitive ability, also known as “g factor” or general intelligence. The literature is again quite solid on this point.

It stands to reason that a standardised and culturally neutral IQ test provides a much better predictor for future performance. And by “much better” I mean an order of magnitude better. It is also less time-consuming than going through a series of algorithm/coding problems. So why are companies not using them? One reason is that in certain countries, such as the USA, IQ tests are seen as potentially discriminatory and could therefore be legally contestable. This is obviously a matter of policy, and well idiocy. Encountering an IQ test in a job interview appears to raise more eyebrows than encountering a esoteric programming problems. Another reason is that high quality standardised and culturally neutral IQ tests are somewhat difficult to develop. And new ones would have to be developed all the time to ensure high quality results and to prevent abuse. Yet another predictor for career success was recently (2013) suggested by Angela Lee Duckworth in a TED talk. She called it “grit”, or the “power of passion and perseverance” and subsequently received a lot of attention from the tech industry. The problem with “grit” is that as of now no reliable way of measuring it has been devised.

So, the question that springs to mind is: why do companies use coding interviews in the selection process if they already know that the resulting score is a poor predictor for career success. Frankly, I don’t know. If you’re a big tech HR manager, please comment and enlighten us. I can only speculate. Companies like Facebook, Google or Apple are swamped with applications and might have to create artificial barriers to filter applications and reduce the number of candidates to a manageable amount for round two. What does this artificial barrier achieve? Perhaps it is about grit. Only the ambitious candidates will pass, namely the ones that are willing to learn and memorise algorithm textbooks just for the interview, and just for getting the chance to land a job with that big tech company. It is reasonable to assume that someone who has the motivation to put in three or four weeks of cramming for an interview, is also motivated to put in hard work into their job. In this case, developer interviews could just as well require candidates to conjugate Latin declinations and cite Roman philosophers. The effect would be the same, although it would certainly raise many eyebrows.

Another plausible explanation is that companies nowadays tend to put processes over people. The decision making process, especially in large enterprises, is highly formalised. Instead of leaving the hiring decision to an experienced HR manager who relies on their personal knowledge and skills, it is relegated to an impersonal procedure that produces data. On one hand, this frees decision makers from personal accountability. On the other hand it provides an instrument that top management can manipulate at will. For example, if management should want to steer their engineering staff into a new direction, it could replace algorithm questions with machine learning questions. Whatever the reasons may be, we can be sure that thousands of smaller tech companies will follow suit and imitate the example of Google, Microsoft and others, even if they don’t understand their reasons and even if the adopted procedures aren’t fitting their own true needs.

In the end, I believe coding interviews are not totally useless. They are an effective means to engage the candidate in his field and simulate a work situation. The coding interview gives the interviewer a chance to observe how a candidate approaches technical problems. For example, it may reveal whether the candidate’s course of action is methodical, or whether they have exaggerated their familiarity with a certain technology. Under ideal circumstances, it can reveal a lot about how a developer thinks. However, since an interview is a special situation these indicators need to be evaluated carefully. For the benefit of all involved parties, the coding interview is best conducted in a casual way. An expanded problem space leaves the candidate with more choices and is is likely to provide more information. I don’t see any good reason, why coding interviews should be conducted like a university exam, however. If you can think of any, please let us know.