I had read articles on the S.O.L.I.D principles
I had a decent grasp of OO design principles and understanding Polymorphism, encapsulation, abstraction and inheritance.
I used interfaces and abstract classes but it was only recently that I understood some of the benefits of abstraction with regards to code design.
This understanding has come through reading (re-reading in some instances) various parts of the book mentioned below
- Code Complete 2
- Clean Code
- Head First Design Patterns
- Design Patterns – Elements of Reusable Object-Orientated Software
- S.O.L.I.D design principles
Head First Design Patterns mention these design principles, which I found really useful to understand the effects of good OO design
- Encapsulate what varies
- Favour composition over inheritance
- Program to interfaces, not to implementations
- Strive for loosely coupled design between objects that interact
- Depend upon abstractions. Do not depend upon concrete classes
Knowledge is like a jigsaw puzzle
I had read some of the material a long time ago, on my recent reading I found my initial understanding of some of the concepts was lacking a bit of understanding. This isn’t unusual when trying to understand complex and abstract concepts, here is an interesting article on that phenomenon.
When learning new ideas and concepts you can get a partial understanding where bits of it are clear, whilst other areas can be fuzzy. I view information/ideas as having a 3D property where it suddenly makes sense when you view the information/idea from a different perspective.
This article talks about the metaphor as knowledge as a jigsaw puzzle
Your understanding grows as more pieces of the puzzle fall into place
What is Abstraction?
Before looking at abstraction from a coding point of view what is a general definition of abstraction, Wiki has a few definition
Abstraction in its main sense is a conceptual process by which general rules and concepts are derived from the usage and classification of specific examples, literal (“real” or “concrete”) signifiers
Conceptual abstractions may be formed by filtering the information content of a concept or an observable phenomenon, selecting only the aspects which are relevant for a particular purpose. For example, abstracting a leather soccer ball to the more general idea of a ball selects only the information on general ball attributes and behavior, eliminating the other characteristics of that particular ball
In computer science, abstraction is a technique for managing complexity of computer systems. It works by establishing a level of complexity on which a person interacts with the system, suppressing the more complex details below the current level
When abstraction proceeds into the operations defined, enabling objects of different types to be substituted, it is called polymorphism. When it proceeds in the opposite direction, inside the types or classes, structuring them to simplify a complex set of relationships, it is called delegation orinheritance.
Code Complete 2 gives a clear definition of what an abstraction is
abstraction is the ability to view a complex operation in a simplified form. A class interface provides an abstraction of the implementation that’s hidden behind the interface
What is an abstraction?
- Mobile Phone
Why is understanding Abstraction important
Abstractions help hide concrete code which can change with abstractions such as interfaces and abstract classes which are less likely to change.
Using abstraction limits dependencies in code, reduced dependency means reducing the effect of change in your code.
Two of the key long term goals for developers when writing code
- Increase the readability of the code
- Minimise dependencies in code, reducing the effects of change
The two goals will make maintaining the code easier, below I talk how abstraction can help you to achieve those goals.
Junior developers seem reluctant to use abstractions in code because of a mixture of not understanding how abstractions work and because they are focused on getting the code working and bypass the creation of abstractions, which can lead to big complex methods, few classes and no abstractions.
Junior developers are focused on the short term goal of getting the code working with the intent of leaving the design and creation of abstractions until later (later often doesn’t come).
Which leads me to write articles like the two below
Abstraction is one of the key principles behind many of the OO design principles such as
- Benefits of abstraction
- Code is easy to understand
- Manages change and the effect of chnage
- Creates cohesive code – it finds common fields
- Create loose coupling
Abstraction refines concepts to their core values, stripping away ideas to the fundamentals of the abstract idea. It leaves the common details of an idea.
Abstractions make it easier to understand code because it concentrates on core features/actions and not on the small details.
My understanding started to grow whilst reading these two OO design principle
- Encapsulate what varies
- Program to interfaces, not to implementations.
The various books and articles concentrated on the benefits of these two design principles I start to understand how abstraction could reduce dependences and the affect of changes on code, you can see I started thinking about whilst writing this article Information Hiding.
How to find abstractions?
- Nouns – things, people, systems
- Is A – Inheritance
- Has A – Behaviours
Actions/Verbs are often abstractions e.g. Drawing, validating, processing, routing.
When I mention types I am referring to
Abstractions are useful in life
People use abstractions all the time, you often mention
You don’t talk about the distinctive type of car but say car in general and people will understand you what you are talking about.
The same idea can be used in your code design. You can find a common action like validating, drawing, Updating, exceptions. The common action will be the interface and the concrete classes can hide behind it.
Exceptions are a good example you have a core exception (the ones lazy programmers throw when they don’t want to specify the exact error) and then distinctive exceptions extend it.
Exception is the abstraction and InvalidPluginExecutionException , NullReferenceException etc are the implementing concrete classes.
I had some code where which was triggered on the change of state and depending on certain values it would be go a different route, there were lots of different routes
The abstraction was Route, I made this an interface and it was then implemented by many different Routes through the system. If the users wanted more routes the code was made to encapsulate what varies.
Half the code used the interface Route, any changes by adding more routes would mean the code which used the interface would need to change or be effected by the change.
Why Abstractions are so important
Abstractions help create well designed code.
The code is easy to understand because if you have captured the right abstractions is obvious what the code is doing.
Abstractions help create loosly coupled code. The reason is the abstraction acts like a type and encapsulates the potential changes behind the abstract class/interface.
To understand why this is import you need to understand the statement
code to an interface, not a concrete class.
A classic abstraction is creating a database layer, an abstract class or interface which parts of the code users to interact with the database. The abstract minimises the effects of change because the code which interacts with the interface will not be effected by the implementation/concrete class changing. It also allows the code to change in the future and more types being added.
Adding more types will not effect any code which interacts only with the interface.
This brings me nicely to the design principle
Encapsulate what varies
Business rules or algorithms are a good example. When you have a behaviour or type you have an Abstraction. Using an abstract class will manage the effects of change and create a loosely coupled system which will manage the effect of change.
Understanding abstraction can take time
Abstractions are used everywhere because they make life easier
- Common language
- S.O.L.I.D principles
- Design Patterns
- Design Principles
It was until I began to understand the terms Encapsulate what varies and Code to an interface that I slowly (very slowly) could see how abstractions made it easier to organise code/reduce dependencies and how abstractions through abstract classes and interfaces helped manage the affects of change.
Change can ripple through poorly designed code because poorly designed code is fragile, you change one part of it and an unrelated part of the code suddenly breaks. The reason for this sudden breaking is dependency.
Abstractions (interfaces/Abstract classes) reduces dependencies and the abstraction acts as a barrier to dependency and change.
The next stage of my personal appreciation of abstraction was when writing the blog post – How to find classes, the method of looking and finding classes through nouns and types made it easier for me to identify potential abstractions.
Studying design patterns and good code will help you to understand and learn how great code uses abstractions. The two books below are great books to get started with design patterns, my vote goes to Head First Design Patterns because it’s easier to get started with.
Abstractions are a handy tool to understand when designing your code, it can make maintaining code much easier because you will improve readability and reduce dependencies in the code.
It’s definitely time well spent understanding abstractions in code design and it will make designing code easier.
Understanding abstractions can make you look at your existing code base from a different perspective because the potential abstractions highlight where the code might change in the future and areas of potential refractoring.