Перейти до вмісту

Class

Матеріал з K2 ERP Wiki

class Box<T> {

class EmailAddress {

</syntaxhighlight> Добрий service class має чітку відповідальність.; } Проста аналогія: class — це форма для печива, object — конкретне печиво, яке з цієї форми зробили.; * `User`;

  • `Order`;
  • `Invoice`;
  • `PaymentGateway`;
  • `EmailSender`;
  • `Cart`;
  • `Money`;
  • `DateRange`;
  • `UserRepository`;
  • `PasswordResetService`.;

Приклад checklist для Class

God Class

Приклад:

const user = await userService.findUser(request.params.id);

істотно: property виглядає як інформаційні дані, але іноді за нею має змогу стояти логіка.; info(message: string) {

class EmailAddress {

class User:

deposit(amount: number) {

Class і Struct

console.log(MathUtils.double(5));

EmailSender class

public class User {

;
* конфлікти методів;
* diamond problem;
* складніша логіка lookup;
* важче читати код;
* несподівана поведінка.; Class описує конкретний тип обєкта.; Іноді це без ускладнень складність у костюмі дизайну.; Якщо назва туманна, клас уже важче зрозуміти.;<syntaxhighlight lang="python">
 std::string name;
'''Практична порада:''' controller не має містити всю бізнес-логіку.; TypeScript додає до JavaScript classes типи й access modifiers.; Інакше subclass має змогу ламати код, який функціонує з base class.; * collections;
* repositories;
* wrappers;
* result types;
* API responses;
* reusable data structures.; це шаблон, характеристика або модель; додатково реалізовано які обєкт зберігає, і поведінка, яку він має змогу виконувати виступає ключовою рисою створення обєктів у програмуванні.; }
Добрий domain class містить не тільки поля, а й поведінку, яка має сенс у бізнесі.;</div>
'''Mutable class''' надає можливість змінювати стан object після створення.; |-
| Class
| Шаблон для створення обєктів
|-
| Module
| Організаційна одиниця коду або namespace
|}

Ознаки:

}
class CreateUserDto {
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

'''Class/static method''' викликається на самому класі.; }
Сильний клас має чітку відповідальність, зрозумілу назву, захищає свій стан, підтримує роботу invariants і не робить зайвого.; }
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

</div>

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

* давати класам точні назви;
* тримати одну основну відповідальність;
* приховувати internal state;
* робити objects валідними після constructor;
* не створювати God classes;
* не будувати глибокі inheritance trees без потреби;
* надавати маленький public interface;
* використовувати composition, коли inheritance зайве;
* писати tests для важливих methods;
* не змішувати domain logic і infrastructure без потреби;
* захищати invariants;
* використовувати immutable objects там, де це доречно;
* передавати dependencies через constructor;
* не використовувати static state без потреби.;<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
Приклад Java:
 private status: "draft" | "paid" | "cancelled" = "draft";

== DTO Class ==

 private String name;

 addItem(item: string) {

</div>
 private items: string [] = [];
 print("Sound")
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
Приклад:

<syntaxhighlight lang="typescript">
Клас часто поєднує '''state''' і '''behavior'''.; Processor
 }

!; ) {

Краще:

У domain-driven design клас має змогу представляти поняття предметної області.; Суть

}

'''Value object'''  обєкт, який визначається значенням, а не identity.;<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
Поширено в Kotlin.; Код, який викликає `send`, не мусить знати всі деталі SMTP, retries, templates або provider API.; У багатьох системах composition дає гнучкіший дизайн.;</div>
+ changeEmail()
'''Inheritance''' або '''наслідування''' надає можливість одному класу успадковувати властивості й методи іншого класу.; // cannot be subclassed
'''Interface''' описує контракт, а class реалізує поведінку.; }

 public price: number
</div>

 public readonly amount: number,
== Base Class і Derived Class ==
</div>
 }
'''Nested class'''  клас, оголошений всередині іншого класу.;== Class у Ruby ==

'''Практична порада:''' nested class корисний, коли тип має сенс тільки в контексті зовнішнього класу.; class UserController {
</div>
Ruby classes підтримують:

Практична роль: method відповідає на питання: “Що цей об’єкт має змогу робити?”

Приклад:

Помилка: більше класів не означає кращу архітектуру.; * Data classes і records з’явилися, щоб прибрати boilerplate для простих data containers.; Погано спроєктований клас має змогу зробити код складнішим.; User

class DataManager { Favor composition over inheritance

self.balance = balance

class User: Приклад:

def __init__(self, name):

}

Приклад: Invariant — правило, яке має залишатися істинним для об’єкта протягом його життя.; class BankAccount:

Repository Class

</syntaxhighlight>

Це має змогу бути корисно для:

}

return this._name;

class Car extends Vehicle {

C++ `class` має private members за замовчуванням, `struct` — public
C# class — reference type, struct — value type
Swift class — reference type, struct — value type
return "Hello, " + name;

Приклад Python: class Cat {

class Circle extends Shape {

</div>
як ілюстрація, користувач системи має змогу змінити email, але все одно лишається тим самим user за `id`.;
<syntaxhighlight lang="typescript">

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
}
 constructor(name) {
'''Практична роль:''' mixin надає можливість додавати домішки поведінки без створення великої inheritance tree.; {| class="wikitable"
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
if (!value) {

Ризики:

describe() {

</syntaxhighlight>

this._name = value;
def speak(self):

істотно: якщо клас не проєктувався для inheritance, іноді краще явно заборонити наслідування.;== Inheritance vs Composition ==

}
void speak() {
  • fields;
  • properties;
  • methods;
  • constructor;
  • access modifiers;
  • static members;
  • inheritance rules;
  • validation logic;
  • business behavior;
  • internal state;
  • relationships with other classes.; constructor(

Method Overriding

істотно: ООП не означає автономно хороший дизайн.; Цікавий момент: хороший клас — це не без ускладнень “коробка для даних”, а охоронець правил, за якими ці інформаційні дані можуть змінюватися.;</syntaxhighlight>

  • reusable behavior;
  • logging;
  • serialization;
  • validation;
  • permissions;
  • UI behavior;
  • shared methods.;== Недоліки і ризики Class ==

Class diagram — UML-діаграма, яка показує класи, fields, methods і relationships.; class Dog(Animal): Тут `User` — клас, а `anna` і `oleh` — об’єкти.; Клас має змогу бути зайвим, якщо:

status: string;
def __init__(self, balance):

{

Module часто групує functions, classes, constants або types.; Класи є собою фундаментальним поняттям ООП і використовуються для моделювання domain entities, services, repositories, controllers, value objects, UI components і багатьох інших частин програм.;</syntaxhighlight> Controller має змогу: істотно: не кожен клас має бути “розумним”, але domain entity без поведінки часто втрачає сенс ООП.; self.name = name

Цікавий факт: у Python класи самі є собою об’єктами, з цієї причини їх можна передавати, змінювати й створювати динамічно.; Поширені modifiers: переважні аспекти immutable classes:

Чи не є собою це God class?; Функція `makeSound` не знає, чи отримала Dog, Cat або інший об’єкт.; істотно: не треба робити клас лише з цієї причини, що “так серйозніше виглядає”.;

}

</syntaxhighlight>

return "Meow";
speak() {
drive() {
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
<syntaxhighlight lang="java">
'''Object-Oriented Programming''' або '''ООП'''  стиль програмування, у якому програма моделюється через objects, classes і взаємодію між ними.;== Polymorphism ==
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

Чи захищені invariants?; Поширено в Java та деяких інших мовах.; * У Ruby майже все є собою object, навіть числа й класи.; Приклад TypeScript:

* `dataclass` у Python;
* `record` у C#;
* `data class` у Kotlin;
* `case class` у Scala;
* `record` у Java;
* `struct` у Swift.; Ризик
</div>
</div>
 ) {}
</div>

== Class у TypeScript ==

* types;
* interfaces;
* access modifiers;
* generics;
* abstract classes;
* decorators у частині сценаріїв;
* readonly fields;
* parameter properties.; Приклад ідеї:
- email
 data: any;

<syntaxhighlight lang="text">

* простіше reasoning;
* безпечніше в concurrency;
* менше side effects;
* легше тестувати;
* стабільні value objects.; Це спосіб моделювати систему через відповідальності, межі й поведінку.; Клас `GameCharacter` зберігає health, position, inventory і methods для movement або actions.; return $"Hello, {Name}";
 end
<syntaxhighlight lang="javascript">

class User:

  • легше тестувати;
  • легше замінювати реалізації;
  • менше hardcoded dependencies;
  • чистіша технічна архітектура;
  • краще separation of concerns.; }

class User end

send(to: string, message: string): Promise<void>

class User {

email: string;
return `Hello, ${this.name}`;

class Product {

}
return f"Hello, {self.name}"
<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">

Utils

Клас `User` зберігає identity, email, name і методи для зміни профілю.; Слабкий клас має змогу перетворитися на God class, зайву abstraction або без ускладнень контейнер без сенсу.; C# classes підтримують:
 }
`Dog` наслідує `Animal` і змінює поведінку `speak`.;<syntaxhighlight lang="typescript">
 greet() {
 area() {
 }
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">

== Controller Class ==
}
 console.log(animal.speak());

 abstract area(): number;

* Матеріали з object-oriented programming щодо classes, objects, inheritance, encapsulation, polymorphism і abstraction.; name: string;
</div>
<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

 def __init__(self, name):
 }
Приклади:
== Class у Python ==
</div>

</div>
Підтримується в деяких мовах, як ілюстрація C++ і Python.;<syntaxhighlight lang="java">
Order

 def greet

=== User class ===

Підказка: хороший class зазвичай можна пояснити одним реченням: “Цей клас відповідає за…” Runnable task = new Runnable() { Anemic class або anemic domain model — клас, який майже не має поведінки й лише зберігає інформаційні дані.; {| class="wikitable"

private engine: Engine,
  • User;
  • Order;
  • Invoice;
  • Customer;
  • Product;
  • Account;
  • Project.; Чи без зайвих зусиль написати tests?; Це комфортно, але не варто робити приховану складну роботу без потреби.; * Документація мов програмування Java, C#, C++, Python, JavaScript, TypeScript, Ruby, Kotlin і Swift щодо class syntax і object model.; Клас варто створювати, якщо:

переважні аспекти Class

}

}

Method — функція, яка належить класу або об’єкту.; console.log(message);

Чи прихований internal state?; InvoiceGenerator

'''істотно:''' SRP не означає один метод на клас.; '''Практична роль:''' у C# class часто є собою основним способом моделювання domain logic, services, entities і application components.;</div>
}
 count = 0

'''Mixin'''  спосіб додати класу поведінку без класичного глибокого inheritance.; }
== Access Modifiers ==

'''Immutable class'''  клас, обєкти якого не змінюються після створення.; greet(): string {
</div>
Приклад:

 }

</div>
Приклад:
Чи має клас зрозумілу назву?; * classes;
* interfaces;
* inheritance;
* access modifiers;
* constructors;
* static members;
* annotations;
* generics;
* packages.; class UserService {

'''Практична роль:''' checklist сприяє відрізнити корисний клас від зайвого архітектурного шуму.; * Матеріали щодо refactoring, class design, UML class diagrams, composition over inheritance і testing object-oriented code.; Ruby є собою дуже обєктно-орієнтованою мовою: майже все є собою обєктом.; '''Головна думка:''' class  це не без ускладнень синтаксис мови.; }

interface Logger {

</syntaxhighlight> Constructor зазвичай: Практична роль: value object надає можливість сховати правила й validation у маленькому класі замість розкидати їх по всьому коду.; class UserRepository {

Тематичні мітки

await this.emailSender.send(user.email, "Welcome");

TypeScript classes можуть використовувати:

Приклад: Service class містить логіку, яка не належить природно одному entity або value object.; * У JavaScript class syntax виглядає класично, але базується на prototypes.; }

Mixin

  • `self`;
  • dynamic attributes;
  • inheritance;
  • magic methods;
  • dataclasses;
  • class variables;
  • properties;
  • multiple inheritance;
  • duck typing.; }
total: number;

Приклади:

Практична порада: якщо ви постійно передаєте разом ті самі інформаційні дані й функції, можливо, вони просяться в клас.; Клас `EmailSender` приховує деталі SMTP або external API й дає простий method `send`.; if (!value.includes("@")) {

істотно: service class без зайвих зусиль перетворити на “мішок логіки”.;
Приклад:

class User {
const stringBox = new Box<string>("hello");
=== GameCharacter class ===
 @classmethod
 print("Woof")
'''Практична роль:''' anonymous class зручний для короткої одноразової реалізації interface або abstract class.; * state — інформаційні дані об’єкта;
* behavior — дії об’єкта.;<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
== Class і Dependency Injection ==
 if (!value.includes("@")) {

abstract class Shape {

Це не завжди погано: DTO або simple data class можуть бути anemic навмисно.; }
 private emailSender: EmailSender,
Приклад:

'''Головне правило:''' хороший клас має бути зрозумілим за назвою, безпечним у використанні й обмеженим у відповідальності.;== Abstraction ==
 constructor(private radius: number) {
 return cls.count
}
) {}
private balance = 0;
// database write

Final Class

`greet` функціонує з конкретним user, а `total_users` — з class-level state.;== Service Class ==

  • має чітку відповідальність;
  • має зрозумілу назву;
  • приховує внутрішній стан;
  • не робить забагато;
  • захищає invariants;
  • без зайвих зусиль тестується;
  • має невеликий public interface;
  • не залежить від усього підряд;
  • відповідає предметній області.; constructor(
const user = await this.userRepository.findById(userId);

- id

PaymentGateway class

Manager Property — властивість об’єкта.;== Див.; додатково ==

  • безпеки;
  • стабільності API;
  • performance optimization у частині мов;
  • заборони неправильного extension;
  • immutable value objects.; // unclear responsibility

Особливості Python classes:

  • PaymentService;
  • EmailService;
  • ReportService;
  • OrderPricingService;
  • AuthService;
  • NotificationService.;
  • є собою стан і поведінка;
  • потрібні invariants;
  • є собою domain entity;
  • потрібно кілька пов’язаних methods;
  • потрібна polymorphism;
  • потрібна lifecycle-логіка.; Приклад, де клас зайвий:

Class і Object

  • є собою проста операційна дія;
  • немає складного стану;
  • логіка чиста;
  • потрібне перетворення даних;
  • немає потреби створювати object.; Приклад:
return Math.PI * this.radius * this.radius;
}

</syntaxhighlight>

У цьому прикладі `name` і `email` — fields.; Composition — підхід, де клас використовує інші об’єкти як частини, замість надмірного наслідування.;
  • properties;
  • methods;
  • interfaces;
  • inheritance;
  • generics;
  • access modifiers;
  • records;
  • partial classes;
  • attributes;
  • async methods.;== Приклади сценаріїв використання ==
if (amount < 0) {
throw new Error("Amount cannot be negative");
}
}

} </syntaxhighlight>

response.json(user);
public string Name { get; set; }
{
  • сотні або тисячі рядків;
  • багато unrelated methods;
  • багато dependencies;
  • важко тестувати;
  • важко змінювати;
  • клас застосовується всюди;
  • назва типу `Manager`, `System`, `AppService`;
  • будь-яка зміна ризикована.; Поняття

} Приклади:

Приклад ідеї:

Name = name;

Polymorphism або поліморфізм надає можливість працювати з різними об’єктами через спільний інтерфейс або base class.;

Composition

  • `public`;
  • `private`;
  • `protected`;
  • `internal`;
  • `readonly`;
  • `static`;
  • package-private у частині мов.;</syntaxhighlight>

!; Class design — бізнес-процес визначення, за що клас відповідає, які має fields, methods і relationships.;

Приклад JavaScript:

  • є собою сутність із state і behavior;
  • потрібно захистити invariants;
  • є собою domain concept;
  • є собою кілька пов’язаних methods;
  • потрібно створювати багато instances;
  • потрібен polymorphism;
  • потрібне dependency injection;
  • потрібне приховування details;
  • є собою lifecycle або rules;
  • проста структура даних уже не справляється.; Якщо об’єкт одразу після створення “напівзламаний”, клас спроєктований слабко.; * Найкращий клас часто має менше methods, ніж хочеться додати на старті.; Це спосіб дати програмній сутності ім’я, стан, правила й поведінку.;== Приклад хорошого Class ==
}
// database query

Entity class — клас, який має identity й життєвий цикл.;

throw new Error("Invalid email");
}
String name;

function makeSound(animal: { speak(): string }) {

Чи не є собою це зайвою обгорткою над однією функцією?; Клас є собою одним із ключових понять object-oriented programming або ООП.; !; constructor( };

 constructor(name) {

* validation;
* computed properties;
* controlled access;
* backward compatibility;
* hiding internal representation.; }
Приклад:
Приклад C#:

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

== Anonymous Class ==

 }

</div>

== Class Naming ==

 this.engine.start();

- status

== Anemic Class ==

 console.error(message);

 }

<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">

!; * приймає початкові інформаційні дані;
* ініціалізує fields;
* перевіряє параметри;
* встановлює default values;
* готує object до роботи.;</div>

Чи немає зайвого inheritance?;<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
`user`  instance класу `User`.; Суть
</div>
<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

* імя користувача;
* ціна товару;
* баланс акаунта;
* статус замовлення;
* дата створення;
* координати персонажа;
* рівень доступу.; Property має змогу:

</div>

== Приклад слабкого Class ==

<syntaxhighlight lang="text">

== Constructor ==
{| class="wikitable"
</div>
markAsPaid() {

class ConsoleLogger implements Logger {

Коли Class має змогу бути зайвим

</syntaxhighlight> Помилка: клас із назвою `Manager` часто приховує те, що команда ще не зрозуміла справжню відповідальність.; PasswordResetService

Основна ідея: class — це шаблон для створення об’єктів, який об’єднує стан і поведінку в одну зрозумілу модель.;

}

Class у Java

Abstract Class

{
'''Практична роль:''' immutable class схожий на запечатаний документ: після створення його зміст не змінюється.; Чи можна пояснити відповідальність одним реченням?; '''Class''' і '''object'''  повязані, але різні поняття.; Проблема виникає, коли domain logic розкидана по services, а domain classes не захищають власні правила.; constructor(name) {
Чи public methods справді потрібні?; Підхід

== Instance ==

* encapsulation;
* abstraction;
* inheritance;
* polymorphism.; '''істотно:''' constructor має створювати валідний обєкт.; Погано:
C# активно використовує classes у .NET-екосистемі.;== Sealed Class ==
!; }

 return this.value.split("@")[1];

* нечітка назва;
* `any`;
* багато незрозумілих methods;
* немає явної відповідальності;
* важко тестувати;
* важко підтримувати.; }

'''Проста ідея:''' inheritance надає можливість сказати: Dog  це особливий вид Animal.;</div>

* має зрозумілу назву;
* захищає invariant;
* є собою immutable;
* має корисну behavior;
* не робить зайвого.; if (amount <= 0) {
 throw new Error("Amount must be positive");
 }

 this.balance += amount;
 }

 getBalance() {
 return this.balance;
 }
}

Головне правило: клас має бути достатньо маленьким, щоб його можна було зрозуміти, і достатньо змістовним, щоб він не був зайвою обгорткою.; як ілюстрація, клас `User` описує, які поля й методи має користувач системи, а конкретний користувач системи Anna або Oleh є собою об’єктом цього класу.; * Іноді найкраще покращення класу — видалити його й залишити просту функцію.; !; God class — антипатерн, коли один клас знає й робить занадто багато.; !; Різниця |- | public | доступний ззовні |- | private | доступний тільки всередині класу |- | protected | доступний у класі й subclasses |- | readonly | значення не можна змінювати після ініціалізації у частині мов |}

}
 speak() {

class BankAccount {

- надсилає email

Generics корисні для:

* balance не має змогу бути меншим за 0;
* email має бути валідним;
* order total не має змогу бути від’ємним;
* start date не має змогу бути пізніше end date;
* user role має бути однією з дозволених;
* cart item quantity має бути більшою за 0.; * prototypes;
* `this`;
* constructor;
* class fields;
* private fields;
* static methods;
* inheritance через `extends`.; У наслідуванні є собою:
'''Method overriding''' — коли subclass замінює реалізацію методу з parent class.; }
|-
| Interface
| Що об’єкт має вміти
|-
| Class
| Як саме це реалізовано
|}

class Counter:
<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

- зберігає в database

const phone = new Product("Phone", 500);

Приклад:

class Cart {
 public User(String name) {
== Getter і Setter ==
'''Sealed class''' обмежує, які класи можуть її наслідувати.;<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
'''Field''' — змінна, яка належить об’єкту або класу.; Це потужно, але потребує обережності.; '''Практична роль:''' назва класу — це перша документація.; Цей клас:
Python підтримує роботу класи, але має більш динамічну модель.; Якщо ім’я вибрано добре, код починає читатися майже як мова задачі.; Приклад
class User
Приклади:

Чи зрозуміє цей клас інший розробник через місяць?; !;<syntaxhighlight lang="kotlin">

EmailSender

* stateful objects;
* UI components;
* game objects;
* sessions;
* accumulators;
* workflows;
* domain entities.;

Getters і setters корисні для:

  • overengineering;
  • God class;
  • class explosion;
  • складна inheritance tree;
  • tight coupling;
  • mutable state bugs;
  • hidden side effects;
  • boilerplate;
  • складне тестування при поганих dependencies;
  • надмірні abstractions;
  • неправильне моделювання domain;
  • плутанина між class і data structure.; console.log("Moving");

Anonymous class — клас без імені, який створюється прямо на місці використання.; }

Приклад TypeScript:
У цьому прикладі `items`  state, а `addItem` і `countItems`  behavior.;<syntaxhighlight lang="javascript">
 // unknown behavior
 constructor(public value: T) {}

<syntaxhighlight lang="typescript">

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

як ілюстрація, клас `EmailSender` має змогу мати метод:

!; }

* constructors;
* destructors;
* copy/move semantics;
* operator overloading;
* templates;
* inheritance;
* virtual methods;
* RAII;
* access control.; Коли корисний
Класи є собою важливою частиною ООП, але ООП  це не без ускладнень створити багато класів.; UserManager:
== Immutable Class ==

- рахує billing
== Interface і Class ==
super();

Чи не краще використати composition?; ) {} class Failed(val reason: String) : PaymentResult() public:

Клас `Order` має items, status, total і методи `addItem`, `markAsPaid`, `cancel`.; Окремо варто відзначити Java, C# і інших мовах.; Клас має змогу захищати invariants через constructor, methods і access modifiers.; class Order {

У Java класи є собою центральним елементом мови.; як ілюстрація, у реальному світі автомобіль  це клас, а конкретна машина біля будинку  обєкт.; Часто краще делегувати її service або domain layer.; * повторне використання поведінки;
* гнучкі ієрархії;
* mixin-подібні patterns.; Він означає одну зрозумілу відповідальність.; '''Практична роль:''' замість передавати email як простий string всюди, клас `EmailAddress` робить правило валідності явним.; Не варто переносити правило з C++ напряму в C# або Swift.; '''істотно:''' JavaScript classes виглядають схоже на Java або C#, але модель мови має власні особливості.; '''Головна перевага:''' клас сприяє перетворити розрізнені інформаційні дані й функції на зрозумілу програмну сутність.;<div style="background:#e8f8f5; border-left:6px solid #16a085; padding:12px; margin:12px 0;">

</div>
 set name(value) {
'''Abstraction''' або '''абстракція''' у класах означає виділення суттєвого й приховування деталей.; У деяких мовах є собою і `class`, і `struct`.; !;

ReportExporter

public final class Money { } - id

}

Generic class — клас, який функціонує з типом як параметром.; void speak() {

  • helper objects;
  • тісно пов’язаних типів;
  • builders;
  • iterators;
  • implementation details;
  • logical grouping.;== Class у C# ==
honk() {
info(message: string): void;

істотно: private — це не без ускладнень “сховати від очей”, а спосіб зберегти invariants класу.; @name = name

Якщо об’єкт — це конкретна річ у програмі, то клас — це креслення, за яким такі речі створюються.; Цікавий факт: у Ruby можна “відкрити” існуючий клас і додати до нього методи.; public User(string name)

Instance або екземпляр — це конкретний об’єкт, створений на основі класу.;== Object-Oriented Programming == </syntaxhighlight>

Instance method викликається на конкретному об’єкті.; } sealed class PaymentResult Практична роль: class diagram сприяє побачити структуру системи до або під час реалізації.; + markAsPaid()

from dataclasses import dataclass

Практична роль: entity class моделює сутність із власною ідентичністю, правилами й історією змін.; class Animal { Основні принципи ООП: }

`deposit` — method.;

return "Woof";
public name: string,

</syntaxhighlight>

  • `calculateTotal`;
  • `sendEmail`;
  • `approveOrder`;
  • `withdraw`;
  • `render`;
  • `validate`;
  • `save`;
  • `move`;
  • `login`.; * Глибока inheritance tree має змогу виглядати красиво на діаграмі, але бути дуже болючою в підтримці.; throw new Error("Invalid email address");
'''істотно:''' у C++ class часто керує не тільки логікою, а й ресурсами: пам’яттю, файлами, locks або handles.;<syntaxhighlight lang="python">

<syntaxhighlight lang="ruby">

C++ classes можуть включати:

 id: str
self.name = name

Class Diagram

Головна ідея ООП: інформаційні дані й поведінка, які логічно належать одній сутності, можуть жити разом.; Поняття

  • створювати class для кожної маленької функції;
  • робити всі fields public;
  • не використовувати constructor для валідного стану;
  • писати God class;
  • називати класи `Manager` і `Helper`;
  • надмірно використовувати inheritance;
  • не розуміти різницю між class і object;
  • плутати static і instance members;
  • зберігати global state у static fields;
  • не тестувати behavior;
  • робити getters/setters для всього без логіки;
  • змішувати database, UI і business logic в одному класі;
  • копіювати Java-style classes у мову, де простіше використати functions.; істотно: не кожна функція має ставати класом.; І не кожен клас має існувати, якщо достатньо простої функції.; if (this.status !== "draft") {

!; this._name = name;

}

Constructor — спеціальний метод, який викликається під час створення об’єкта.;</syntaxhighlight> істотно: inheritance зручне, але його без зайвих зусиль переоцінити.; Класи використовуються в багатьох мовах: </syntaxhighlight>

Клас або interface `PaymentGateway` описує спосіб приймати платежі, а конкретні реалізації працюють із Stripe, PayPal або іншим provider.; } const user = new User("Anna");

self.name = name

Приклад:

async save(user: User): Promise<void> {
  • організація коду;
  • моделювання предметної області;
  • поєднання state і behavior;
  • encapsulation;
  • reuse;
  • polymorphism;
  • abstraction;
  • testability у хорошому дизайні;
  • супровід великих систем;
  • зрозумілі APIs;
  • type safety у типізованих мовах;
  • контроль invariants;
  • можливість inheritance або composition.;== Class і Module ==

Single Responsibility Principle

def initialize(name)

Value Object Class

public string Name { get; }

} Основні переважні аспекти класів: class Success(val id: String) : PaymentResult() class Order {

Order class

</syntaxhighlight>

return `Hello, ${this.name}`;

У деяких мовах є собою спеціальні конструкції для класів, які переважно зберігають інформаційні дані.; ) {} BillingService

handle() {

Слабкі назви: - створює користувачів

Найлюдяніший факт: клас — це спосіб дати частині програми ім’я, пам’ять і поведінку.; Приклад:

'''Module''' і '''class''' теж різні.;<syntaxhighlight lang="typescript">
</div>

class Money { Composition часто формулюють як:

Fields описують стан обєкта:

Mutable classes корисні для:

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
== State і Behavior ==
 def __init__(self):
`Vehicle`  base class, `Car`  derived class.; '''Практична порада:''' не використовуйте setter, якщо зміна значення має складну бізнес-логіку.; def greet(self):

<syntaxhighlight lang="typescript">

DTO має змогу використовуватися для:

Практична роль: abstraction надає можливість користуватися класом через зрозумілий public interface, не занурюючись у внутрішню реалізацію.;
 User.count += 1
|-
| Class
| Шаблон або характеристика
| `User`
|-
| Object
| Конкретний екземпляр класу
| користувач системи Anna з email `anna@example.com`
|}

'''істотно:''' overriding має зберігати очікуваний контракт методу.; System.out.println("Meow");
Приклад:
}

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">

 end

* `Order`;
* `Customer`;
* `Invoice`;
* `Payment`;
* `Shipment`;
* `Product`;
* `Subscription`;
* `Account`;
* `Booking`.; class User:

* один простий use case розкиданий по 15 класах;
* багато classes мають по одному методу;
* назви стають штучними;
* важко знайти реальну логіку;
* абстракції створені про запас;
* code navigation стає болючою.; public void run() {
'''Repository class''' приховує доступ до даних і надає доменний інтерфейс для збереження або пошуку objects.; Назва класу має пояснювати, що він представляє або робить.;== Загальний характеристика ==
== Class Explosion ==

PaymentCaptureService

Invariant

std::string greet() {

Ознаки:

}

Цікаві факти про Class

 return `Area: ${this.area()}`;

'''Static members''' належать класу, а не конкретному object instance.; Суть

!; class Vehicle {

== Хороші практики Class ==
'''Практична роль:''' sealed class надає можливість моделювати закритий набір станів або результатів без випадкових сторонніх subclasses.; Інакше ієрархія оперативно стає заплутаною.; з цієї причини головне — не без ускладнень створювати класи, а моделювати ними реальні поняття й відповідальності системи.; Якщо потрібен лише контракт, interface часто простіший.;</div>
</div>
anna = User("Anna")
Приклад:

 }
Приклад ідеї:
Приклад:

 }

'''Class''' — це шаблон для створення об’єктів, який описує їхній стан, поведінку, правила й взаємодію з іншими частинами системи.; '''Практична роль:''' у Java майже весь application code організовується навколо classes.; У класі зазвичай визначаються інформаційні дані забезпечується через '''Class''' або '''клас'''.; '''Controller class''' часто застосовують, коли потрібно в web frameworks для обробки HTTP-запитів.; Їй істотно, що є собою метод `speak`.; Поганий ООП-код має змогу бути таким самим хаотичним, як і поганий процедурний код.;<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
<syntaxhighlight lang="typescript">
 doStuff() {
 return this.items.length;
== Class у JavaScript ==
<syntaxhighlight lang="cpp">

Class і Record/Data Class

Класи можуть створювати проблеми.;</syntaxhighlight>

}

public class User

JavaScript має class syntax, але під капотом використовує prototype-based inheritance.; process() {

throw new Error("Only draft orders can be paid");
this.status = "paid";

Access modifiers визначають, хто має змогу бачити або змінювати members класу.; {| class="wikitable"

Entity Class

// does many unrelated things
  • читати значення;
  • змінювати значення;
  • виконувати validation;
  • обчислювати значення;
  • приховувати внутрішнє поле.; }

}

}

static double(value: number) {

Клас зазвичай містить: class User {

} Практична роль: polymorphism надає можливість писати код, який функціонує з поведінкою, а не з конкретною реалізацією.; throw new Error("Name is required"); </syntaxhighlight>

class MathUtils {

Приклади:

  • inheritance;
  • composition;
  • aggregation;
  • associations;
  • interfaces;
  • dependencies;
  • visibility;
  • multiplicity.;</syntaxhighlight>

Приклад: Helper Service

}

oleh = User("Oleh")

Корисно, коли потрібно описати обмежений набір варіантів:

id: string;
return "Hello, " + name;

Abstract class — клас, який не призначений для створення об’єктів напряму, а задає спільну основу для subclasses.; constructor(

</div>
<syntaxhighlight lang="typescript">

'''Перевага:''' клас надає можливість зібрати повязані інформаційні дані й дії разом, щоб код був організованішим і ближчим до реальної моделі задачі.; Поняття

'''істотно:''' mutable state не є собою злом, але його потрібно контролювати через methods і invariants.; class Car {
}
}

Приклад:

 }

</div>

'''Практична роль:''' TypeScript class надає можливість поєднати JavaScript runtime-модель із compile-time перевіркою типів.; У такому випадку краще названий method, як ілюстрація `changeEmail`.;== Class у C++ ==
 private brakes: Brakes
Класи й функції  різні способи організації логіки.; async welcomeUser(userId: string) {

 System.out.println("Running");
 error(message: string): void;
{| class="wikitable"

== Generic Class ==

застосовується для:
}
<div style="background:#f0eaff; border-left:6px solid #8e44ad; padding:12px; margin:12px 0;">

<div style="background:#fdecea; border-left:6px solid #e74c3c; padding:12px; margin:12px 0;">

class Animal:

{

'''істотно:''' різниця між class і struct залежить від мови.; * приймати request;
* викликати service;
* повертати response;
* робити validation;
* обробляти errors;
* керувати routing у частині frameworks.;== Multiple Inheritance ==
== Method ==
Приклад:

'''Практична роль:''' dependency injection надає можливість класу не створювати всі залежності самому, а отримувати їх як готові інструменти.; Приклад:

Чи має клас валідний стан після constructor?; error(message: string) {
 private id: string,

 }

 constructor(
</div>
Приклад спрощено:

}
Можливі ризики:
</div>

'''Практична роль:''' base class задає спільну поведінку, а derived class уточнює або розширює її.;<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

Приклади entities:

== Class і Domain Model ==

Краще:

constructor(public readonly value: string) {

InvoiceCalculator

System.out.println("Sound");

Methods описують поведінку:

}

переважні аспекти:

UserService

  • SQL;
  • ORM;
  • database driver;
  • cache;
  • mapping rows to objects;
  • persistence details.; Class diagram має змогу показувати:
self.value = 0
this.name = name;
'''Небезпека:''' найчастіша помилка  думати, що ООП означає все має бути класом.;<syntaxhighlight lang="typescript">
У C++ class схожий на struct, але за замовчуванням members у class є собою private.; def greet(self):
'''Цікавий момент:''' сильний domain class не без ускладнень має status, а знає, коли цей status можна змінити.; '''Dependency injection'''  передача залежностей класу ззовні, часто через constructor.;</div>

Class і Function

Приклад TypeScript:
Java активно використовує:

 self.balance += amount

 "Hello, #{@name}"

<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">

'''Практична роль:''' data class зменшує boilerplate для простих обєктів даних.; '''Практична роль:''' fields відповідають на питання: Що цей обєкт знає або зберігає?

 return a + b;
 def total_users(cls):
<div style="background:#fef2f2; border-left:6px solid #ef4444; padding:12px; margin:12px 0;">
== Static Members ==
Приклад:

<div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">

* instance variables;
* methods;
* modules;
* mixins;
* inheritance;
* metaprogramming;
* open classes.; Зовнішній код не має змогу напряму змінити `balance`, а має використовувати метод `deposit`.; * У C++ class має змогу керувати ресурсами напряму через RAII.; }
domain(): string {

class User {

'''Практична роль:''' repository class надає можливість бізнес-логіці не знати деталей database access.;
  • side effects;
  • складніше debug;
  • проблеми concurrency;
  • неочікувані зміни state.; Приклад:
Практична роль: instance method відповідає за поведінку об’єкта, static або class method — за поведінку, пов’язану з класом загалом.;
 def deposit(self, amount):
<syntaxhighlight lang="typescript">
== Цікавий факт ==

Добрі назви:
 async findById(id: string): Promise<User | null> {
<div style="background:#fef2f2; border-left:6px solid #ef4444; padding:12px; margin:12px 0;">

'''Проста різниця:''' interface  це обіцянка, class  це виконання цієї обіцянки.; this.items.push(item);

'''Проста різниця:''' module  це папка або розділ знань, class  це модель конкретної сутності.; '''Практична роль:''' encapsulation захищає обєкт від неправильних змін і надає можливість контролювати правила роботи зі станом.; !;</div>

</div>
 get name() {
public name: string

UserRepository

public string Greet()

Приклад:

<syntaxhighlight lang="typescript">

Проблеми:

* base class  базовий клас;
* parent class  батьківський клас;
* superclass  надклас;
* derived class  похідний клас;
* child class  дочірній клас;
* subclass  підклас.;<div style="background:#eafaf1; border-left:6px solid #2ecc71; padding:12px; margin:12px 0;">
 User(std::string name) : name(name) {}
 }
def speak(self):

Джерела

Repository має змогу приховувати: Static members використовують для:

'''Практична роль:''' generic class надає можливість писати reusable code без втрати type safety.; Entity важлива не тільки своїми полями, а й тим, що це той самий обєкт у часі.; Мова
class AddNumbers {
User + TimestampMixin  User має createdAt і updatedAt behavior

</div>

'''Multiple inheritance'''  можливість класу наслідувати кілька parent classes.; JavaScript class syntax зручний для ООП-стилю, але істотно памятати про:

'''Небезпека:''' God class стає центром гравітації хаосу: усе нове комфортно додати туди, поки клас не стає майже нерухомим.;
  • Java;
  • C#;
  • C++;
  • Python;
  • JavaScript;
  • TypeScript;
  • Kotlin;
  • Swift;
  • Ruby;
  • PHP;
  • Scala;
  • Dart;
  • Objective-C;
  • Smalltalk;
  • Groovy.;

переважні аспекти: |- | Inheritance | є собою справжній зв’язок “is-a” | Жорстка ієрархія, fragile base class |- | Composition | Об’єкт складається з частин або поведінок | Потрібно більше явного wiring |}

public readonly currency: string

@dataclass class User {

def increment(self):

Приклад:

Проста аналогія: inheritance каже “Car є собою Vehicle”, composition каже “Car має Engine”.; * У Python клас сам є собою object.; Encapsulation або інкапсуляція — принцип приховування внутрішніх деталей класу й надання контрольованого доступу через methods або properties.; return f"Hello, {self.name}"

async getUser(request, response) {
public String greet() {

Добрий клас:

}

</syntaxhighlight>

@Override
return a + b;
  • Money;
  • EmailAddress;
  • DateRange;
  • Address;
  • Coordinates;
  • Percentage;
  • Color.;
     console.log("Beep");
    <div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
    
    </div>
    
    '''істотно:''' abstract class корисний, коли є собою спільна поведінка.;</div>
    '''істотно:''' надмірне використання static methods має змогу зробити код менш гнучким для testing і dependency injection.; Modifier
    
    '''Class explosion'''  ситуація, коли створюється надто багато дрібних або зайвих classes.; Функція добре підходить, коли:
    
    == Encapsulation ==
    
    '''DTO''' або '''Data Transfer Object'''  клас або структура для передачі даних між шарами або системами.; Назва й межі відповідальності мають бути чіткими.; class User {
    

Class добре підходить, коли:

constructor(public readonly value: string) {
String email;

};

істотно: multiple inheritance — потужний інструмент, але він потребує дисципліни.;
this.name = name;

private:

}

}

Простіше: Погано:

Property

execute(a: number, b: number) {

Приклад: - генерує PDF

}

</syntaxhighlight> {{SEO

У програмуванні ця ідея дуже потужна: розробник має змогу думати не про набір випадкових змінних, а про сутності — `User`, `Order`, `Invoice`, `Product`, `Message`, `GameCharacter`.; Практична роль: instance надає можливість одному класу створювати багато незалежних об’єктів із власним станом.;== Class Method і Instance Method ==

Чи залежності передаються явно?;== Висновок ==

  • `Manager`;
  • `Helper`;
  • `Processor`;
  • `Data`;
  • `Object`;
  • `Common`;
  • `Utils`;
  • `Thing`;
  • `Service2`.;== Field ==
  • API request;
  • API response;
  • validation;
  • serialization;
  • transport між services;
  • form data;
  • command objects.; Single Responsibility Principle або SRP — принцип, за яким клас має мати одну основну причину для зміни.;
    Ризики:
    
    == Inner Class і Nested Class ==
    }
     }
    
    function addNumbers(a: number, b: number) {
    Mixins часто використовують для:
    Поширені помилки:
     move() {
    
    }
    == Mutable Class ==
    '''Практична роль:''' DTO сприяє не змішувати зовнішній формат API з внутрішньою domain model.; * У TypeScript access modifiers частково працюють на compile-time, а JavaScript runtime має власні private fields.; }
     def __init__(self, name):
    
    Рекомендовано:
    '''істотно:''' клас — це інструмент, а не гарантія хорошого дизайну.; }
    
    * потрібна одна проста pure function;
    * немає стану;
    * немає invariants;
    * немає lifecycle;
    * це без ускладнень одноразова трансформація;
    * class буде мати одну маленьку функцію без сенсу;
    * створюється abstraction “на майбутнє”;
    * module з функціями читається простіше.; У різних мовах property має змогу бути без ускладнень field або спеціальним способом доступу до даних через getter/setter.; Суть
    </div>
    == Типові помилки початківців ==
    
    Слово '''class''' у програмуванні означає не “шкільний клас”, а “клас речей” — групу об’єктів із подібними властивостями й поведінкою.; }
    
     this.name = name;
    
    Приклад:
    '''Final class''' — клас, який не можна наслідувати.;<div style="background:#e7f3ff; border-left:6px solid #2b7cff; padding:12px; margin:12px 0;">
     return value * 2;
    
     self.value += 1
    <div style="background:#fff4e5; border-left:6px solid #f39c12; padding:12px; margin:12px 0;">
    
    class Dog {
    
    * utility methods;
    * factory methods;
    * constants;
    * shared counters;
    * configuration у частині сценаріїв;
    * class-level behavior.; * У GitHub-проєктах різними мовами слово `class` має змогу означати дуже різні runtime-моделі.; name: str
    
    '''Getter''' читає значення, '''setter''' змінює значення.;
    

завдяки наявності Найлюдяніший факт: клас користувачі можуть програмісту говорити мовою предметної області: не “рядок у таблиці з полями”, а “користувач системи”, “замовлення” або “рахунок”.; countItems(): number {

Class Design

Inheritance

Inner class у деяких мовах має спеціальний доступ до зовнішнього instance.; * Практики software design, domain modeling, SOLID, design patterns, dependency injection і clean architecture.; class Cat extends Animal {

як ілюстрація:

const numberBox = new Box<number>(123); </syntaxhighlight>

Коли варто створювати Class

private userRepository: UserRepository