Frame – works?!

 

For last few years I’ve been listening to software architects having conversations about frameworks that should be used and where. There are always different opinions. Heated discussions. At the end, decision is made that turns out to be a pain in the developer’s back.

What is framework?

Framework is the common piece of code that provides some generic functionality, that could be reused. All the frameworks are created with the aim of solving some kind of a problem. I like to think of frameworks as tools with default solutions.

In software development the multitudes of frameworks are great. There are testing frameworks, for writing your tests. Dependency Injection frameworks for all your DI needs. Multitudes of web frameworks for every possible programming language that could serve html.

Framework creation

I was involved in building up the frameworks. They were designed for specific technology, with the purpose of solving particular problem. Once they had been created, people thought of those frames to be good at solving any problems.

Unfortunately, those frameworks were designed to deal with few issues one had. It is possible that by chance you might deal with exactly same problem and the framework would suit you.

Framework on steroids

There are frameworks that became monsters. The architects of those, started with a simple idea and developed them into mammoth projects. Those frameworks are trying to solve all your problems. All they do at the end, is creating more.

Process of selection

As I mentioned earlier, one designed a framework to deal with a specific problem, that is why most likely, it will not solve yours in exactly 100%. During my development life I have learned that there is no single Software project that looks the same as the other.

That is why you should leave some room for yourself when you select a framework. Don’t rely entirely on all the framework features. Don’t bind yourself to one framework as well. If there is a way, try to shield yourself with some kind of abstraction, which can be easily manipulated into another framework.

Avoid frameworks on steroids. If you are going to go the route of it, you’ll end up hacking around it, or putting up with it and jeopardising your design.

One tool to rule them all

I don’t like to use one tool to solve many problems. I always compare it to a use of a hammer. You can perfectly drive a nail into a piece of wood with it. I’m sure you can as well cut a wooden plank with a hammer but unfortunately the result might not be as pretty as if you used a saw.

Simplicity is a bliss

According to Dr John Medina, human brain is constantly learning, trying to see patterns, matching them and generalise. This is what we tend to do when it comes to a software design. We often see patterns in places where there aren’t any.

I was once at a brilliant presentation delivered by Dan North on architecture design. The bottom line of it was, that we should take a step back and look at what we are doing as the solution might be much simpler without any fancy framework.

Greg

Tests revealing design problems

Within last few months I was introducing tests into untested code. It was not old code, just some code that was not Unit Tested. As much as I was eager to do so, I found myself getting in a bit of a pickle.

 

Code complexity

Code was actually quite complex and difficult (smell) to understand. I was also a little scared that I will misunderstand the code and its intention. I assume that I will not be the only person facing this problem while working on the piece of code.

Fortunately there was some testing coverage in a form of a higher level Acceptance tests (not sufficient though).

I decided to refactor the code a little to make it more manageable. Extract few methods, rename few variables, remove unnecessary conditions and loops, etc.

When I finished refactoring and made sure build was still successful, I checked in the code and off I go to write some Unit Test. That was the point when I hit another brick wall.

Instantiated dependencies

Necessary dependencies in a class that I wanted to test were not provided to an object upon creation, but were instantiated internally. This means that code is not flexible to changes in a future and is impossible to test (smell). Making all the dependencies passed through constructor will make it more obvious to what the class will do, and make it possible to unit test.

So, after some refactoring again, building and submitting the code, I had my dependencies all wired up through constructor, just the way I like (mmmm, delicious).

Concrete classes

Many of the dependencies were still concrete classes. Pity, actually you don’t care what’s in the guts of your collaborators (most of the time) as long as they do what they indicate. This could be replaced by interfaces (or some abstract types in worst case) as dependencies. They also make it easy and simple to stub or mock your collaborators, so the testing is simpler to setup and you’ll be testing only the correct object.

Another refactoring session ended in a bunch of new interfaces.

So I started to write a test. I created my object and started to pass some dependencies. The problem was that I had to pass some other dependencies to those dependencies, and dependencies of dependencies and even more dependencies and … you know where this is going.

This great monster had too much setup code than the one I was going to test.

Too many collaborators

This got me into thinking that something was not right. The thing was that the tested class was trying to do too much. This was the main reason of mentioned previously code complexity. Testing was not easy and possibility of introducing new bugs during future changes was great.

So, extracting few methods here and there (around same functional area) and I was able to pull those methods into new object. This new class was very simple and was responsible for one area of functionality only. I could unit test that new class.

Last problem during the tests was that I got some unexpected behaviour. As I looked into the code it turned out that there was one more smelly thing left.

Static methods

There was some code that was calling to a static method of another class. It was impossible to mock or stub it. What’s even more horrible, it was using some internal static variables. That caused some un-expected behaviour.

Summary

As it turned out, I found problems in a code even before I started to write a single line of test. Just thinking about the ways to test, revealed first issues. More of the issues appeared while testing. The work I had to do in order to make code tidy, simple and testable could be avoided by writing it in TDD/BDD way.

I’m convinced there could be more problems revealed. Here are these that I found once again:

  • complex code
  • instantiated (new Foo()) dependencies inside tested class
  • concrete classes with no interfaces
  • too many collaborators (class was doing too much)
  • static methods (brrrr)

Greg

Bad interFACE design based on a TOILET example

So I’m reading this book at the moment “Design of Everyday Things” by Donald Norman. It’s good read for all the people that design/create things/software that would be used by others. I realized that I’m paying more attention to how things are design. If they are user friendly etc.

Client that I work for at the moment has one disable toilet with shower. I use this toilet to change and shower when I arrive on my bike to work. There is couple of things in this toilet that made me generally think about the design and find analogy in software, AND more exactly in Web Interfaces. I have stumble upon those issues all the time, on BIG GUN web sites (like banking interfaces) and on small private web sites.

Continue reading