Tuesday, 27 October 2015

Coding In the Real World

As a student when confronted with a problem, I would end up coding it and thinking - how do the professionals do this?

For some reason I had the impression that once I entered the industry I would find enlightenment. Discovering the one true way to write high quality, professional code.

It turns out that code in industry is not too far removed from the code I was writing back when I knew very little.

Code in the real world can be:

  • messy or clean
  • hard or easy to understand
  • simple or complex
  • easy or hard to change
  • or any combination of the above

Very rarely will you be confronted with a problem that is difficult. Most challenges typically are formed around individuals and processes, rather than day to day coding. Years later I finally have the answer. Code in the real world is not that much different to code we were all writing when we first started out.

If I could offer myself some advice back in those early days it would be to follow KISS, YAGNI and DRY religiously. The rest will fall into place naturally. Above all, aim for simplicity.

The best way to summarise my feelings would be this image courtesy of Imgur.

View post on imgur.com

Tuesday, 20 October 2015

Set Based Design

Each morning newspapers hit the newstands without fail. Live broadcasts are the same. Come show time they hit the air without fail. You can probably think of more examples of deadlines that are constantly achieved. So why does software development accept missed deadlines? Software development not only encourages software to be late, it has become accepted or just another risk to the project by default.

Solution

Implementing Lean Software Development introduces the concept of Set Based Design (SBD). SBD provides an answer on how to never miss a deadline every again, providing the deadline is feasible. SBD will allow software to constantly hit deadlines just as newspapers and TV shows do.

SBD requires multiple teams to implement the same functionality split over several sets (versions) of work. Each team works independently and in parallel to fulfil the same goal. This is in stark contrast to normal proceedings where each team is usually assigned to separate projects. At the end of the deadline the set that is best fit for purpose is chosen. This ensures the teams as a collective have delivered the best possible solution within the deadline. Each set should increase in scope and complexity. This means each additional set has a higher chance of missing the deadline.

Example

The number of sets you decide upon is based on each variation, so there is no fixed limit. Assume three for the following introduction.

Set One
  • Start by accepting and acknowledging the deadline. This may be an integration deadline, a release or third party dependencies.
  • One of the teams should be working on the simplest thing that can possibly work. Some may say this is verging on a bodge or hack. You may end up adding logic to views, inserting business logic into sprocs or committing any other coding related atrocity. Despite this you must ensure the functionality is fit for purpose, tested and agreed by all.
  • The worst case scenario is the first set is released. You hit the deadline and you resolve some technical debt in the background afterwards.
Set Two
  • The team working on the second set would up their game. Still aiming for the deadline while the scope increases. Instead of adding logic into views, it goes into domain objects. Logic in sprocs? No chance. Other further enhacements could be added.
  • The worst case scenario? The deadline is missed but they have a solution which is better than the first set and close to completion.
  • After the first release the team simply finish up and deploy after the fact. This wipes out the technical debt of the first set and provides both a met deadline (via the first set) and the best possible solution.
Set Three
  • A third set would take a much higher level approach to the solution. This would be the best proposed solution. A strategic decision for the team factoring in long term goals and ambitions.
  • The chance of completing this set within the deadline are slim to none.
  • The worst case scenario is the team on the third set miss the deadline and one of the other two sets are released.
  • This is not the end of the world. Depending on how much work is left would dictate what happens. Scope could be further reduced, the set could be finished, or abandoned completely.

Questions

Is this waste?

No. The goal is to hit the deadline with the best possible solution. While a number of sets will never be released, the teams have hit their target. Teams should judge success on goal completion, not lines of code into production.

What are the downsides?

Trying to explain SBD and actually convincing the business to have a number of teams all working on the same project would sadly be an incredible challenge in most organisations.

When would you not use SBD?

SBD makes sense when there is a fixed scope deadline that cannot be missed. If this is not the case, iteration or refactoring at each step would suffice.

Alternatives?

Producing an architecture that allows replacement or changes easily is another alternative, though this has risks of its own. Changeable architecture will be covered in a future post.

Tuesday, 13 October 2015

Header Interfaces vs Role Interfaces

In some languages such as C++ you must define header interfaces. These constructs define how a public type is exposed in terms of its public interface. Other languages take a different route. C# or Java do not require headers but they are still very much in circulation. This unfortunately brings along some unwanted side effects.

Header Interfaces

Header interfaces are a one to one mapping of public methods that match the type it is defining. In other words, they are recreating the overhead of headers in languages that do not need them.

  • Header interfaces tend to break the Interface Segregation Principle.
  • Harder to switch objects via DI as you are forced to implement all members even if you do not use the whole interface.
  • Prone to breakages as the one to one mapping means any change is breaking.

Role Interfaces

Role interfaces define the role an object plays. Due to various roles having different responsibilities they are usually grouped by functionality. Role interfaces are usually combined with composition or interface inheritance.

The role of a Developer has now been introduced. This is a separate concept from the rest of the object.

  • Easier to follow the Interface Segregation Principle.
  • Closely related to the Liskov Substitution Principle - no need for partial implementations.
  • Less chance of breaking changes - interfaces can be removed or added easily.
  • Reduced scope - anything that fulfils the role of Developer can be provided as an argument.
  • DI frameworks may take more configuration if role interfaces are used. This may explain the bias towards header interfaces.

More

Tuesday, 6 October 2015

Abstractions in Code, Details in Metadata

I've programmed many games - each one was special in its own way. One in particular stands out early in my university studies, a top down shooter. It was not graphics, gameplay, or sound that made it stand out however. It was the lesson it taught me about software development.

Level One

With the deadline for completion of the project looming, time was running out. The core game engine was complete but other than the first level there was nothing else for the player to do. With more marks awarded for various components I decided to add a second level.

At the time the game consisted of a source file called level.cs. This contained parts of functionality explicit to every level that I would need. It also contained code specific to the first level. My solution was to extract a base class and introduce level.cs and level1.cs. This worked. The addition of level two was not as easy. The second level required a considerable amount of additional code, despite the shared functionality. A slow feedback cycle of change, compile, and test, made this addition even more tedious. With the test phase consuming much of my time.

Hopefully you can see where this is going. While I never added a third level, the same problem exists. In fact for every additional level the problem would get worse.

Lesson

The lesson I learned here was that a game engine should be abstract, while the details of the level should be data that is configured outside of the code. This allows anyone to make levels for the game. Levels can be unique rather than constrained to how the programmers coded them to be, introducing novel gameplay elements constrained only by the imagination of the designers.

This concept is not unique to games programming. I would learn a few years later that this is a well known and advised practice - The Pragmatic Programmer summarises that abstractions should live in code, while details lives in metadata (data about data).

"Program for the general case, and put the specifics outside the compiled code base."

Those of you with a keen sense for code smells may be thinking about another issue with this story, and yes, you're right. The base class caused issues. The use and misuse of inheritance will be the subject of a future post.