Почему классы лучше чем функции

от автора

Дисклэймер: мне нужно было объяснить моему сотруднику зачем нужны классы в принципе, а именно в чём их преимущество перед функциями. Я начал фантазировать примеры кода, и написал много комментариев. В итоге я посмотрел на то что получилось и подумал — а не дерзнуть ли в песочницу на Хабре?

Что такое хороший код?

  • Это востребованный код, то есть код который работает в живом проекте
    Это не сильно связанно с темой, но это нужно понимать, так как остальное следует из первого пункта

  • Это код, который работает с минимальным количеством ошибок

  • Это код, который удобно поддерживать и расширять (не важно, будет ли это делать один человек или команда разработчиков)

Классы помогают писать хороший код

Буду рассматривать классы не как необходимый инструмент парадигмы ООП, а как инструмент проектирования системы (и стараться доказать их преимущества перед функциями)

Читаемость

<?php $Article = new Article($articleId); $Article->setMeta('');

Банально читается понятнее чем

<?php  article_set_meta($articleId, '');

Даже без подсветки синтаксиса IDE. А с подсветкой — кратно понятнее.
Да, это одна лишняя строчка кода, но если речь о количестве символов — в масштабах проекта это экономия.
Пример более очевиден с увеличением масштаба

<?php $Article = new Article($articleId); $Article->setMeta('')->addImage('')->markAsHot(); $Article->render();

VS

<?php article_set_meta($articleId, ''); article_add_image($articleId, ''); article_mark_as_hot($articleId); article_render($articleId);

Организация кода

Структура с нэймспэйсами и классами визуально понятнее

<?php /Article/Article::create(); /Article/Gallery/Gallery::create(); /* VS */ article_create(); article_gallery_create();

При соблюдении хоть каких-то стандартов код с классами сразу рисует в голове структуру проекта, просто мозг так работает.
Да, любая IDE по клику на метод или функцию найдёт её, но в случае с функциями мозгу не очевидна структура, особенно в большом проекте где 10-ки классов и методов (или сотни функций)

В командной разработке очень удобно отдавать разные Классы/Нэймспэйсы, можно сказать, модули, разным исполнителям.

Ассоциация с реальными вещами в жизни

Когда мы мыслим в рамках классов — нам проще строить сложные структуры, потому что мозг ассоциирует классы и методы с реальными (или абстрактными) понятиями

<?php $User = new User(); //Посетитель, человек $Article = new Article($id); // Статья на сайте, читаемый на мониторе текст $Article->readBy($User); // Статья прочитана человеком   $user = get_from_session(); // Что-то про сессии $article = get_article_by_id($id); // Что-то get и id article_read_by_user($article, $user); // Вроде понятно, но не с первого прочтения

Инкапсуляция, как инструмент скрывания внутреннего функционала

Private и Protected методы нужны не для абстрактных доктрин ООП.

  • Самое банальное — при подстановке кода IDE не будет показывать Private и Protected методы

  • Опять же, про работу мозга — такие методы помогают переключаться с объекта и его внутренних методов на более высокие уровни структуры, когда мы работаем с конкретным объектом — мы можем быстро сфокусироваться на нём, когда на высоком уровне — «забыть» какие-то внутренние методы объекта. С функциями такое просто не получится, потому что они все видны, мозгу сложно держать в памяти их все, также как сложно вспоминать конкретные наборы функций, потому что он перебирает все.

  • А самое главное — без таких методов не получится хорошо спроектировать систему, немного об этом ниже

Шаблоны проектирования

Шаблоны проектирования — набор отточенных годами практик, которые помогают решать сложные задачи, причём таким образом, чтобы было понятно всем (кто знаком с реализованным шаблоном). Без классов(и ООП) они просто не получатся. Конечно, можно сделать их на функциях… Хотя нет, нельзя.

И, немного о архитектуре

Хороший проект — это не просто код, это код, связанный архитектурой. Архитектура задаёт стандарты, помогает разным программистам работать над разными частями, повышает отказоустойчивость системы. Во многом это делается благодаря уровням.

Самый высокий уровень

<?php $Client = new Client($clientId); $Product = new Product($productId); $Invoice = InvoiceBuilder::create($Client); $Invoice->addProduct($Product, $amount, $sellPrice); $Invoice->checkout();

На этом уровне мы не обязаны знать что там под капотом. Мы пишем понятную человеческими словами логику. Нам очевидно что мы выписали счёт клиенту. По этому и классы: чисто визуальнее они понятнее чем функции, вот есть счёт, мы что-то в него добавили, и выписали его.

Средний уровень

<?php class Invoice { public function addProduct(Product $Product, int $amount, int $sellPrice) { // Добавим товар в счёт $this->products[] = [ 'product' => $Product->id, 'amount' => $amount, 'sellPrice' => $sellPrice, ];  // Запомним выбор клиента, если он не оформит покупку - будем ему спамить этот товар $EvilTracker = new EvilTracker($this->Client); $EvilTracker->track($Product->id);  // Создадим запись для отдела аналитики по добавленному товару ProductAnalytics::log($Product->id, $amount, $sellPrice, 'added-to-basket'); } }

Смысл его в том что на этом уровне мы можем менять поведение системы, не затрагивая верхний уровень, добавить какие-то действия, убрать, и тд. Здесь классы нужны чтобы

  • Реализовывать инкапсуляцию, делать код «модульным» и прятать методы-функции от других классов-модулей синтаксис классов и нэймспэйсов для этого просто удобен.

  • Реализовывать наследование, это очень хорошая штука для разработки и проектирования.

  • Реализовывать шаблоны проектирования.

При хорошей архитектуре мы меняем EvilTracker() на SpareTracker() и всё работает.

Низкий уровень

<?php class { public function someLowLevelLogic(bool $boolSomething):array { $someArray = mysql::get_something(); if ($boolSomething) { $someArray = array_map(function ($element) { return [ 'id' => $element['id'], 'title' => $element['title'] . ' ' . $element['bankTitle'], ]; }, $someArray); }       returm $someArray; } }

Разделение на уровни и модули (под модулями я имею ввиду /Разные/Нэймспэйсы и наборы классов) помогает делать проекты, которые удобно развивать как в одиночку, так и командами. Лишние пару строк на старте разработки нового функционала помогает экономить часы доработки.

P.S. Получилось немного сумбурно, я пытался от простого к сложному обосновать пользу понимания и использования классов, даже без каких-то лютых наследований и трейтов.

Прошу судить строго, так как это помогает двигаться вперёд.


ссылка на оригинал статьи https://habr.com/ru/articles/742294/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *