Абстракция

Абстракция — один из главных способов борьбы со сложностью реального мира.

Стив Макконнелл - Совершенный код

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

Вы могли подумать, что на этот раз мы будем осваивать массивы. И если бы мы не были Хекслетом, то всё было бы именно так. Но у нас немного другие планы на ближайшие курсы. Есть вещи важнее массивов, и с них мы и начнём. К массивам же обратимся позже.

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

Как вы увидите позже, точно так же можно (и зачастую нужно) работать с массивами. К тому моменту, когда мы начнём их использовать, вы уже будете готовы к такому способу работы.

Одна из самых важных тем в программировании — абстракция. Чем больше кодовая база, тем больше абстракций используется, либо создаётся в ней. Значительная часть времени разработчика тратится на моделирование предметной области и реализацию её в коде, а также в её дальнейшей поддержке и развитии. Как правило, этому вопросу совсем не уделяют времени, но именно от умения моделировать зависит качество вашего кода, насколько просто будет работать с ним, понимать и модифицировать его.

Представьте, что вам необходимо автоматизировать работу отдела продаж (создать CRM). С чего вы начнете? А начать стоит с онтологии.

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

Введение

По названию этого курса можно подумать, что мы будем говорить о таких типах данных в php, как массив или объект. Это совсем не так. В этом курсе мы используем php, как язык, на котором пишем код, но сам курс относится в целом к программированию. Мы изучим такое понятие, как абстракция данных. Это общая концепция никак не связана конкретно с php и является важным механизмом абсолютно во всех языках программирования. В отличие от предыдущих курсов мы вообще не введём ни одной новой синтаксической конструкции. В этом и есть наше отличие. Мы учим вас мыслить, писать код и программировать, что сильно отличается от того, что существует сейчас на рынке.

Итак, давайте начнём.

Что такое составные данные?

Составные данные используются в следующих случаях. Когда мы пишем программы, то чаще всего пытаемся моделировать достаточно сложные процессы и явления, протекающие часто в реальной жизни. Для этого мы можем использовать составные вычислительные объекты, которые включают в себя несколько различных частей. Это позволяет лучше моделировать все явления реальной среды, того, с чем мы взаимодействуем. И язык программирования должен предоставлять возможность создавать механизмы для создания так называемых составных данных, т.е. из разных кусков собирать отдельный вычислительный объект.

Зачем это нужно?

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

У нас есть координатная плоскость, и мы можем строить на ней точки. При этом любая точка обладает двумя характеристиками — это её координаты x и y, т.е. абсцисса и ордината. В данном примере я использую то, что уже известно — простые числовые значения, и описываю две точки. Одна из них — x1 / y1, вторая — x2 / y2. После этого, вычисляю точку посередине.

<?php 

$x1 = 3;
$y1 = 5;

$x2 = -2;
$y2 = 10;

// Точка посередине
$x3 = middleX($x1, $x2);
$y3 = middleY($y1, $y2);

Мы считаем, что мы строим отрезок между двумя этими точками и находим точку, которая лежит посередине. То, как это работает, не имеет значения. Главное, что вы можете себе это представить. Мы оперируем понятием точка. При этом понимаем, что она состоит из двух простых типов, т.е. двух чисел. По сути появляется такая вещь, как пара. И в общем-то нам удобно оперировать такими терминами.

Но при написании кода, если у нас не существует понятия составные данные, то, как видите, нам приходится производить вычисления независимо. Т.е. сначала вычислить $х3, после этого нам надо вычислить $y3. Это происходит потому, что мы не оперируем понятием точка. У нас нет такого составного вычислительного объекта. И всё, что мы можем в наших функциях, это принимать простые параметры и возвращать точно такие же простые параметры. Получается, что одно действие технически разбивается на два. Согласитесь, это крайне не удобно. Особенно, когда ваша программа становится достаточно большой и начинает оперировать большим количество сложных объектов.

Точки, кстати говоря — это ещё достаточно простые объекты, которые включают в себя буквально 2 параметра. Представьте, что будет, когда мы начнём использовать более сложные объекты: хотя бы фигуры, например, квадрат. Квадрат включает в себя 4 точки — это уже 8 параметров, потому что в каждой точке 2 параметра. Работать на таком уровне абстракции, используя только примитивные типы и примитивные данные, мы просто бы не смогли. Наше мышление очень сильно бы этому сопротивлялось. Код получался бы очень громоздкий очень неинтуитивный.

В идеале нам бы хотелось работать так, как показано в этой строчке:

// Compound Data
$middlePoint = middle($point1, $point2);

Мы отдаём в функцию две точки ($point1 и $point2), и нам возвращается точка посередине. Как она устроена и что там внутри — это отдельный вопрос. Главное, что мы оперируем этим понятием, как единым целым. Возможность строить составные объекты данных позволяет нам использовать технику, которая называется абстракция данных.

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

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

Абстракция данных приводит нас к такому понятию, как барьеры абстракции, когда мы можем строить многоуровневые слои, позволяющие изолировать разные части и разные уровни системы друг от друга. Об этом будет отдельный урок, где мы подробно поговорим, как работает абстракция данных, и как строятся барьеры абстракции.

Кроме этого в любом языке программирования нужен некий клей, который позволит из простых данных строить более сложные. И как мы увидим в дальнейшем, для этого даже не нужны специальные операции. Строить составные объекты можно используя только возможности функций, что ещё больше стирает разницу между функциями и данными. Это можно было уже заметить, потому что функции определяются точно так же, как данные. Функции являются полноправными данными, так называемыми объектами первого рода. Этому будет посвящён целый отдельный урок.

Графические примитивы

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

Рациональные числа

Кроме этого попробуем построить простую библиотеку для работы с рациональными числами. Это числа, у которых есть числитель и знаменатель. Определение, конечно, не строго математическое, но вы на интуитивном уровне все с ними знакомы. Рациональное число — достаточно простой, но составной объект, который включает в себя пару чисел.

Преимущества Hexlet

  • Осмысление
  • СИКП
  • Не используем существующие структуры данных
  • Функции высшего порядка
  • Неизменяемость (Функциональный стиль)

По опыту предыдущих курсов очень часто у людей возникают вопросы: "А почему именно так?", "Как мне это поможет в практике?" и "Я хочу быстрее начать писать продакшн код во фреймворках". Да, мы не просто учим синтаксису. Мы хотим изменить ваше мышление, хотим сделать его правильным, чтобы у вас развилось критическое мышление, чтобы вы понимали причинно-следственные связи и в первую очередь мыслили не синтаксисом языка, а смыслом того, что вы делаете с точки зрения построения абстракций. Это позволит писать вам модульные программы, которые легко читать, поддерживать, развивать, и они будут выполнять то, что нам нужно. Это наша основная идея, то, что хочет дать и несёт Хекслет. Возможно, вы уже заметили это по каким-то вещам, которые мы рассказываем или делаем.

Наш курс во многом построен на так называемом СИКПе — курсе, который вёлся и ведётся до сих пор в большом количестве университетов мира. Расшифровывается, как структура и интерпретация компьютерных программ. Курс был придуман в Массачусетском технологическом институте (MIT). Это университет номер один в мире IT-технологий, который выпускал и выпускает лучших специалистов в этой области. СИКП — достаточно большой, сложный, но крайне важный курс. По нему выпущена книга, которая уже десятки лет считается книгой номер один среди обучающей литературы по программированию. В любом случае, всем её рекомендуем. При этом здесь мы её активно используем, потому что она дала нам много материала и пищи для размышлений. Книга была выпущена в 1985 году, а сам курс вёлся ещё раньше (в начала 80-х). Но, как вы увидите в дальнейшем, несмотря на то, что меняются технологии, меняются фреймворки, меняется всё вокруг (php меняется особенно сильно), но базовые вещи, также, как во многом и математика, в общем-то не меняется и не поменяется. Не гонитесь за новым модным, изучайте то, на чём всё это базируется.

Курс не использует существующие структуры данных. Я сказал об этом в самом начале. Здесь не будет ничего про массивы, объекты или какие-то другие возможные способы комбинирования данных. Это отвлечёт нас от основной идеи. От понимания сути вопроса. Наши функции в этом курсе приобретут совершенно новый оттенок и заиграют новыми красками. Мы познакомимся с функциями высшего порядка и увидим, что функции — это точно такие же данные, которые можно передавать в другие функции, возвращать из функций и делать с ними совершенные чудеса.

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

Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →