Questions on OOP (Object Oriented Programming) - page 2

 
VOLDEMAR:

As always, I wanted to learn, but there are bound to be those who have nothing more to say except to be clever...

I wrote a simple example to take it apart, I don't know how to write more competently with OOP ... It is just an example, if you know how to write a similar code correctly and OOP then please write, so that I and others could learn ...

OOP begins with finding an object. If there is no object, there is no OOP.

Usually, an object is some resources, data.

You just have to write and watch how others write. Then you will figure it out by yourself. You could also read textbooks. There are plenty of them on the Internet.

 
Zhunko:

OOP starts with finding an object. If there is no object, there is no OOP.

Usually, an object is some resources, data.

You just have to write and watch how others write. Then you will figure it out by yourself. You could also read textbooks. There are plenty of them on the Internet.


Recommend a couple of textbooks please ... The easiest and most useful in your opinion ...
 
VOLDEMAR:

Recommend a couple of tutorials please ... The easiest and most useful in your opinion ...

Grady Buch. "Object-Oriented Analysis and Design. With examples of C++ applications".

Ire Paul (sometimes spelled Ira Paul) "Object-oriented programming in C++".

 

1) Not related to OOP, but trade operation error handler(OrderSend(), OrderDelete(), OrderModify() ) should be added...

To make it relevant to OOP - make it as a virtual class method (to override it in descendant classes, adding processing of other codes).

2) All the class methods that in descendant classes can work differently than now - make themvirtual.

The first candidate is openorders().

The disadvantage is that in virtual methods, you cannot change the number and type of parameters.

On the plus side, the "old" Buy, Sel, BuyStop etc. will be able to call the "new" (altered in the child class) openorders()

3) Let's have nicer names at once. OpenOrders instead of openorders, for example.

4) If the terminology is to call something, then you use similar terminology.

If selling = SELL, then you call it Sell or SELL (i.e. SellStop instead of SelStop)

5) You must remove all constants (500, etc.) from the class.

Let them be taken from variables or set as parameters of methods.

Now you remember about 500 embedded into openorders(), but later you will forget about it or will write a lot of owls using these classes and it will be difficult to change something.

The hardest thing to fix are architectural errors.

And it's the skeleton you're creating now (if it's not just an exercise).

6) Don't put everything in one class.

Make a clOrder class and stick SetSL, CloseOrder, GetSL, GetProfit, SetTP, GetTP , etc. with it.

And in the clTrade class, add an array/list of orders, a symbol and symbol properties(TICKETSIZE, POINT, TICKETVALUE, MINLOT, MAXLOT, STOPSTEP, LOTSTEP, LOTSIZE , etc.).

If you attach Ask and Bid (as properties of a symbol), don't forget to refresh them in OnTick().

To RefreshRates(), make a binding so that after updating of МТ variables Ask and Bid properties are called (I have also checked the status of orders, who opened and who closed. The closed ones are removed from the list of orders).

You can add schedule (first of all, make a class) and trailing stop (also make a separate class).

PS: I did it all at weekend (I made library for trades), but this time I decided without classes (only structures, arrays of structures and functions that work with it all).

There's also a schedule for every day (since Alps on gold has a break every day from 0:00 to 1:00). In the last 2 minutes of trading, the schedule checker closes all trades and cancels all orders.

And in the last hour of trading - it closes losing trades, cancels orders and trills profitable ones. I have also made a trailing stop. One type, but it fits to different symbols due to different parameters.

The scheme is as follows - symbols (with their own fields), orders (with their own fields), schedules (with their own fields) and an Expert Advisor that has its own fields (magik, etc.) and refers to the symbol and has a list of orders and a list of schedules.

The top of the hierarchy is the list of Advisors (symbol+magic combination must be unique).

 
VOLDEMAR:

Recommend some tutorials please ... The most simple and useful in your opinion ...

Examples written using OOP are now appearing in CodeBase. From VOLDEMAR, for example ))))

Actually your https://www.mql5.com/ru/code/11159 is what inspired me to rewrite my trade library for structures.

I have decided to wait with classes - I don't see the point of using them in MQL .

 
I don't quite understand, is it possible to use the standard Trade class now?
Or is it standard only in MQL5, and it's just taken over from there in the new MetaEditor?
 
EverAlex:

Examples written using OOP are now appearing in CodeBase. From VOLDEMAR, for example ))))

Actually, your https://www.mql5.com/ru/code/11159 is what inspired me to rewrite my trade library for structures.

I've decided to wait with classes - I don't see the point of using them in MQL so far.


Yes, I wrote this, but apart from transferring functions to a class, I haven't understood anything else yet,
 
VOLDEMAR:

Yes I wrote that, but apart from transferring functions to a class I haven't understood anything else yet,

3(+1) OOP principles:

1) Encapsulation. I.e. storing variables, pseudo variables (called "object properties" or just "properties") in the object itself. I.e. if a class is declared correctly, its data cannot be changed from the outside.

Only by using functions of the class itself (referred to as "class methods" or simply "methods"). Needed in order not just to assign a value to a variable, but to perform some action in connection with the change of those fields.

And this is the main (in my opinion) usefulness of introducing OOP in MQL, rather than porting functions (the functions of my trade library receive the index of the EA as one of the parameters and work with the selected EA, including its array of orders).

No one can get into the data of a class created by you (if there is no source code) and then complain that your code has errors.

2) Inheritance. When an ancestor class is created, it inherits all the fields and methods of the ancestor class (there is a private type for the fields and methods which cannot be seen in the ancestor classes, but we are omitting this for now).

And here at the design phase of the object you need to clearly think through the architecture - how the class will be used, what fields it will contain, how they should be visible in the descendant classes, etc.

It's used in powerful systems and class libraries, for tasks which I personally don't see in trade tasks. But maybe someone will need it. You can make descendant classes with different trailing stops, for example.

That's why - no constants inside methods, everything must be set externally via appropriate methods (usually start with .Set) or directly as parameters of methods. That's what I mean about your 500.

3) Polymorphism. The thing I wrote a couple of posts above - when a remodeled in a descendant class function openorders() will freely call the old Buy() functions.

An example of polymorphism is calculating area of a geometric figure for different shapes.

It is calculated one way for a circle, another way for a square. But in any case - by calling Figura.GetSquare() we'll get the area of a particular shape inherited from a base class (unless we forgot to declare Square() ).

Again some qualification is required to create the architecture of the base class. For example, forgetting to declare Square() as virtual will make it impossible to call Square in a generic way (you will have to check the type of the class before each call and call its implementation of Square exactly).

Some people recommend making all methods except constructors virtual (I take the same view if you can't see the horizon of what the class can grow into when you create it). The main thing is that destructors must be virtual too.


Update:

================

4) Abstraction (as requested by comrades, although when I studied OOP (in the 1990s) it was not considered a principle (for in fact - just derived from the first three), and in the article (see link below) it is written about it, but it is not in the title of the article, there are only 3).

In practical application it is creating an "empty" base class (where methods are declared, but do nothing). In some languages, a method can be marked so abstract. Which means that in a descendant class it must necessarily be overlapped (i.e. a method that does something is added).

===================

PS: you can read briefly, without going into too much detail, here


PPS: I don't want to offend anyone, but when I asked in Work to write a trade library, only 1 person replied that he has it and uses it.

5 MQL-programmers (on Skype) said they had no idea what should be in it and they copy-paste the required functions from one of their owls to another. They even stick RefreshRates() between code fragments that do not change anything and cannot be executed more than a few milliseconds. And the subsequent code does not depend on changed Ask and Bid and (maybe) types of orders.

Therefore, for MQL programmers who haven't worked with OOP in other programming languages before, the OOP in MQL will not be useful. At most, it will hide data from external changes (which is not bad either).

 
EverAlex:

3) The 3 principles of OOP:

1) Encapsulation. I.e. storage of variables, pseudo-variables (referred to as "object properties" or simply "properties") in the object itself. I.e. if a class is declared correctly, its data cannot

2) Inheritance. When an ancestor class is created, it inherits all fields and methods of the ancestor class (there is a private type for fields and methods which cannot be seen in the ancestor classes, but we omit it here for now).

3) Polymorphism. What I wrote a few posts above - when remodeled in a descendant class function openorders() will safely call old functions Buy(), etc.

An example of polymorphism is calculating area of a geometric figure for various shapes.

It is calculated one way for a circle and another way for a square. But in any case, by calling Figura.GetSquare() we will get the area of a particular shape inherited from the base class (unless we forgot to declare Square() ).

Where's the fourth?! Where is the abstract! Undeservedly forgotten :-(
 
Zhunko:
Where's the fourth?! Where is the abstract! Undeservedly forgotten :-(


Add.