Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
tristamoff
7 лет назад

Как сделать код красивым и удобночитаемым. Процедуры, функции и классы в PHP.

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


Картинка с сайта www.jclassified.in

Вначале немного теории. Один и тот же код можно писать разными способами. Код может быть процедурным, функциональным и объектно-ориентированным.

Процедурный подход

Процедурный подход самый простой. Под ним подразумевается скрипт, в котором сплошняком написан команды и вызваны элементарные php функции.
Например:

<?php
$a = 12;
$b = 10;
$c = 4;
$d = $a % $b;
$e = $c + $d;
echo round($e);
?>

Такой подход уместен, если у вас очень маленький код или он выполняет строго одну задачу(например генерирует картинку), как говорится "ни шаг вправо, ни шаг влево".

Функциональный подход

В функциональном подходе ваш код разделён на части и каждая из них помещена в свою функцию. Это позволит избежать дублирования кода, придаст коду лаконичность и его будет проще читать.
Так-же у каждой функции будет своя собственная область видимости переменных. То есть переменные, "живущие внутри неё" никогда не просочатся наружу и переменные, используемые вне функции так-же не попадут в саму функцию.
Определяя функцию вы сами можете указать какие переменные должны попасть в функцию и что она должна вернуть, то есть вы строго контролируете этот процесс.

Исключения составляют суперглобальные переменные, такие как $_SERVER, $_REQUEST, $_GET, $_POST - они доступны всегда и везде.

Перепишем процедуру на функции:

<?php
function getRemainder($a, $b) {
  $result = $a % $b;
  return $result;
}
function getSum($a, $b) {
  $result = $a + $b;
  return $result;
}
$a = 12;
$b = 10;
$c = 4;
$d = getRemainder($a, $b);
$e = getSum($c, $d);
echo round($e);
?>

Теперь вычисление остатка от деления $a на $b и нахождение суммы от $c и $d завёрнуто в функции getRemainder и getSum.
Функции могут быть определены как до их вызова, так и после. Наверняка вы обратили внимание, что в функции getSum "используются переменные" $a и $b, хотя складываем мы $c и $d.
Это как раз и есть область видимости переменных внутри функции и они не имеют ничего общего с числовыми переменными $a и $b, определёнными вне функции. Мы могли назвать их как угодно.
Оператор return в конце функции возвращает работы функции. То есть переменная $result возвращается наружу и её значение присваивается переменной $d или $e.
Если просто вызвать функцию, не присваивая никакой переменной её возвращаемого значения - то функция просто "отправит в космос" возвращаемое ей значение.
Объясню на примере:

<?php
function getValue() {
  $string = 'String';
  return $string;
}

$a = getValue();
echo $a;//выведет String
echo $string;//ничего не выведет, так как переменная $string существует только внутри функции getValue

//А если просто вызвать функцию
getValue();
echo $string;// так же ничего не выведет, так как переменная $string существует только внутри функции getValue
//получается, что функция getValue "отработала вхолостую", так как никто не принял её возвращаемого значения.
?>

Если нужно провести какую-то типовую операцию много раз(используя разные входные данные) - то её обязательно надо поместить в функцию и вызывать сколько угодно раз.

Объектно-ориентированный подход

И третий подход - объектно-ориентированный. Сокращённо ООП(объектно-ориентированное программирование).
Он так называется в связи с тем, что он представляет из себя произвольное количество объектов с определенными наборами свойств и действий, называемых методами.
В ООП так-же есть такие вещи, как наследование, полиморфизм, абстракция, интерфейсы, конструкторы, деструкторы и многое другое. Это огромная тема и раскрывать её в рамках этой статьи я не буду.
Я покажу лишь простейший пример использования класса.

<?php
class Calc {
  //объявление свойств(переменных) класса
  public $a;
  public $b;
  public $c;
  private $d;
  private $e;

  //метод для определения остатка от деления
  private function getRemainder() {
    $this->d = $this->a % $this->b;
  }

  //метод найдёт сумму
  private function getSum() {
    $this->e = $this->c + $this->d;
  }

  //метод вернёт результат
  public function getResult() {
    self::getRemainder();
    self::getSum();
    return round($this->e);
  }
}

//создание объекта или экземпляра класса
$calc = new Calc();

//задание свойств класса
$calc->a = 12;
$calc->b = 10;
$calc->c = 4;

//вызов метода класса
$e = $calc->getResult();

//вывод на экран результата
echo $e;
?>

При объявлении свойств я использовал ключевые слова public и private.
public - это значит общедоступный и к этому свойству или методу можно обратиться в любом контексте.
private - к таким свойствам и методам можно получить доступ только внутри класса, в котором они определены.
Так же свойство или метод можно определить как protected. Это означает, что доступ к методу или свойству можно получить из текущего класса или из класса, который наследует свойства и методы текущего класса.
Ключевое слово self ссылается на текущий класс и через него можно обратиться к методам текущего класса.
Переменная $this используется для обращения к переменной или методу в контексте класса.
Вот вкратце и всё, можете проверить, все 3 способа будут выдавать одинаковый результат.

Теперь традиционно ставим задачу и её примере рассматриваем решения, так сказать обкатаем теорию.

Имеем 5 видов фруктов и у каждого указана стоимость(за кг).
По условиям задачи нужно посчитать сколько будет стоить 5кг, 12кг, 14кг, 16кг, 22кг, 135кг, 150кг, 200кг, 254кг, 300кг и 400кг каждого фрукта.

Что такое массивы и как с ними работать я уже рассказывал ранее.

<?php
//исходные данные
$fruits = array();
$fruits[] = array(
  'name' => 'Бананы',
  'price' => 65,
);
$fruits[] = array(
  'name' => 'Ананасы',
  'price' => 90,
);
$fruits[] = array(
  'name' => 'Яблоки',
  'price' => 50,
);
$fruits[] = array(
  'name' => 'Груши',
  'price' => 80,
);
$fruits[] = array(
  'name' => 'Кокосы',
  'price' => 130,
);
?>

Для наглядности попробуем решить её процедурно.

<?php
foreach ($fruits as $fruit) {
  $price_5 = $fruit['price'] * 5;
  $price_12 = $fruit['price'] * 12;
  $price_14 = $fruit['price'] * 14;
  $price_16 = $fruit['price'] * 16;
  $price_22 = $fruit['price'] * 22;
  $price_135 = $fruit['price'] * 135;
  $price_150 = $fruit['price'] * 150;
  $price_200 = $fruit['price'] * 200;
  $price_254 = $fruit['price'] * 254;
  $price_300 = $fruit['price'] * 300;
  $price_400 = $fruit['price'] * 400;

  echo $fruit['name'] . ' 5кг стоят ' . $price_5 . 'руб.<br />';
  echo $fruit['name'] . ' 12кг стоят ' . $price_12 . 'руб.<br />';
  echo $fruit['name'] . ' 14кг стоят ' . $price_14 . 'руб.<br />';
  echo $fruit['name'] . ' 16кг стоят ' . $price_16 . 'руб.<br />';
  echo $fruit['name'] . ' 22кг стоят ' . $price_22 . 'руб.<br />';
  echo $fruit['name'] . ' 135кг стоят ' . $price_135 . 'руб.<br />';
  echo $fruit['name'] . ' 150кг стоят ' . $price_150 . 'руб.<br />';
  echo $fruit['name'] . ' 200кг стоят ' . $price_200 . 'руб.<br />';
  echo $fruit['name'] . ' 254кг стоят ' . $price_254 . 'руб.<br />';
  echo $fruit['name'] . ' 300кг стоят ' . $price_300 . 'руб.<br />';
  echo $fruit['name'] . ' 400кг стоят ' . $price_400 . 'руб.<br />';
}
?>

Выглядит это громоздко и некрасиво. А если надо будет посчитать не 11 значений, а 500? И готов поспорить, что при копипасте вы точно не всё поправите и будете получать неверные данные.
Исходник на pastebin http://pastebin.com/ZP91uX8R

Теперь пробуем функционально.

<?php
//вернёт стоимость
function getPrice($price, $weight) {
  $result_price = $price * $weight;
  return $result_price;
}
//вернёт все веса
function getWeights() {
  return array(5, 12, 14, 16, 22, 135, 150, 200, 254, 300, 400);
}

//получаем веса в переменную
$weights = getWeights();
//перебираем все фрукты
foreach ($fruits as $fruit) {
  //перебираем все веса для каждого фрукта
  foreach ($weights as $weight) {
    echo $fruit['name'] . ' ' . $weight . 'кг стоят ' . getPrice($fruit['price'], $weight) . 'руб.<br />';
  }
}
?>

Код вышел гораздо более читабельным. Веса указаны в функции getWeights и простым добавлением их туда посчитать сколько бы стоил другой вес каждых фруктов.
Я перебрал все фрукты и при каждом переборе перебирал все веса. Можно было сделать и наоборот.
Исходник на pastebin http://pastebin.com/07QTBihX

И наконец реализация на ООП.

<?php
class Fruiting {
  public $fruits;
  public $weights;

  public function setData($fruits, $weights) {
    $this->fruits = $fruits;
    $this->weights = $weights;
  }

  private function getPrice($price, $weight) {
    $result_price = $price * $weight;
    return $result_price;
  }

  public function getResult() {
    //перебираем все фрукты
    foreach ($this->fruits as $fruit) {
      //перебираем все веса для каждого фрукта
      foreach ($this->weights as $weight) {
        echo $fruit['name'] . ' ' . $weight . 'кг стоят ' . self::getPrice($fruit['price'], $weight) . 'руб.<br />';
      }
    }
  }
}

$fruiting = new Fruiting();
$fruiting->setData($fruits, array(5, 12, 14, 16, 22, 135, 150, 200, 254, 300, 400));
$fruiting->getResult();
?>

Исходник на pastebin http://pastebin.com/2dBEQFtK

Как видите - код более объёмный. При простых вычислениях можно обойтись и функциональным подходом, но все действительно большие и сложные проекты написаны с использованием ООП.

Подробнее о классах можно почитать в официальной документации

При написании материала старался следовать советам @ontofractal :)

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

9
64.772 GOLOS
На Golos с January 2017
Комментарии (7)
Сортировать по:
Сначала старые