OOP vs procedural programming - page 11

 
Реter Konow:

In my opinion, there is a flaw in your problem-solving system. The problem itself should be crystal clear and precise, and hence its solution too. If the solution is cloudy and defined by the words "The system has shown itself to be very reasonable" (how can it be reasonable in 270 kb of code?!), it means that the author roughly understands how his system works. And it's the scary contrivances of syntax and superfluous entities in the solution that prevent him from understanding it to the end.

Reasonableness lies in "predictive power" - a significant change of working protocols did not require changes in the code of experts responsible for the logic of their work. The code modification was only in the place which directly handled the terminal at a low level.


The given code shows very well how all the OOP-hacks can be well replaced with "functional hacks". That is, exactly what I was saying above - it can be written both ways.

But looking at your code I see that you have to keep much more in memory. Say, in most of your if's I "drowned" in a moment. They are correct, but if I had to maintain this code - I would insert before each condition a few lines of comments, what does this check do and why these fields are used in the array. Similar to the comment before declaring the CTradePositionI interface in my code. Plus - complex conditions - would also personally stress me out a lot.

I would personally make more mistakes in your code, and it would be harder to catch them. That is, despite the correctness and logic of such a code it would be more difficult for me to maintain it, than if I had written it all in OOP-style.

In OOP-style I would declare interfaces of windows, parts of canvas, elements, canvas, then I'd write real classes of those objects, and then I'd give out pointers to those interfaces in the right blocks, and work specifically with those entities, which would be needed at the moment - everything else would be unavailable at that point. This is so you don't have to remember what belongs to what and what is responsible for what. When you get the simplest interface consisting of a couple of functions, you just work with it, and the rest is unnecessary and unavailable to you. You don't need to remember anything at all.

 
George Merts:

Well, you've made a mess of it...

It's clear that any task can be solved both in OOP-style, with allocation of interfaces, building inheritance hierarchy, declaration of virtual functions, and in pure procedural style - you can even stick everything in one huge function.

The question is in the convenience and efficiency of support.

In MT - the most OOP-appropriate place is the order system. Personally, I have virtual interfaces for "position" and "position components". "Position" is a set of orders in MT4 or a set of positions in MT5. "Position component" is an individual order or an individual MT5 position (hedge or netting).

Here's the actual interface file(Retag Konow, you can appreciate the number of comments compared to the amount of code, and I periodically add them there when I encounter some subtleties I don't remember. For example, I regularly forget which real objects constitute a "position component". I just don't need to remember it - the Expert Advisor works with components according to the interface, and what's behind that interface in reality doesn't matter. But, I have to return to it during modification - that's why I need the first comment in this file very often):

The file for the trade component interface is as follows (I've already given it above, but I'll repeat it:

According to these interfaces - I have both MT4 and MT5 order system implemented for both real and historical orders.

The Expert Advisor requesting a position receives this interface and does not have to take into account the difference between MT4 and MT5 orders. And if a new order type is added or the order of working with them is changed - nothing will change for the Expert Advisor, only the new order type class will be added, and it will also support this interface.

The system proved to be very clever when hedging accounts were introduced. The experts - absolutely no change from that.

Reg Konow, how do you deal with the difference in order types in MT4 and MT5 ?

If a new account type is introduced (in addition to hedge and netting) - what changes will need to be made, and in the same place ?

In my opinion, really, if you remember all your code to a letter, and can easily tell why this or that line was written in your code a year ago - then, really, all these OOP-enhancers are just unnecessary gestures.

OOP is necessary precisely when you don't remember everything when modifying code - OOP allows you to isolate blocks from each other to limit the set of entities available at any given moment to a particular place in the program.


George, you sometimes write such a clinic about women, but respect the code ))))

 
George Merts:

The reasonableness lies in the 'predictive power' - a significant change in the operating protocols - did not require changes to the EA code responsible for the logic of their operation. The code modification was done only in the place which directly handled the terminal at a low level.


The given code shows very well how all the OOP-hacks can be well replaced with "functional hacks". That is, exactly what I was saying above - it can be written both ways.

But looking at your code I see that you have to keep much more in memory. Say, in most of your if's I "drowned" in a moment. They are correct, but if I had to maintain this code - I would insert before each condition a few lines of comments, what does this check do and why these fields are used in the array. Similar to the comment before declaring the CTradePositionI interface in my code. Plus - complex conditions - would also personally stress me out a lot.

I would personally make more mistakes in your code, and it would be harder to catch them. That is, for all correctness and logic of such a code, its support would be more difficult for ME than if I had written it all in OOP-style.

In OOP-style I would declare interfaces of windows, parts of canvas, elements, canvas, then I'd write real classes of those objects, and then I'd give out pointers to those interfaces in the right blocks, and work specifically with those entities, which would be needed at the moment - everything else would be unavailable at that point. This is so you don't have to remember what belongs to what and what is responsible for what. When you get the simplest interface consisting of a couple of functions, you just work with it, and the rest is unnecessary and unavailable to you. You don't have to remember anything at all.

In my code, the large number of fonts and their nesting is due to the complex behavior of different control definitions at different events and in different states. However, this function covers all of these options and fully "serves" the entire GUI. When redrawing any element, the colour of the part is determined by the original colour value in the kernel and this function.

P.S. Regarding OOP or procedural style, then - "To each his own" (c).

 
Alexey Volchanskiy:

Georges, you sometimes write such a clinic about women, but respect the code )))

About the code - I'm flattered. (Really, no kidding).

And about the chicks... I'm not a Casanova like you... I'm the one who holds back and doesn't say what I'm thinking... I've always had and still have a lot of problems in that respect, although a comfortable personal life has always been very important to me... It's good that sometimes luck smiled on me, and there is something to remember, after all.

 
George Merts:

About the code - I'm flattered. (Really, no kidding).

And about women... I'm not a Casanova like you... I'm the one who holds back and doesn't say what I think... I've always had and still have a lot of problems in that respect, although a comfortable personal life has always been very important to me... It's good that sometimes luck smiled on me, and there is something to remember, after all.


It's just that we have different attitudes to women. I think they should be helped. Yes, they're cranky, with their own quibbles, fickle in their passions, etc. You just have to not take them seriously, otherwise there will be moral tragedies.

 
George Merts:

Well, you've made a mess of it...

It's clear that any task can be solved both in OOP-style, with allocation of interfaces, building inheritance hierarchy, declaration of virtual functions, and in pure procedural style - you can even stick everything in one huge function.

The question is in the convenience and efficiency of support.


We can do it, but the efficiency of operation varies. We are not talking about support here, it's too relative.

There are tasks which procedurally can't be solved in an optimal way.

 
Alexey Volchanskiy:

We just have different attitudes to women. I think they should be helped. Yes, they're cranky, with their quirks, fickle in their predilections, etc. You just have to not take them seriously, otherwise there will be moral tragedies.


Alexei, have you done an experiment on how endless a woman's desire for help is? Have you met the satisfaction of help and how long has it lasted?

 
Реter Konow:


I take it you don't even use structures to store data? Your multidimensional arrays bring back memories of ancient MQL4, where you had to use such solutions for lack of structures. But now what's the point? For example

 int Элемент                     =  G_CORE[Окно][Деталь_полотна][_MAIN_ELEMENT];
 int Состояние_детали            =  G_CORE[Окно][Элемент][_CURRENT_STATE]; 

you could replace it with

 int Элемент                     =  G_CORE[Окно][Деталь_полотна].MAIN_ELEMENT;
 int Состояние_детали            =  G_CORE[Окно][Элемент].CURRENT_STATE; 

This is shorter, safer and faster. In the first case there is no control at the compilation stage over those values of array indexes you pass to it. And then you have to clean up all sorts of "array out of range" in runtime - and this is at best. Worse is when the index is acceptable but incorrect. That's why it is good programming practice to involve the compiler as much as possible, detecting errors at the compilation stage and not catching them at runtime like in your case.

Yes, right now you are good at remembering what values to feed to where. But this is probably because you are constantly busy with this project. Try taking a break for, say, half a year, and feel the difference. Some people have already mentioned that. Or do you think we're all sclerotics or something? :) It's a common thing for a programmer...

So the task is to minimize the probability of shooting yourself in the foot. I strongly recommend that you create your own types using enum instead of the ubiquitous int. And they don't necessarily have to have enumerated values, the main thing is that it is a separate independent type, which will be controlled by the compiler, and will not allow you to swap function arguments, etc.

 

I write only and exclusively OOP.

Back in the 1900s, I couldn't get into it - Pascal 6.0, then Borland C++ 4.5. But when I've mastered it, I can't imagine anything else - it's that simple and convenient.

 
Alexey Navoykov:

I take it you don't even use structures to store data? Your multidimensional arrays bring back memories of ancient MQL4, where you had to use such solutions for lack of structures. But now what's the point? For example

you could replace it with

This is shorter, safer and faster. In the first case there is no control at the compilation stage over those values of array indexes you pass to it. And then you have to clean up all sorts of "array out of range" in runtime - and this is at best. Worse is when the index is acceptable but incorrect. That's why it is good programming practice to involve the compiler as much as possible, detecting errors at the compilation stage and not catching them at runtime like in your case.

Yes, right now you are good at remembering what values to feed to where. But this is probably because you are constantly busy with this project. Try taking a break for, say, six months, and you will feel the difference. Some people have already mentioned that. Or do you think we're all sclerotics or something? :) It's a common thing for a programmer...

So the task is to minimize the probability of shooting yourself in the foot. I strongly recommend that you create your own types using enum instead of the ubiquitous int. And they don't have to have enumerated values, the main thing is that it is a separate independent type, which will be controlled by the compiler, and will not allow you to swap function arguments, etc.

I read your posts on other threads and realized that you are a big expert in programming. Of course, I'm not and do not claim to be such. However, I consider myself a specialist in solving tasks as such. Well, don't you agree that effectiveness of the solution is the most important thing?

Overloading of syntax and complexity of rules has never contributed to keeping the solution efficient. It was simplicity and brevity expressed in conciseness, universality and readability of code blocks that did it.

My rules in programming are less code, less rules, less syntax and less comments at the expense of using native language and meaningful names of variables and functions.

My main thesis is "if you can do without something in a solution, you should definitely do without it".

I don't think there are sclerotic people here at all)). Simply looking at the given codes it becomes clear why they are easily forgotten. Even the very fact of programming in a foreign language plays a role. When you program in your own language, it feels absolutely different. You feel power and freedom instead of tension and constraint. A foreign language takes more effort, takes more time to get into the code and slips out of your head faster. It's just a "biological factor".

Therefore, I consider (quite reasonably) inefficient to use OOP in general to solve my tasks. Lots of rules, syntax and all in a foreign language. This way the talent can't really develop, which means that the result will be poorer.