Василий Соловей, Солигорск. PHP-разработчик в в «Электронном Солигорске».
«Минусы ООП на примере языка PHP». Development секция. Для разработчиков (начальный и средний уровень).
1. Что есть ООП (легкое повторение уже знакомого)
2. Лучше доверять авторитету мнения, чем мнению авторитета (во всем нужно разбираться основательно, а в ООП тем более)
3. Неизменная скупость в похвалах — верный признак посредственного ума (плюсы ООП)
4. Не все то солнышко, что блестит (основная часть доклада – минусы ООП)
5. Кто владеет информацией, тот владеет ситуацией (пояснение сути доклада:
доклад не принижает и не умоляет достоинств ООП он создан расширить кругозор)
«Начинать никогда не поздно!». Мотивационное выступление. На личном примере, я могу рассказать, что начинать никогда не поздно, и если есть желание – нет повода себе отказывать.
1. Путь в тысячу миль начинается с одного шага (с чего начать)
2. И на верном пути повстречаются распутья (как не сбиться с дороги начав)
3. Кто ты программист? (мой взгляд на программирование)
4. Успех – дитя настойчивости
Solit 2014, Как создать продукт, как запустить стартап?, Граков Алексей
Solit 2014, Functional programming, Соловей Василий
1. Functional programming
Важные аспекты функционального программирования
Начнём с терминов. Википедия определяет функциональное программирование как
“парадигму программирования, в которой процесс вычисления трактуется как вычисление
значений функций в математическом понимании последних”. В данном способе
программирования главным объектом манипуляции являются функции, в то время как в
императивном программировании главным принципом является последовательное
выполнение команд для достижения желаемого результата.
Когда я сказал, что главным объектом манипуляции являются функции, я имел в виду, что с
ними мы можем делать всё, что угодно: передавать как аргументы в другие функции,
определять функции в функциях, использовать функции в качестве возвращаемых значений!
В общем, кругом одни функции.
Теперь давайте подойдём ближе к некоторым особенностями функционального
программирования.
Неизменность
Свойством неизменности обладают значения, которые не могут быть изменены. В PHP и
многих других языках их называют константами.
Рекурсия
Рекурсия - это один из часто используемых приёмов в функциональном программировании.
При императивном подходе, для прокрутки по массивам мы можем воспользоваться циклами
for или foreach, записывая текущее значение во временную переменную. Из-за принципа
“неизменности”, данный подход неприемлем для функционального программирования.
Предположим, что мы хотим получить сумму элементов массива (забудьте о array_sum()).
При функциональном подходе, решение данной задачи будет выглядеть так:
1 <?php
2 function sum($array) {
3 if (empty($array))
4 return 0;
5 else
6 return $array[0] + sum(array_slice($array, 1));
7 }
8
9 $total = sum(array(1, 2, 3)); // 6
Если массив пустой, то сумма элементов будет равна 0. В случае
если в массиве больше элементов, мы применяем рекурсию.
Чистые функции
Если функция никаким образом не меняет значения переменных, которые находятся за её
пределами и не осуществляет действия по вводу/выводу данных в файл, базу данных и т.д.,
то такую функцию можно назвать чистой.
Возвращаемое значение чистых функций будет всегда одинаковым для одного и того же
2. набора входящих параметров. В этом случае, мы можем не переживать за работоспособность
программы в целом, если заменим вызов чистой функции на вычисленное значение. Все
математические функции - это чистые функции, в то время как функции работы с датой и
rand() - нет.
Функции высших порядков
Если чистые функции можно реализовать практически при любом подходе, функции
высшего порядка - это очень характерная отличительная черта функционального
программирования. Особенностью функций высших порядков является то, что они могут
принимать в качестве аргументов и возвращать другие функции. В PHP - это лямбда функции
и замыкания.
Лямбда функции
Лямбда функции (также известные, как анонимные функции) - это ничто иное, как функции
без названия. Работа с подобными функциями осуществляется через переменную, которой
данная функция была присвоена.
Возможность создания подобных функций есть во множестве языков. Вы наверняка уже
писали их в вашем JavaScript коде, когда реализовывали функции обратного действия при
работе с ajax.
1 $("#myButton").click(function () {
2 // do something
3 });
Приведённый фрагмент кода - это ничто иное, как создание анонимной
функции.
В PHP лямбда функции появились в версии 5.3:
1 <?php
2
$square = function ($arg)
{
3
return $arg *
$arg;
4 };
5
6 $value = $square(2); // 4
Когда речь идёт об анонимных функциях, очень важно понимать
область видимости переменных. К примеру, в JavaScript анонимные
функции имеют доступ к переменным за их пределами, а в PHP - нет.
Замыкания
Иногда всё же возникает необходимость иметь доступ к какой-то переменной, которая
находится за пределами анонимной функции, но не является входящим параметром. Для того
чтобы получить доступ к подобным переменным, можно воспользоваться замыканиями,
используя ключевое слово use:
1 <?php
2 $rate = .12;
3
3. 4
$findInterest = function ($value) use ($rate)
{
5
return $value *
$rate;
6 };
7
8 $interest = $findInterest(100);
В этом случае, мы не передаём переменную как входящий параметр
функции, а получаем к ней доступ, используя use.
Каррирование и частичное применение
Функции частичного применения - это функции содержащие другие функции, которые
работают с набором аргументов родителя.
В PHP мы можем создавать подобные функции при помощи замыканий. Ниже вы можете
найти пример вычисления объёма коробки. Все аргументы являются необязательными.
Однако, если передать меньше 3х параметров, то запустится ещё и другая внутренняя
функция.
01 <?php
02
$volume = function ($length = 0, $width = 0, $height = 0) use
(&$volume) {
03 $args = func_get_args();
04 $numArgs = func_num_args();
05
if ($numArgs == 3)
{
06
return $length * $width *
$height;
07 }
08
else if ($numArgs < 3)
{
09 return function() use(&$volume, $args) {
10 $newArgs = array_merge($args, func_get_args());
11 return call_user_func_array($volume, $newArgs);
12 };
13 }
14 else {
15
throw new BadFunctionCallException("Too many
arguments");
16 }
17 };
В первой проверке мы проверяем количество аргументов. Если оно
равно 3, то возвращаем результат. Если изначальное количество
аргументов меньше, вызываем другую функцию, которая пытается найти
решение с заданными данными.
Таким образом, мы можем вычислить размер коробки, передав сначала один аргумент, а
потом и другие.
4. 1 <?php
2 $standardVolume = $volume(10);
3
4 $vol = $standardVolume(5, 5); // 250
Каррирование - это специальный вид функции частичного применения,
когда каждый аргумент может быть принят в отдельную функцию. Что-
то типа f(x,y,z) to f(x)(y)(z). В PHP такой синтаксис невозможен,
но реализовать принцип можно.
Плюсы и минусы
В использовании функционального подхода есть множество плюсов. К примеру, анонимные
функции можно использовать в качестве функций обратного вызова. Как в фрэймворке Slim:
1 <?php
2
$app = new
SlimSlim();
3 $app->get("/home", function () {
4 // show home page
5 });
В данном примере, анонимная функция запустится, когда пользователь
зайдёт по адресу home.
При функциональном подходе нужно писать функции, которые выполняют какую-то свою
узкопрофильную задачу, не затрагивающую какие-то глобальные вещи. Следуя данной
парадигме, ваши программы не будут разбухать.
Однако стоит заметить, что не все приёмы данной парадигмы можно реализовать в PHP. В
качестве примера, можно привести работу с параллельными процессами.
Также не всегда можно определить сложность рекурсивной функции и её эффект на
производительность кода. Иногда стоит отойти от функционального принципа.
Наверное самым большим недостатком функционального подхода является то, что нужно
отказаться от императивного мышления. Если это сделать, то новый подход к
программированию может даже и увлечь.
Итог
Функциональное программирование - это больше, чем просто подход. Это больше способ
мышления, причём вне зависимости от языка.