What is Abstraction
Abstraction in programming basically is a part of code that hides complex logic. Keeps unrelated parts of the program underneath. Skipping irrelevant parts and extracting parts common to a given part of code. To make it more clear let’s add a bit of history.
Abstractions in hardware:
The first abstractions in the programming world were the so-called Logic gates. To make this term clearer, let’s start from the beginning. The computer processor consists of the so-called logical transistor. These transistors operate on quite complex math equations based on voltage and current.
Modern computers have up to billions of transistors connected in the so-called circuit. It would be impossible to grasp billions of equations solved by individual transistors. Therefore, at some point in the development of computer science, when the number of transistors began to get out of hand, engineers came up with the idea that they would group the transistors into the so-called Logical gates. Hiding complicated mathematical operations in the form of simple logical functions (OR, AND, and NOT).
Logical algebra
Thus, leading to the invention of the so-called Logical algebra (boolean algebra). From that moment on, instead of looking at designing circuits through the prism of voltage and current and mathematical operations, they could look through the prism of OR, AND, and NOT (logic gates) operations. Logical gates are therefore called abstractions superimposed on transistors. These are some of the first abstractions in the computer world.
Abstraction is an alternative representation of a certain concept that hides unnecessary details. It only exposes parts that interest us (programmers). As first programmers, engineers were not interested in tension and intensity. Therefore, tensions and intensities were ‘covered’ with Boolean algebra. Exposing logical operations in a simple and transparent way. That at the same time hides what is happening underneath.
With the development of processors, we have reached the point in which logical gates and are no longer abstract enough. We have millions of logic gates in our processors these days. This is how another abstraction – modules, was applied to the logic gates. Modules no longer even operate on Boolean algebra.
Abstraction in software:
In the world of low-level programming, there are also many levels of abstraction. Let me cut it short so as not to make this article too voluminous.
CPU – hardware system,
Firmware – controls the hardware of the system
Operating system – This is the level at which the API developers use to develop:
Programs, applications, services, etc.
Abstraction in programming:
Let’s start with the simplest and most basic concepts in programming. The smallest units of code are the so-called Expressions (statements) (ie an operation that results in some value, eg. assignment expression, or if statement). Then bigger units are functions and methods. They hide the logic of expressions exposing individual operations. E.g. calculateSum, displayName, etc… In object-oriented languages, methods and functions are grouped into objects that display functional behavior. For example, relating to the user of a given website or character in the game. In the functional paradigm, functions are wrapped by so-called higher-order functions. Objects, in turn, make up modules.
At this level, we touch on domain problems (let’s call it the most general) of the application. Modules aggregate objects and display functional or business concepts. The modules, in turn, make up the entire application.
It is a very simplified image of abstraction. The applications themselves consist of many levels of abstraction. From the simplest functions through classes to modules. All parts surrounding certain behaviors, system functions.
Overlapping abstractions does not ‘exclude the use’ of the logic hidden underneath them. The use of abstraction only separates particular parts of a problem. It groups bits of knowledge. By making specializations.
A high-level programmer does not need to know the equations governing transistors. Electronics designing transistors, in turn, do not have to care about programming languages. But we all build an interdependent working system that provides users with new solutions.
Why should you care about abstractions
“Managing complexity is the most important technical topic in software development. In my view, it’s so important that Software’s Primary Technical Imperative has to be managing complexity. Complexity is not a new feature of software development.”
Steve McConnell, Code Complete
One of the indisputable elements of clean code is the ability to use appropriate abstractions. One of the SOLID principles – The Liskov Substitution Principle is sometimes expressed as a counter-example to the duck test: If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction.
“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.”
https://www.101computing.net/understanding-abstraction/
However, it should not be forgotten that too much abstraction can also lead to unnecessary complexities. Programming is the art of balancing on this edge.
Note that abstractions do not provide an implementation, they only define them. By declaring abstractions, we undertake to provide its implementations somewhere.
BTW concept of abstraction reaches far out of the code itself. The most commonly seen example of using abstraction are just simple UML diagrams. They hide unnecessary details, exposing important, relevant information.
How to implement abstractions
In addition to the constructs, I mentioned earlier (statement, function, object, module). The most popular programming languages in the object-oriented paradigm offer the following concepts that are used for abstraction:
Interfaces
Some kind of blown shells or classroom skeletons. They are requirements that must be met by classes that implement a given interface. Only have field and method declarations without their implementation. Interfaces are contracts that tell classes what to do but not how. They are most often used at the code design stage. Contain information about the created objects. They introduce greater order and order, making the code more understandable and readable. Their use additionally allows the compiler to detect whether the concluded contracts have been fulfilled. In addition, many IDEs offer validation of the implementation of the application of interfaces as early as the writing stage. Allowing us to catch many errors such as type mismatch before running the program.
Abstract classes
So classes that cannot create objects. You can only inherit from such classes. An abstract class can have methods. Even with simple implementations. However, the basis is abstract methods, i.e. only declarations that should be implemented in a child class.
This class can be used as the basis for other classes. Child classes inherit all behaviors of an abstract class (behaviors in code are represented by methods, abstract and non-abstract).
The concepts behind an interface or abstract class are merely an agreement between a programmer and a piece of the program. Some languages make sure that we do not exceed their boundaries with the use of a given construct.
However, we can set these limits ourselves using other tools. So in dynamically typed languages (such as javascript or ruby), which do not provide us with abstract class explicit tools, we use the so-called:
Duck Typing
We simply use normal classes instead of abstract classes as if they were abstract (no redundant implementations, only for an inheritance, etc. ). This situation is called implicit abstractions.
We don’t explicitly state in the code that the class is abstract using keywords provided by the language. But if the implemented class meets the assumptions of the abstract class. From the point of view of runtime and programming rules in general, a class is abstract.
In functional programming, abstractions are simply functions, so-called higher-order functions. I will write more about these types of functions in the chapters on functional programming.
Summary
Abstractions are packages of individual parts of the code. They hide unnecessary details. Exposing only the necessary elements (API). Thanks to abstractions, we can break down the code into related parts. This makes it easier to understand and manage.
Interfaces and abstract classes are ways to implement abstractions. They constitute a kind of boundaries for the created objects. Keep in mind that these are contractual boundaries between developer and code. In languages that do not have this type of construct, the so-called duck typing.
Senior Software Engineer with over 7 years of experience and entrepreneurial background. Most often, apart from delivering good quality code on time, responsible for introducing good practices, teaching programmers and building team bonds andestablishing communication on the line of development-management. Privately Kākāpō and Wombat enthusiast, traveler and retired acrobat.