Основные парадигмы программирования

После изучения языка программирования, его синтаксиса, приходит вопрос: какой парадигмы придерживаться? На самом деле нет(в большинстве случаев). Парадигма программирования это архитектура кода, следование одной из них необходимо, чтоб другой разработчик мог быстрее понять как ваша прога работает. Почему-же этот выбор, за частую, сделан за вас? все просто: если это не одноразовый скриптик, а часть какой-то программы, писать его нужно будет в том же архитектурном стиле, что и предыдущий код(нынче программы редко пишутся с нуля). Итак, рассмотрим 3 парадигмы: процедурное, функциональное и объектно-ориентированное программирование.

И еще, для того чтоб было более наглядно – приведу код. Код будет выполнять недавнее мое тестовое задание – вот и само задание:

<?php
/*
Implement Mankind class, which works with Person instances.

General requirements:
- there can only exist a single instance of the class (Martians are not mankind...)
- allow to use the instance as array (use person IDs as array keys) and allow to loop through the instance via foreach

Required operations:
- Load people from the file (see below)
- Get the Person based on ID
- get the percentage of Men in Mankind



Loading people from the file:

Input file is in CSV format. Each person is in separate line. 
Each line contains ID of the person, name, surname, sex (M/F) and birth date in format dd.mm.yyyy.
Attributes are separated by semicolon (;) File is using UTF8 encoding. 
 
Example:
123;Michal;Walker;M;01.11.1962
3457;Pavla;Nowak;F;13.04.1887
*/

Для тех, кто слаб в английский(таких, как я) – простыми словами:

Создать класс Mankind, работающий с классом Person и делающий следующее:

  • читает xml-строку указанного формата и извлекает из нее данные о персонах;
  • уметь выдавать данные по отдельной персоне;
  • рассчитать процентное содержание мужчин среди населения;
  • представить население в виде массива персон.

там еще есть требования к классам, но их опущу(в рамках этой статьи).

Процедурное программирование

Определение с Википедии “Процедурное программирование — программирование на императивном языке, при котором последовательно выполняемые операторы можно собрать в подпрограммы, то есть более крупные целостные единицы кода, с помощью механизмов самого языка”. К определению добавить нечего…

Теперь к сути, а суть такая – это просто текст кода(то, как программирует большинство при изучении ЯП). Функционал моего тестового задания, в процедурном стиле будет выглядеть так:

<?php
$persons = [];
$maleCount = 0;
// открытие файла для чтения
$resource = fopen($filePath, 'r');;
// построчное чтение
while ($line = fgets($resource)) {
    // разбиение строки в массив
    $personData = str_getcsv($line, ';');
    // формирование массива персон
    $persons[$personData[0]] = [
        'id' => $personData[0],
        'name' => $personData[1],
        'second_name' => $personData[2],
        'sex' => $personData[3],
        'birthday' => $personData[4]
    ];
    // считаем мужчинн
    if ($personData[3] === 'M') {
        $maleCount++;
    }
}
// получаем персону
$person123 = $persons[123];
// получим % мужчин
$genderStats = $maleCount * 100 / count($persons);

Функциональный стиль программирования

Все та же википедия(в иных источниках определение такое же): “Функциональное программирование – парадигма программирования, в которой процесс вычисления трактуется как вычисление значений функций в математическом понимании последних”. Для большего понимания, моими словами(ну может так все его объясняют) – программирование, при котором результат работы первой функции является входным параметром следующей.

Код моей программки, переписанный в этом стиле, будет таким

<?php
$persons = [];
$maleCount = 0;
// открытие файла для чтения
$resource = fopen($filePath, 'r');;
// чтение файла в массив строк
$lines = file($filePath);
// обработка каждой строкм ф-ей parser
$persons = array_map('parser', $lines);
// получаем персону
$person123 = getPeron(123, $persons);
// получим % мужчин
$maleStats = getMaleStats($persons);

function parser($line)
{
    $personData = str_getcsv($line, ';');

    return [
        'id' => $personData[0],
        'name' => $personData[1],
        'second_name' => $personData[2],
        'sex' => $personData[3],
        'birthday' => $personData[4]
    ];
}

function getPeron($id, $persons)
{
    $index = array_search(['id' => $id], $persons);

    return $persons[$index] ?? "Персоны с этим  идентификатором[{$index}] не существует";
}

function getMaleStats($persons)
{
    $count = 0;

    foreach ($persons as $person) {
        if ($person['sex'] === 'M') {
            $count++;
        }
    }

    return $count * 100 / count($persons);
}

преимущества такого кода – появляется возможность пере использования кода, что приводит к возможности масштабирования приложения. Недостатком же есть увеличение времени работы скрипта(незначительное)…

Объектно-ориентированное программирование

Традиционно, начнем из определения в Вики: “Объектно-ориентированное программирование (ООП) — методология программирования, основанная на представлении программы в виде совокупности объектов, каждый из которых является экземпляром определённого класса, а классы образуют иерархию наследования”. И добавить нечего… даже своими словами – все предельно четко и ясно(как по мне).

Перепишем код порги в этом стиле. сразу скажу, это ООП “курящего человека”, почему так – объясню в следующих статьях.

<?php
// инициализация объекта
$mankindObj = new Mankind($filePath);
// поллучение массива персон
$persons = $mankindObj->toArray();
// получаем персону
$person123 = $mankindObj->getPersonById(123);
// получим % мужчин
$maleStats = $mankindObj->getMaleStats();

class Person
{
    public int $id;
    public string $name;
    public string $secondName;
    public string $sex;
    public string $birthday;

    public function toArray()
    {
        return get_object_vars($this);
    }
}

class Mankind
{
    public array $mankind;

    public function __construct($path)
    {
        $lines = file($path);

        $this->load($lines);
    }

    public function getPersonById($id)
    {
        return $this->mankind[$id] ?? "Персоны с этим  идентификатором[{$id}] не существует";
    }

    public function getMaleStats()
    {
        $count = 0;

        foreach ($this->mankind as $person) {
            if ($person->sex === 'M') {
                $count++;
            }
        }

        return $count * 100 / count($this->mankind);
    }

    public function toArray()
    {
        $mankind = [];

        foreach ($this->mankind as $person) {
            $mankind[$person->id] = $person->toArray();
        }

        return $mankind;
    }

    protected function load($lines)
    {
        array_map([$this, 'addPerson'], $lines);
    }

    protected function addPerson($line)
    {
        $person = new Person();

        $personData = str_getcsv($line, ';');
        $person->id = (int)$personData[0];
        $person->name = $personData[1];
        $person->secondName = $personData[2];
        $person->sex = $personData[3];
        $person->birthday = $personData[4];

        $this->mankind[(int)$personData[0]] = $person;
    }
}

В этом стиле, несмотря на то, что код максимально длинный, все максимально понятно. Это помимо того что дает возможность масштабировать систему – так еще и делает этот процесс более понятным(при адекватном наименовании классов, методов и т.д.) и быстрым(относительно). Преимущества:

  • Дополнительные пути для уникального нейминга(неймспейс, имя класса, имя метода/свойства);
  • Удобное и, в принципе, возможное масштабирование.

Недостатком здесь выступает еще меньшая скорость работы, чем у функционального кода, однако оно незначительно по сравнению с достоинствами такого подхода.

Имхо

Говорят, эта тема холиварна в кругах программистов, но я, как экстра-интроверт, не в курсе и потому выскажусь. После изучения синтаксиса ЯП, переменных и др. его основ, изучите ООП(до изучения фреймворков, зная объектное вы быстрее поймете любой из них). Без него не выйдет написать ни один крупный проект да и найти работу программистом. К примеру, больше половины тех.собеседований начаты были вопросами об ООП; каждое тех.собеседование содержало о нем вопросы; единственный раз, когда меня не позвали на тех.собеседование — когда я тестовое задание выполнил в процедурно-функциональном стиле(тогда мне показалось что ООП для него излишек).