This article is a written statement of my personal perception of programming and Object-oriented programming in particular. Here both mental indignations, and experiences for programmers of the whole world are collected. All, of course, backed by source code.
What is programming?
Where did I learn about programming?
- From 9 to 11 grade in school taught to program in Pascal.
What did my programs consist of?
- From the procedures and functions, data and actions on them.
')
What did not like?
- When I tried to write a great program, I struggled with errors for a very long time ... And the farther away the more there were ... I had to keep in my head a huge amount of information about how everything works. Who is calling whom?
How did I struggle with complexity?
- Allocated independent modules in which combined functions according to their meaningful purpose. Separate functions for working with a mouse, separately for working with graphics, separately for working with BMP, etc.
What is OOP?
How did you find out about OOP?
- In the first year of the institute.
What exactly did they tell me about OOP?
- It is hard to remember. I remember classes, inheritance,
private ,
public, and
static .
How did I use the knowledge gained?
- Well, I created classes as a reflection of real-world objects. Inherited to extend the functionality of a certain class.
How did the PLO help me? Was it easier to write programs?
- At first, it was convenient. It was possible to reuse the old classes. Sometimes, if the requirements were changed, I inherited and changed the behavior of the heir as necessary.
What are the principles of SOLID?
What is a class interface and why should it be explicitly described?
What is the ratio of total / partial and part / integer?
If you gave a positive answer to the two previous questions, you can stop reading. The rest of this article will discuss the interfaces, briefly describes the principles of SOLID, and 2 main types of relationships between objects in an object-oriented program.
What is the interface?
Look at the code for the class Foo:
class Foo { int a; static int b; public: Foo() { a = 0; } ~Foo() { a = 0; } int a() { return a; } static int b() { return b; } int sum1() { return a+b; } int sum2() { return a()+b(); } };
We see several types of information:
1. Class information
- class fields: b
- class methods: b ()
2. Information about a class instance
- class instance fields: a
- class instance methods: a (), sum1 (), sum2 ()
- class instance constructor: foo ()
- class instance destructor: ~ Foo ()
So the
interface of the class is the following data:
- class instance methods: a (), sum1 (), sum2 ()
What to do to explicitly describe an interface in C ++?
- The C ++ language has some minor problems (the syntax leaves much to be desired)
class IFoo { public: virtual ~IFoo() {} virtual int a() = 0; virtual int sum1() = 0; virtual int sum2() = 0; };
Lord, what is it?
-
Virtual destructor : ~ Foo ().
- Pure virtual methods: a (), sum1 (), sum2 ().
And now what to do with this IFoo?
- Inherited from it by the Foo class.
class Foo : public IFoo { int a; static int b; public: Foo() { a = 0; } ~Foo() { a = 0; } int a() { return a; } static b() { return b; } int sum1() { return a+b; } int sum2() { return a()+b(); } };
Now the interface of the class
Foo is described explicitly. The class
Foo can be called the implementation (implementation) of the interface
IFoo . It is necessary to use objects of the
Foo class via the
IFoo interface as follows:
IFoo * foo = new Foo(); int a = foo->a(); int sum1 = foo->sum1(); int sum2 = foo->sum2();
What does this give us?
- Well, just look at the function:
void process(IFoo * foo) {
Any implementation of the
IFoo interface can be passed to the
process function. It can be both
Foo and
SuperFoo and
GiperPuperFoo .
In C #, Java, and other languages, there is an interface keyword that is used to describe interfaces:
interface IFoo { public int a(); public int sum1(); public int sum2(); };
In Microsoft Visual C ++ there is a __interface keyword, more
here .
What is SOLID?
“SOLID is the abbreviation of the five basic principles of class design in object-oriented design.”
WikipediaS | Srp | Single responsibility principle | The principle of a single division of responsibility |
O | OCP | Open / closed principle | Principle of openness / closeness |
L | Lsp | Liskov Substitution Principle | The principle of substitution Liskov |
I | ISP | Interface segregation principle | Interface isolation principle |
D | Dip | Dependency Inversion Principle | Principle of dependency inversion |
I will try to give a brief description of each of them.
The principle of a single division of responsibility states that each object in the program must have a sole responsibility. If the object performs many different duties - it must be cut. For example, the report printing object is responsible for the format and content of the reports - this is wrong. One object must be responsible for the format, and another for content.
The principle of openness / closeness requires that classes, modules, functions be open for expansion, but closed for change. The bottom line is that once created classes / functions can not be changed to the specific needs of a particular project. It is allowed only to correct errors in them - no more than that. To change the behavior of a class / function, it is necessary to explicitly describe its interface and create another implementation of this interface.
The principle of substitution Liskov in general suggests that inheritance is properly used to create program hierarchies of the
common-particular type , but not in some cases not
part-whole . Example: the wheels of a car is a part-whole, and the “wheel of a passenger car” with respect to the generalized essence “wheel” is a common-partial relation.
The principle of isolation of an interface states that it is more correct to use a set of specialized interfaces, rather than grouping completely unrelated methods into common interfaces.
The principle of dependency inversion is necessary to ensure the interchangeability of objects without edits throughout the code and to weaken dependencies in the code. When you have a class A that has a pointer to a class B, the classes are considered to be strongly related. To replace class B with any other, you will have to correct the code of class A - which is not good. It is proposed to bring the interface of class B, let's call it IB. Change pointer type in class A to IB. Thus, the dependence
A -> B was replaced by
A -> IB <- B. Now you can use any other implementation of the IB interface instead of B.
What is object-oriented design?
An object-oriented program consists of classes. In the course of the program, instances of classes are created, interact with other instances and terminate their existence. Interacting with self-similar classes form two types of hierarchies:
- Hierarchy of relations part / integer
- Hierarchy of public / private relationships
What does a shared / private hierarchy look like?
- Hierarchy of land transport types:
- Hierarchy of wheel types:
What does the part / integer hierarchy look like?
- Hierarchy of a car:
When designing a system, it is necessary to define hierarchies of both types.
Why is this necessary if everything works like this?
OOP was created to “reduce the complexity of the program”! When used properly, your programs can become extremely simple in their internal structure. You, as a programmer, just have to be lazy)) So here's a way to reduce the complexity of your programs, reduce connectivity, etc.
Recommended literature
- Clean code. Robert Martin ( OZON.ru )
- Refactoring. Improve existing code. Martin Fowler ( OZON.ru )
- Object-oriented analysis and design with examples of applications. Grady Butch ( OZON.ru )
- Object-oriented design techniques. Design patterns. E. Gamma, R. Helm, R. Johnson, J. Vlissides ( OZON.ru )
PS In one of the J2ME programming books in the chapter on OOP there was this phrase: “If for you OOP is the Palestine Liberation Organization, turn to another more fundamental book.” Now this phrase is associated with the wrong understanding of the PLO.