JavaRush /Java Blog /Random EN /Object Oriented Programming
Exidnus
Level 38
Санкт-Петербург

Object Oriented Programming

Published in the Random EN group
Translator's note: Unfortunately, I don't have any significant experience in translating from English, although I read quite a lot in English. But it turned out that reading and translating are two different things. Also, unfortunately, I don't have much programming experience (recently I just made a simple web application using Spring MVC and Hibernate). Therefore, the translation turned out much worse than it could have been. I took the liberty of correcting the code examples that are given in the article a little, as they do not follow the naming conventions (code conventions) in Java. Perhaps it was not worth translating the name of some patterns (such a translation does not give much for understanding), but I considered that this is the lesser evil. Separately, it is worth mentioning "high cohesion" as a translation of "high cohesion". I agree, not the best translation. But "strong coupling" is "high coupling" (another important concept), and "coherence" is hardly suitable here. I am open to criticism and will gratefully accept comments on the article in any form. Object-oriented programming is a style of programming in which a program consists of components that correspond to real-world objects. Any real-world object has some properties (which may or may not change over time) and behavior (which may or may not change depending on others). conditions). For example, a pencil is a real world object that has the following properties:
  • It is red (this does not change over time).
  • It is 10 centimeters long now (this may change if the pencil is sharpened).
And it has the following behavior:
  • It leaves a mark if used correctly.
  • The trace may differ depending on the pressure (depends on external factors).
  • Its length shortens when sharpened (permanent behavior).
As in this example, real world objects can have many properties, but when writing programs, we only take into account the necessary properties. Object-oriented programming has its advantages. For example, it makes it easier to establish a connection between a real world object and a program in the way expected. This really helps as the application grows and many objects interact with each other. This helps in the distribution of responsibility within the objective world, allowing you to focus on thinking through the application. Another important feature associated with OOP(Object Oriented Programming) is a classification of objects. Since the world (real/virtual) is full of objects, it is difficult to manage individually. We need a way to classify these objects that will help us relate different objects and their properties, such as a black pencil. It would be indistinguishable (same?) if used in the previous example, but it is a different object. But since they are both pencils, they belong to the same Pencil class. Whereas a pen, which is very similar to a pencil, belongs to another class. However, the pen and pencil are both "Writing Instruments". Object-oriented programming has the following principles:
Abstraction
Abstraction is defined as the characteristic feature (quality) of interaction with ideas rather than events, or, in other words, freedom from representative qualities . This allows programmers to focus on what to program rather than how . An abstraction can be thought of as a convention by which we provide functionality. Implementation details can be hidden if this concept is used. For example, if we need a class that writes, then we must be sure that it has the "write" methods abstract class writer { write (); } What have we done? We designed a high-level class that is abstract, in other words, it knows what kind of functionality we need, but how to implement it is out of scope (out of scope) of this class. This provides many benefits:
  • We disclose the minimum information necessary to external entities, this allows us to focus on thinking through the program (this enable focused thinking), avoid confusion and not make unintentional promises.
  • We leave room for improvements in the future that would not be possible if implementation details were disclosed.
Inheritance
"Inheritance" in common English means "acquire and pass on." This word has been in our culture for a very long time. Ancestors acquired land through hard work and passed it on to their children, even nature favors inheritance. All properties of the body, such as height, skin/eye/hair color, etc. dependent on genes, we inherit from our parents. Inheritance prevents the wheel from being reinvented and speeds up progress. The same is true in OOP. We create a parent class with a few basic properties/behaviors. All classes that inherit from this parent will contain the same properties/behavior as their parent. However, inherited classes may get more properties/behavior or change the implementation of the behavior. class WritingInstrument { colour; write() { } } class Pen (child of parent) { inkcolour; } In the example above, the parent class (WritingInstrument) has a "color" property and a "write" behavior. When a derived class (pen) is declared, the color property and the write behavior need not be redeclared. They are present in the "handle" class by virtue of inheritance. However, a derived class may declare its own additional properties/behavior. How can we put this into practice? We developers are very lazy. We don't want to type something over and over again. The existence of multiple copies of the same code is not welcome due to the following considerations:
  • The fewer copies of the code, the easier it is to maintain.
  • If there are not multiple copies of the code, then a change in one place becomes visible everywhere.
  • The less code, the fewer bugs.
  • If one code is used in many places, then generalization is achieved.
  • We focus on writing code.
  • We focus on tests.
Inheritance in Java is achieved using the "extends" and "implements" keywords. class WritingInstrument { } class Pen extends WritingInstrument { }
Polymorphism
The word "polymorphism" comes from two words: "Poly" , i.e. "multiple" / "more than one" "morph" , i.e. "shape" Literally, the word "polymorphism" refers to the ability of objects to behave differently depending on conditions. In programming, polymorphism can be embodied in several places:
  • Classes
  • Methods
  • Operators
All of the above may behave differently depending on the conditions, perhaps the context, in which they are used. This is useful because the client (the programmer using your libraries) doesn't need to know a lot of subtleties, and the desired functionality is implemented by selecting the necessary information from the context. Class WritingObject { wrire() { // пишем, используя стандартные (по дефолту) цвета } } class Pencil extends WritingObject { write() { // пишем, используя серый цвет, написанный текст можно стереть } } class Pen extends WritingObject { write() { // пишем, используя голубой цвет, написанный текст нельзя стереть } } class Main { main() { WritingObject wr = new WritingObject(); wr.write(); // первый вызов WritingObject wr = new Pen(); wr.write(); // второй вызов WritingObject wr2 = new Pencil(); wr2.write(); // третий вызов } } The example above has a default implementation in WritingObject, which is extended/overridden by pen and pen derived classes. The write() method is called three times in the Main class. Each time a different implementation is called depending on which object this method is called on. In this case, the write() method has many behaviors because it is polymorphic.
Encapsulation
Encapsulation is defined as the collection of related data/functionality in a single unit. This helps in facilitating data access/modification. For example, if we want to print all properties that a given user has, we have the following options: printUserProperties(userName, userId, firstname, lastname, email, phone, … … ….) We have created a method that accepts all properties and prints them one after the other. With an increase in the number of elements in the list, the ability to identify the correct fields will disappear, and adding / removing one field will change the method signature. Therefore, we need to replace all users of this method, even if they do not need the newly added fields. To make the code more readable and make future modifications easier, we encapsulate the properties in a class and turn it into a collective object. class User { userName userId firstname lastname email phone .. .. .. } printUserProperties(user) {} An object is a system (software bundle) of variables and associated methods. You can represent real world objects using program objects. You can represent real dogs in an animation program, or a real bicycle as a software object inside an exercise bike. In OOP, a class is an extensible template (program-code-template) for creating objects, providing them with an initial state (variables) and implementing behavior (functions, methods). The acronym SOLID was coined by Michael Feather for the "first five principles" so named by Robert C. Martin in the early 2000s. The purpose of the principles implemented jointly is to increase the likelihood that the programmer will create a system that is easy to maintain and extend. SOLID principles- guidelines in the development of programs that are necessary to remove the "rotten" code through refactoring, as a result of which the code should become easily readable and extensible. This is part of the agile and adaptive programming strategy (flexible and adaptive programming).
Single Responsibility Principle
In OOP, the Single Responsibility Principle states that each class should be responsible for one piece of functionality provided by the program, and that responsibility should be completely encapsulated by that class. All its functionality should be closely related to this responsibility.
Open/Closed Principle
In OOP, the open/closed principle states "software entities (classes, modules, methods, etc.) should be open for extension but closed for modification." In other words, an entity should allow its behavior to be extended without changing the source code.
Liskov Substitution Principle
Substituability is a principle in OOP. It states that if S in a computer program is a subtype of T, then objects of type T must be such that they can be replaced by objects of type S (i.e. objects of type S can replace objects of type T) without changing any of the required properties programs (accuracy, task completion, etc.).
Interface Segregation Principle
The Interface Separation Principle states that a client programmer should not be forced to depend on methods that he does not use. According to this principle, it is necessary to divide large interfaces into smaller and more specific ones, so that the client programmer knows only about the methods that are of interest to him. The purpose of the Interface Decoupling Principle is to keep the system in an uncoupled state (system decoupled), which will make it easier to refactor, make changes, and redeploy.
Dependency Inversion Principle
In OOP, the principle of dependency inversion refers to a specific form of disconnection between software modules. By following this principle, the standard dependency relationships established from the high-level modules that form the application architecture (policy-setting) to the dependent low-level modules are inverted (inverted), so the modified high-level modules become independent of the implementation details of the low-level modules. This principle states:
  • High level modules should not depend on low level modules. Modules of both types must depend on abstractions.
  • Abstractions should not depend on implementation details. Details should depend on abstractions.
The principle inverts the way that people can think of object-oriented design, stating that high-level and low-level objects should depend on the same abstractions.

GRASP Principles

Patterns (principles) used to solve the general tasks of assigning responsibilities to classes and objects (General Responsibility Assignment Software Patterns (GRASP)) contain guidelines (guidelines) for assigning responsibilities to classes and objects in object-oriented design.
Controller
The Controller pattern assigns responsibility for interacting with system events to non-GUI classes that represent the entire system or use case scenario. Controller:
  • It is an object that does not interact directly with the user and is responsible for receiving and responding to system events.
  • Should be used to deal with all system events of one (or multiple related) use cases.
  • It is the first object behind the GUI that controls system operations.
  • He does not have to do the work himself, his task is to control the flow of events.
Creator
The task of the creator class is to create and initialize objects for later use. It knows the initialization parameters as well as which object will be created. Sometimes the creator class creates objects actively and caches them, and provides one instance when needed.
High cohesion (High Cohesion)
High entanglement is an evaluation pattern that aims to keep objects in a state that is focused on a single, clear task and is easily manageable and understandable. High entanglement is usually used to support low coupling (Low Coupling). High connectivity means that the responsibility of this element is clearly indicated (strongly related and highly focused). The division of a program into classes and subsystems is an example of actions that increase the cohesion of the properties of the system. Weak entanglement, on the other hand, is a situation in which an element has too many unrelated tasks. Loosely cohesive elements tend to be hard to understand, hard to reuse, maintain, and change.
Roundabout (Indirection)
The Roundabout pattern maintains loose coupling (and reusability) between two elements by assigning responsibility for the interaction between them to an intermediate object. An example is the introduction of a controller to mediate between data (model) and its display (view) in the Model-View-Controller (MVC) pattern.
Information Expert
Information Expert (also Expert or Expert principle) is the principle used to determine to whom to delegate responsibility. Responsibility includes methods, calculated fields, and so on. When using this principle in assigning responsibility, the main approach is the following sequence of actions: analysis of responsibility, determination of the information that is needed for its execution, and finally, establishing where this information is located. Using the Information Expert principle results in assigning responsibility to the class that has the most information to fulfill it.
Weak Coupling
Weak coupling is an evaluative pattern that indicates how to assign responsibility: weak dependency between classes, changing one should have minimal consequences for the other, maximum reusability.
Polymorphism
Responsibility of defining the variation of behaviors based on type is assigned to the types for which this variation happens, according to polymorphism. This is achieved using polymorphic operations.
Protected Variations
The Protected Changes pattern protects elements from changes to other elements (objects, systems, subsystems) by wrapping the focus of instability with an interface and using polymorphism to create different implementations of that interface.
Pure Fabrication
Pure construction involves a class that does not represent a concept in the problem domain and is designed specifically to achieve loose coupling, high cohesion, and therefore maximum reusability (the solution offered by the Information Expert pattern does not provide this). Such a class is usually called “Service” in Domain-driven design.

Criticism

Research by Potok et al. showed no significant differences between OOP and procedural approaches.
Critical comparison of OOP with other technologies, especially relational technologies, is difficult due to the lack of a definition of OOP that is rigorous and widely accepted (Christopher J. Date)
Compared to other languages ​​(LISP dialects, functional languages, etc.), OOP languages ​​do not have a unique advantage and impose unnecessary complexity. (Lawrence Krubner)
I find object-oriented programming technically unsound. It tries to decompose the world into parts in terms of interfaces that change within the same type. To deal with real problems, you need multi-sorted algebras - families of interfaces that extend over many types. I find object-oriented programming philosophically unhealthy. It states that everything is an object. Even if it is, it's not very interesting: to say that everything is an object is to say nothing at all. (Alexander Stepanov)
The popularity of OOP among large companies is due to "large (and often changing) groups of mediocre programmers." The discipline imposed by OOP prevents the programmer from doing "too much harm". (Paul Graham)
Object-oriented programming puts nouns first and foremost. Why go to such extreme measures and put one part of the speech on a pedestal? Why does one concept take precedence over another? It's impossible for OOP to suddenly make verbs less important to our thinking. This is a strangely skewed perspective. (Steve Yegge)
Rick Hickey, the creator of Clojure, has described object systems as highly simplified models of the real world. He emphasized the inability of OOP to model time correctly, which creates huge problems when multithreading becomes widespread in programs. Eric S. Raymond, a Unix programmer and open source proponent, was critical of the claim that OOP is "The Only True Solution" and wrote that OOP encourages layered programs, which hinders transparency. As an opposite approach, Raymond gave the example of Unix and C.

Links

By Margaret Rouse @ WhatIs.com Wikipedia! ( Russian version ) inheritance is polymorphism SOLID (Object Oriented Design) ( Russian version ) Single Responsibility PrincipleArguments against OOPS ( Russian version ) What is OOPS (without the hype) Translation: Varygin D.V.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION