Abstractions are extremely important in programming and everyone knows that. They help us to separate essential details of anything from insignificant. Ideally, they should select only the most important, the essence, without any extraneous impurities, the minimum characteristics of the object or process, but the ideal is not so common.
When a programmer writes code, he handles abstractions.
"The client sends a request to the server."Each word in the previous sentence is a high-level abstraction. It is important that these four abstractions are on the same level. The corresponding code might look like this:
')
client.send(request, server);
The reader has no questions at the sight of this line.
Often one line of code is not enough and programmers add more lines. A lot of time and space is occupied, for example, by validation of input parameters and processing of values ​​returned by functions.
void sendRequest(Request request) { if (server->error() != Server::errorOk) {
I so often see such ifs that I perceive them as noise (especially Yoda-condition). They are definitely needed, but ... I believe that they should not be here, in this function sendRequest, because client.send is at a higher level of abstraction than any Server :: ErrorState. These ifs are lower-level abstractions, so they should be hidden in separate methods isServerReady () and isRequestValid (). Then the code will be:
void sendRequest(Request request) { if (!isServerReady()) {
Now sendRequest operates with functions that are at the same level of abstraction, so the code is read easily and pleasantly. Bonus - these methods can (should) be reused instead of copying ifs. I do not want to see these ugly server-> error ()! = Server :: errorOk in the sendRequest function, but I would like to see them when I need them. Then I will look at the contents of isServerReady (). Are you feeling
Or for example. Large-very large class. All methods are scattered type conditions
if (niceNamedContainer.empty()) {
When I see the code for the first time, I can only say about
if (niceNamedContainer.empty())
“If there is nothing in niceNamedContainer”. Immediately I have a question, what does this mean? I answer myself: they put nothing in it, somewhere else where they were supposed to put it, but not here. After shoveling no less than one hundred percent of the class code in order to figure out how it works, I understand that this condition actually means "The data is ready." Hooray. But I think that it would not be difficult at all to make a selection of the isDataReady () method at the stage of writing a class. The reader would be much easier, and would not have to use telepathic abilities, because the reader of the code first of all needs high-level abstractions. The isDataReady () method is a ladder connecting a low level of abstraction with a high one. It is very convenient to go down it, if necessary, and if it is not necessary, then you can not descend. I think it would save a lot of time on supporting someone else's, old, inherited code. But the business is to apply the selection method and make sure that one function works with only one level of abstraction ... well, SRP should not be forgotten ... well, Liskov ... well, and encapsulation ... McConnell too ... more often.
These examples, although primitive, are not as far from reality as they may seem. I made an emphasis on ifs, since conditional constructions form, so to speak, the logic of the code work, and because sometimes it is quite difficult to understand if'ov interlacing. However, this is not the only place to use the Extract Method.
References:
ru.wikipedia.org/wiki/Abstraction_dataLiterature:
Steve McConnell. Code Complete: A Practical Handbook of Software Construction.
Robert C. Martin. Clean Code: A Handbook of Agile Software Craftsmanship.
Martin Fowler. Refactoring: Improving the Design of Existing Code