Web and also here in the Stack, we sometimes talk about "abstraction" when it comes to software architecture / / p>
- What is this "abstraction"?
- Why is it important?
- How to get it in practice?
Web and also here in the Stack, we sometimes talk about "abstraction" when it comes to software architecture / / p>
Abstraction in computing has its meaning derived from same concept in philosophy , which is "to isolate an element to the exclusion From others". Its use is very much like that done in math - instead of solving a problem for a very specific domain (eg, had four oranges and I ate two, how many do I have?) Turn this problem into a more general problem (eg% and this problem, applying the resolution back to the original problem.
Given a concrete example, how do you implement a summation?
var resultado = 0;
for ( var i = 0 ; i < array.length ; i++ )
resultado += array[i];
And how do you implement a product?
var resultado = 1;
for ( var i = 0 ; i < array.length ; i++ )
resultado *= array[i];
Note that there are potentially N problems of the same format: one starts with an initial value, applies an operation involving that value and one element of the input, the result of the same combined with the next element, etc., until if you reach the end result. By abstracting the problem in this way (ie isolating the common characteristics, parameterizing by the specific ones) one can arrive at a more general solution :
function reduce(array, fn, valorInicial) {
var resultado = valorInicial;
for ( var i = 0 ; i < array.length ; i++ )
resultado = fn(resultado, array[i]);
return resultado;
}
var somatorio = reduce([1,2,3,4,5], function(a,b) { return a + b; }, 0);
var produtorio = reduce([1,2,3,4,5], function(a,b) { return a * b; }, 1);
Another common day-to-day example is the use of types and subtypes, and the creation of "generic" functions that act on various types. Instead of implementing a specific solution for a data type, one that implements several distinct types is implemented, thus avoiding duplication of the code.
Because this is important, it should be obvious. How to achieve this in practice is already a question of mathematical reasoning: to try to see similarities among the various concepts with which we deal, to describe this similarity in the form of a new concept (more general, or more abstract) and - according to the resources offered by your platform of choice - to develop solutions focused on this new concept, so that it can be easily reused for more specific concepts.
Of course, much of this work has already been done by others, so the more knowledge you have - the more you contact third-party work involving abstraction - the easier you will have to identify in practice when an abstraction applies to you, in order to develop / reuse solutions in this sense. (Do as I say, do not do what I do: study math!) Finally, not directly part of the question but rather related, there is the concept of "layers of abstraction": often to solve a problem "high level" is desirable if you can ignore the "low level" details. For example, when you type "create a window" (eg, x = 4 - 2
) you ignore all the work the computer has to draw the geometric shapes that make up that window, the handling of the input (keyboard, mouse) etc. You're thinking at a high level, and having to think about those details would all just bother you.
On the other hand, anyone who creates a library to implement a graphical interface does it very generically, without worrying exactly what it will be used for (not how will be used, this is part but the specific windows that will be created). At the same time in that phase it is ignored how the computer will draw the pixels on the screen, how the main memory will interact with the video card, etc. This is the work of anyone who creates graphic libraries (such as OpenGL and DirectX).
Programmers who focus on end-user solutions are generally at the highest abstraction level (ie using the tools available to meet a real-world need), but do not always have the tools at the highest level possible. So if you realize that you are (or are) overreacting in building a system, consider that it may be interesting to somewhat abstract the problem you are dealing with - creating solutions to this abstraction, and then applying it to the problem. This is to use abstraction in practice.Abstraction for OO, it's nothing more than observing behaviors and day-to-day structures, and transforming them into a computational language.
By using it wisely or in the right way, you will be able to build less computational systems that are closer to the user's expectations with less effort and more quality. In other words, you will really be able to take into account the need of the user.
Not to mention that this is an arduous process, and that few people master it with mastery, you will achieve with much study, and practice at the same time. That's right, it's not that hard, but if more people dominated as it should have, many systems would not be found in deplorable states as we see so easily today.
This is my opinion, based on what I learned about software engineering so far !, I tried to be brief and I hope I have helped!
Thanks! : D
What is Abstraction?
Abstraction is the act of summarizing characteristics or similar actions shared between two or more objects.
Why is it important?
Because when done well it reinforces the paradigm of virtualizing the real world.
How to get it in practice?
Looking at states and similar behaviors between two or more objects.
According to Wikipedia:
In computer science, abstraction is the process of separating specific ideas from working methods. Computational structures are defined by their meanings (semantics) while hiding details of how they work. Abstraction attempts to factor in details of a common pattern so that programmers can work more closely to human reality.
"But it's such a dull drug!" - Tank, Matrix
Does object orientation not have one of the most basic objectives to represent the real world programmatically? A Port object represents a real-world port, with its properties (proprieddes) and actions (methods).
And just as in the real world several things have similarities, whether of characteristics or actions. The difference is that not between each other, if this were so, we would open the car door and the refrigerator door would be opened together.
Let's continue with the example of the Port object. Let's now enter a Gate object. Both are basically the same thing, have shared features, common actions, but a Gate has some things that a common Port does not have (remote control maybe) p>
Without abstraction we would have:
class Porta {
private $isOpen = FALSE;
public function __construct() {}
public function open() {
$this -> isOpen = TRUE;
}
public function close() {
$this -> isOpen = FALSE;
}
}
class Portao {
private $isOpen = FALSE;
public function __construct() {}
public function open() {
$this -> isOpen = TRUE;
}
public function close() {
$this -> isOpen = FALSE;
}
}
Anything that a Gate needed to open / close, for example could even be implemented in its own methods, but in any case it would not eliminate code smell from the replay.
And if we would repeat it again, again and again it's time to abstract!
In our didactic scenario we can summarize both Port and Gate to:
The first is a characteristic and the last two are actions. Our preliminary refactoring would be:
class Porta {
protected $isOpen = FALSE;
public function __construct() {}
public function open() {
$this -> isOpen = TRUE;
}
public function close() {
$this -> isOpen = FALSE;
}
}
class Portao extends Porta {}
We have the flag flag status, if opened or closed, and opening and closing actions by reducing objects.
Public actions are best characterized by Interfaces here disregarded