Entity vs Value Object: полный список отличий
Чтобы обозначить разницу между entities и value objects, нам необходимо определить три типа эквивалентности (equality), которые вступают в силу как только мы пытаемся сравнить два объекта друг с другом.
Reference equality (ссылочная эквивалентность) означает, что два объекта равны в случае если они ссылаются на один и тот же объект в куче:
Вот как мы можем проверить ссылочную эквивалентность в C#:
Identifier equality (эквивалентность идентификаторов) подразумевает, что у класса присутствует Id поле. Два объекта такого класса будут равны если они имеют одинаковый идентификатор:

И, наконец, струкрурная эквивалентность означает полную эквивалентность всех полей двух объектов:

Основное отличие между сущностями и объектами-значения лежит в том, как мы сравниваем их экземпляры друг с другом. Концепция эквивалентности идентификаторов относится к сущностям, в то время как структурая эквивалентность — к объектам-значениям. Другими словами, сущности обладают неотъемлемой идентичностью, в то время как объекты-значения — нет.
На практике это означает, что объекты-значения не имеют поля-идентификатора и если два экземпляра одного объекта-значения обладают одинаковым набором атрибутов, мы можем считать их взаимозаменяемыми. В то же время, даже если данные в двух сущностях полностью одинаковы (за исключением Id поля), они не являются одной и той же сущностью.
Вы можете думать об этом в том же ключе, в котором вы думаете о двух людях, носящих одинаковое имя. Мы не считаем их одним и тем же человеком из-за этого. Они оба обладают внутренней (неотъемлимой) идентичностью. В то же время, если у нас есть 1 рубль, нам все равно та же ли это монета, что была у нас вчера. То тех пор пока эта монета является монетой ценностью в 1 рубль, мы не против заменить ее другой, точно такой же. Концепция денег в таком случае является объектом-значением.
Жизненный цикл
Еще одно отличие между двумя понятиями состоит в жизненном цикле их экземпляров. Сущности живут в континууме. Они обладают историей (даже если мы не храним эту историю) того, что с ними случилось и как они менялись в течение жизни.
Объекты-значения, с другой стороны, обладают нулевым жизненным циклом. Мы создаем и уничтожаем их с легкостью. Это следствие, логично вытекающее из того, что они взаимозаменяемы. Если рублевая монета — точно такая же, что и другая рублевая монета, то какая разница? Мы можем просто заменить имеющийся объект другим экземпляром и забыть о нем после этого.
Гайдлан, который следует из этого отличия, заключается в том, что объекты-значения не могут существовать сами по себе, они всегда должны принадлежать одной или нескольким сущностям. Данные, которые представляет из себя объект-значение, имеют значение только в контексте какой-либо сущности. В примере с монетами, приведенном выше, вопрос «Сколько денег?» не имеет смысла, т.к. он не несет в себе достаточного контекста. С другой стороны, вопрос «Сколько денег у Пети?» или «Сколько денег у всех юзеров нашей системы?» полностью валидны.
Другое следствие здесь в том, что мы не храним объекты-значения отдельно. Вместо этого, мы должны инлайнить (присоединять) их к сущностям при сохранении в БД (об этом ниже).
Неизменяемость
Следующее отличие — неизменямость. Объекты-значения должны быть неизменяемы в том смысле, что если нам необходимо изменить такой объект, мы создаем новый экземпляр на основе имеющегося вместо того чтобы изменять существующий. В противовес этому, сущности почти всегда изменяемы.
Обязательная неизменяемость объектов-значений принимается не всеми программистами. Некоторые считают, что этот гайдлайн не такой строгий, как предыдущие и объекты-значения могут быть изменяемыми в некоторых случаях. Я тоже придерживался этого мнения некоторое время назад.
В настоящее время я считаю, что связь между неизменяемостью и возможностью заменить один объект-значение на другой лежит глубже чем я думал. Изменяя экземпляр объекта-значения, мы подразумеваем, что он имеет неравный нулю жизненный цикл. А это предположение, в свою очередь, ведет к заключению о том, что объекты-значения имеют внутреннюю идентичность, что противоречит определию этого понятия.
Это несложное мысленное упражнение делает неизменяемость неотъемлемой частью объектов-значений. Если мы принимаем, что они имеют нулевой жизненный цикл, в том смысле что они являются всего лишь слепком какого-либо состояния и ничем более, то мы должны также принять, что они могут представлять только один вариант этого состояния.
Это приводит нас к следующиему правилу: если вы не можете сделать объект-значение неизменяемым, значит этот класс не является объектом-значением.
Как распознать объект-значение в доменной модели?
Не всегда ясно является ли концепция в доменной модели сущностью или объектом-значением. И к сожалению, не существует объективных атрибутов, по которым мы могли мы судить об этом. Является или нет класс объектом-значением полностью зависит от доменной области, в которой мы работаем: один и тот же предмет можно смоделировать в виде сущности в одном домене и в виде объекта-значения в другом.
В примере выше мы рассматриваем деньги как нечно взаимозаменяемое. Таким образом, это понятие является объектом-значением. В то же самое время, если мы создаем систему для отслеживания всех купюр в стране, нам необходимо рассмативать каждую банкноту отдельно для сбора статистики по ней. В этом случае понятие денег будет являться сущностью.
Не смотря на отсутствие объективных показателей, мы все же можем использовать некоторые приемы для того, чтобы отнести концепт к сущностям или объектам-значениям. Мы уже обсуждали три вида эквивалентности: если мы можем заменить один экземпляр класса другим с теми же свойствами, то это хороший знак того, что перед нами объект-значение.
Более простая версия того же приема заключается в том, чтобы мысленно сравнить класс с целочисленным значением (integer). Вам как разработчику безразлично является ли цифра 5 той же цифрой, которую вы использовали в предыдущем методе. Все пятерки в вашем приложении одинаковы, не зависимо от того, как они были созданы. Это делает тип integer по сути объектом-значением. Теперь, задайте себе вопрос: выглядит ли этот класс как integer? Если ответ да, то это объект-значение.
Как хранить объекты-значения в базе данных?
Предположим, что мы имеем два класса в доменной модели: сущность Person и объект-значение Address:
Как будет выглядить структура БД в этом случае? Решение, которое приходит в голову в такой ситуации — создать отдельные таблицы для обоих классов:

Такой дизайн, не смотря на полную валидность с точки зрения БД, имеет два недостатка. Во-первых, таблица Address содержит идентификатор. Это означает, что нам будет необходимо ввести отдельное поле Id в класс Address чтобы работать с такой таблицей корректно. Это, в свою очередь, означает, что мы добавляем классу некоторую идентичность. А это уже нарушает определение объекта-значения.
Второй недостаток здесь в том, что мы потенциально можем отделить объект-значение от родителькой сущности. Address может жить собственной жизнью, т.к. мы можем удалить Person из БД без удаления соответствующей строки Address. Это будет нарушением другого правила, говорящего о том, что время жизни объектов-значений должно полностью зависеть от времени жизни их родительских сущностей.
Наилучшим решением в данном случае будет «заинлайнить» поля из таблицы Address в таблицу Person:

Это решит обе проблемы: Address не будет иметь собственного идентификатора и его время жизни будет полностью зависеть от времени жизни сущности Person.
Этот дизайн также имеет смысл если вы мысленно замените все поля, относящиеся к Address, единственным integer, как я предложил ранее. Создаете ли вы отдельную таблицу для каждого целочисленного значения в вашей доменной модели? Конечно нет, вы просто включаете его в родительскую таблицу. Те же правила применимы к объектам-значениям. Не создавайте отдельную таблицу для объектов-значений, просто включите их поля в таблицу сущности, к которой они принадлежат.
Предпочитайте объекты-значения сущностям
В вопросе объектов-значений и сущностей важное значение имеет следующее правило: всегда предпочитайте объекты-значения сущностям. Объекты-значения неизменяемы и из-за этого с ними крайне просто работать. В идеале, вы всегда должны стремиться включить большинство бизнес-логики в объекты-значения. Сущности в таких ситуациях будут служить обертками над ними и представлять более высокоуровневую функциональность.
Также, может случиться так, что концепт, который вы изначально видели как сущность, на самом деле является объектом-значением. К примеру, вы могли изначально представить класс Address в вашем коде как сущность. Он может иметь собственный Id и отдельную таблицу в БД. После некоторого размышления вы замечаете, что в вашей предметной области адреса на самом деле не имеют собственной идентичности и могут использоваться взаимозаменяемо. В этом случае, не стесняйтесь рефакторить вашу доменную модель, конвертируйте сущность в объект-значение.
Понятие ER-модели. Понятие сущности (entity). Атрибуты. Виды атрибутов
При проектировании базы данных и разработке программного продукта наиболее важной проблемой есть проблема взаимодействия разработчика с заказчиком. Задача разработчика – наиболее точно воссоздать пожелания заказчика при разработке программного продукта управления базой данных. Основная проблема, которую нужно решить разработчику – правильное построение базы данных, а точнее схемы (структуры) базы данных.
Кроме того, разработчик дополнительно встречается с другими трудностями, к которым можно отнести:
- поиск эффективных алгоритмов;
- подбор надлежащих структур данных;
- отладка и тестирование сложного кода;
- дизайн и удобство интерфейса приложения.
В процессе разработки программного обеспечения, управляющего базой данных, разработчик должен подробно выучить требования заказчика. База данных должна быть разработана таким образом, чтобы она была понятной, наиболее точно отображала решаемую проблему и не содержала избыточности в данных.
Чтобы облегчить процесс разработки (проектирования) базы данных, используются так называемые семантические модели данных. Для разных видов баз данных наиболее известной есть ER-модель данных (Entity-Relationship model).
2. Что такое ER-модель (Entity-relationship model)? Для чего нужно разрабатывать ER-модель?
ER-модель (Entity-relationship model или Entity-relationship diagram) – это семантическая модель данных, которая предназначена для упрощения процесса проектирования базы данных. Из ER-модели могут быть порождены все виды баз данных: реляционные, иерархические, сетевые, объектные. В основе ER-модели лежат понятия «сущность», «связь» и «атрибут».
Для больших баз данных построение ER-модели позволяет избежать ошибок проектирования, которые чрезвычайно сложно исправлять, в особенности, если база данных уже эксплуатируется или на стадии тестирования. Ошибки в разработке структуры базы данных могут привести к переделке кода программного обеспечения управляющего этой базой данных. В результате время, средства и человеческие ресурсы будут использованы неэффективно.
ER-модель – это представление базы данных в виде наглядных графических диаграмм. ER-модель визуализирует процесс, который определяет некоторую предметную область. Диаграмма «сущность»-«связь» – это диаграмма, которая представляет в графическом виде сущности, атрибуты и связи.
ER-модель – это только концептуальный уровень моделирования. ER-модель не содержит деталей реализации. Для той же самой ER-модели детали ее реализации могут отличаться.
3. Что такое сущность в базе данных? Примеры
Сущность в базе данных – это любой объект в базе данных, который можно выделить исходя из сути предметной области для которой разрабатывается эта база данных. Разработчик базы данных должен уметь правильно определять сущности.
Пример 1. В базе данных книжного магазина можно выделить следующие сущности:
- книга;
- поставщик;
- размещение в магазине.
Пример 2. В базе данных учета учебного процесса некоторого учебного заведения можно выделить следующие сущности:
- студенты (ученики);
- преподаватели;
- группы;
- дисциплины, которые изучаются.
4. Какие существуют разновидности типов сущностей? Обозначение типов сущностей в ER-модели
В модели «сущность»-«связь» различают две разновидности типов сущностей:
- слабый тип. Этот тип сущности есть зависимым от сильной сущности;
- сильный тип. Это самостоятельный тип сущности, который ни от кого не зависит.
На рисунке 1 изображены обозначения слабого и сильного типа сущности в ER-модели.
Рис. 1. Обозначение сильного и слабого типов сущности
5. Для чего предназначены атрибуты? Виды атрибутов. Обозначение атрибутов на ER-модели
Каждый тип сущности имеет определенный набор атрибутов. Атрибуты предназначены для описания конкретной сущности.
Различают следующие виды атрибутов:
- простые атрибуты. Это атрибуты, которые могут быть частью составных атрибутов. Эти атрибуты состоят из одного компонента. Например, к простым атрибутам можно отнести: код книги в библиотеке или курс обучения студента в учебном заведении;
- составные атрибуты. Это атрибуты, которые состоят из нескольких простых атрибутов. Например, адрес проживания может содержать название страны, населенного пункта, улицы, номера дома;
- однозначные атрибуты. Это атрибуты, которые содержат только одно единственное значение для некоторой сущности. Например, атрибут «Номер зачетной книги» для типа сущности «Студент» есть однозначным, так как студент может иметь только один номер зачетной книги (одно значение);
- многозначные атрибуты. Это атрибуты, которые могут содержать несколько значений. Например, многозначный атрибут «Номер телефона» для сущности «Студент», так как студент может иметь несколько номеров телефона (домашний, мобильный и т.д.);
- произвольные атрибуты. Это атрибуты, значение которых формируется на основе значений других атрибутов. Например, текущий курс обучения студента можно вычислить на основе разности текущего года обучения и года поступления студента в учебное заведение (если студент не имел проблем с учебой и хорошо учил дисциплину «Организация баз данных и знаний»).
На ER-диаграмме атрибуты обозначаются так, как изображено на рисунке 2. Как видно из рисунка, любой атрибут обозначается в виде эллипса с названием внутри эллипса. Если атрибут есть первичным ключом, то его название подчеркивают.

Рисунок 2. Представление атрибутов на диаграммах ER-модели
6. Как типы сущностей и атрибуты ER-модели реализуются в реальных базах данных и управляемых ими программах?
При разработке программ управления базами данных, типы сущностей и их атрибуты можно представлять по разному при этом придерживаясь нескольких подходов:
- выбрать в качестве источника данных известную технологию (например Microsoft SQL Server, Oracle Database, Microsoft Access, Microsoft ODBC Data Source и т.п.), которая уже исследована, протестирована, стандартизирована и имеет огромный набор средств управления базой данных;
- разработать собственный формат базы данных и реализовать методы ее обработки, а взаимодействие с известными источниками данных реализовать в виде специальных команд наподобие Импорт/Экспорт. В этом случае придется собственноручно программировать всю рутинную работу по ведению и обеспечению надежной работы базы данных;
- реализовать объединение двух вышеприведенных подходов. Современные средства разработки программного обеспечения имеют мощный набор библиотек для обработки сложных наборов и визуализации данных в них (коллекции, массивы, компоненты визуализации и т.п.).
Если база данных реализуется в известных реляционных СУБД (например Microsoft Access, Microsoft SQL Server и т.п.), то типы сущностей представляются таблицами. Атрибуты из ER-модели соответствуют полям таблицы. Одна запись в таблице базы данных представляет один экземпляр сущности.
Каждый вид атрибута реализуется следующим образом:
- простой атрибут или однозначный атрибут может быть представлен доступным набором базовых типов, которые есть в любом языке программирования. Например, целочисленные атрибуты представляются типом int , integer , uint и т.д.; атрибуты содержащие дробную часть могут быть представлены типом float , double ; строчные атрибуты типом string и т.д.;
- составной атрибут – это объект, который включает в себя несколько вложенных простых атрибутов. Например, в СУБД Microsoft Access составной атрибут некоторой таблицы может формироваться на основе набора простых типов (полей). В языках программирования объединение полей реализуется структурами или классами;
- многозначный атрибут может быть реализован массивом или коллекцией простых или составных атрибутов;
- произвольный атрибут реализуется дополнительным полем, которое вычисляется при обращении к таблице. Такое поле называется вычислительным полем (calculated field) и формируется на основе других полей таблицы;
- атрибут, который есть первичным ключом может быть целочисленным, строчным или иного порядкового типа. В этом случае, значение каждой ячейки таблицы, которая соответствует первичному ключу, есть уникальным. Наиболее часто, в качестве первичного ключа выступает целый тип ( int , integer ).
Если база данных реализована в уникальном формате, то типы сущностей удобнее всего представлять в виде классов или структур. Атрибуты сущности реализуются в виде полей (внутренних данных) класса. Методы класса реализуют необходимую обработку полей класса (атрибутов). Взаимодействие (связь) между классами реализуется с помощью специально разработанных интерфейсов с использованием известных шаблонов проектирования.
7. Пример фрагмента ER-модели для типа сущности «Студент»
Приведенный пример демонстрирует фрагмент ER-модели для типа сущности «Студент».

Рисунок 3. Фрагмент ER-модели для типа сущности «Студент»
На вышеприведенном рисунке объявляются следующие атрибуты, которые в СУБД (программе) могут иметь следующие типы:
Основные понятия в объектно-ориентированном программировании ИЛИ
моя шпаргалка по ООП
Я обожаю эту книгу, потому что она написана простым языком со знанием дела и такой любовью к программированию, что вы ее с упоением прочтете в метро. Вы будете с нетерпением ждать того момента, когда вы сможете усесться с книжечкой в поезде и взахлеб читать и пропускать свои станции.
А теперь для ленивых и для себя любимой я составила краткий конспект-шпаргалку по этой книги.
ШПАРГАЛКА ПО ООП
Объектно-ориентированное программирование или ООП — это способ создания программных компонентов, базирующихся на объектах.
Основные принципы ООП
- абстрагирование
- инкапсуляция
- модульность
- иерархия
- типизация
- параллелизм
- устойчивость
Абстрагирование — это процесс выделения наиболее существенных характеристик некоторого объекта, отличающих его от всех других видов объектов, важных с точки зрения дальнейшего рассмотрения и анализа, и игнорирование менее важных или незначительных деталей.
Объекты и классы — основные абстракции предметной области.
Инкапсуляция — это процесс отделения друг от друга элементов объекта, определяющих его устройство и поведение; инкапсуляция служит для того, чтобы изолировать контрактные обязательства абстракции от их реализации.
Модульность — это свойство системы, связанное с возможностью ее декомпозиции на ряд внутренне сильно сцепленных, но слабо связанных между собой подсистем (частей).
Модульность снижает сложность системы, позволяя выполнять независимую разработку ее отдельных частей.
Иерархия — это упорядочение абстракций, расположение их по уровням.
Типизация — способ защититься от использования объектов одного класса вместо другого, или, по крайней мере, управлять таким использованием.
Тип — точная характеристика некоторой совокупности однородных объектов, включающая структуру и поведение.
При строгой типизации (например, в языке Оберон) запрещается использование объектов неверного типа, требуется явное преобразование к нужному типу. При менее строгой типизации такого рода запреты ослаблены. В частности, допускается полиморфизм — многозначность имен. Одно из проявлений полиморфизма, использование объект подтипа (наследника) в роли объекта супертипа (предка).
Параллелизм — это свойство, отличающее активные объекты от пассивных.
Параллелизм — наличие в системе нескольких потоков управления одновременно. Объект может быть активен, т. е. может порождать отдельный поток управления. Различные объекты могут быть активны одновременно.
Сохраняемость (устойчивость) — способность объекта существовать во времени, переживая породивший его процесс, и (или) в пространстве, перемещаясь из своего первоначального адресного пространства.
Устойчивость — способность объекта сохранять свое существование во времени и/или пространстве (адресном, в частности при перемещении между узлами вычислительной системы). В частности, устойчивость объектов может быть обеспечена за счет их хранения в базе данных.
Основные понятия объектно-ориентированного подхода или элементы объектной модели
“ Объект в ООП — это сущность, способная сохранять свое состояние (информацию) и обеспечивающая набор операций (поведение) для проверки и изменения этого состояния. ”
Объект — осязаемая сущность (tangible entity) — предмет или явление (процесс), имеющие четко выраженные границы, индивидуальность и поведение.
Любой объект обладает состоянием, поведением и индивидуальностью.
Состояние объекта определяется значениями его свойств (атрибутов) и связями с другими объектами, оно может меняться со временем.
Поведение определяет действия объекта и его реакцию на запросы от других объектов. Поведение представляется с помощью набора сообщений, воспринимаемых объектом (операций, которые может выполнять объект).
Индивидуальность — это свойства объекта, отличающие его от всех других объектов.
Структура и поведение схожих объектов определяют общий для них класс.
Объект в JavaScript создаётся с помощью функции Object.create. Эта функция из родителя и опционального набора свойств создаёт новую сущность. Пока что мы не будем беспокоиться о параметрах.
Прототип — это объект-образец, по образу и подобию которого создаются другие объекты. Объекты-копии могут сохранять связь с родительским объектом, автоматически наследуя изменения в прототипе; эта особенность определяется в рамках конкретного языка.
Класс — это множество объектов, связанных общностью свойств, поведения, связей и семантики. Любой объект является экземпляром класса. Определение классов и объектов — одна из самых сложных задач объектно-ориентированного проектирования.
Класс (class) — это группа данных и методов(функций) для работы с этими данными. Это шаблон. Объекты с одинаковыми свойствами, то есть с одинаковыми наборами переменных состояния и методов, образуют класс.
Конструктор класса — специальный блок инструкций, вызываемый при создании объекта.
var s = new String();
Деструктор — специальный метод класса, служащий для деинициализации объекта (например освобождения памяти).
Атрибут — поименованное свойство класса, определяющее диапазон допустимых значений, которые могут принимать экземпляры данного свойства. Атрибуты могут быть скрыты от других классов, это определяет видимость атрибута: рublic (общий, открытый); private (закрытый, секретный); protected (защищенный).
Требуемое поведение системы реализуется через взаимодействие объектов. Взаимодействие объектов обеспечивается механизмом пересылки сообщений. Определенное воздействие одного объекта на другой с целью вызвать соответствующую реакцию называется операцией или посылкой сообщения. Сообщение может быть послано только вдоль соединения между объектами. В терминах программирования соединение между объектами существует, если один объект имеет ссылку на другой.
Дескриптор — это атрибут объекта со связанным поведением (англ. binding behavior), т.е. такой, чьё поведение при доступе переопределяется методами протокола дескриптора.
Операция — это услуга, которую можно запросить у любого объекта данного класса. Операции реализуют поведение экземпляров класса. Описание операции включает четыре части: имя; список параметров; тип возвращаемого значения; видимость.
Реализация операции называется методом.
Метод — это функция или процедура, принадлежащая какому-то классу или объекту.
Различают простые методы и статические методы (методы класса):
- простые методы имеют доступ к данным объекта (конкретного экземпляра данного класса),
- статические методы не имеют доступа к данным объекта и для их использования не нужно создавать экземпляры (данного класса).
Методы предоставляют интерфейс, при помощи которого осуществляется доступ к данным объекта некоторого класса, тем самым, обеспечивая инкапсуляцию данных.
В зависимости от того, какой уровень доступа предоставляет тот или иной метод, выделяют:
- открытый (public) интерфейс — общий интерфейс для всех пользователей данного класса;
- защищённый (protected) интерфейс — внутренний интерфейс для всех наследников данного класса;
- закрытый (private) интерфейс — интерфейс, доступный только изнутри данного класса.
Такое разделение интерфейсов позволяет сохранять неизменным открытый интерфейс, но изменять внутреннюю реализацию.
Полиморфизм — способность скрывать множество различных реализаций под единственным общим именем или интерфейсом.
Понятие полиморфизма может быть интерпретировано, как способность объекта принадлежать более чем одному типу.
Интерфейс — это совокупность операций, определяющих набор услуг класса или компонента. Интерфейс не определяет внутреннюю структуру, все его операции открыты.
Компонент — это относительно независимая и замещаемая часть системы, выполняющая четко определенную функцию в контексте заданной архитектуры.
Компонент представляет собой физическую реализацию проектной абстракции и может быть: компонентом исходного кода (cpp-шник); компонентом времени выполнения (dll, ActiveX и т. п.); исполняемый компонентом (exe-шник). Компонент обеспечивает физическую реализацию набора интерфейсов. Компонентная разработка (component-based development) представляет собой создание программных систем, состоящих из компонентов (не путать с объектно-ориентированным программированием (ООП).
Компонентная разработка — технология, позволяющая объединять объектные компоненты в систему.
Пакет — это общий механизм для организации элементов в группы. Это элемент модели, который может включать другие элементы. Каждый элемент модели может входить только в один пакет.
-средством организации модели в процессе разработки, повышения ее управляемости и читаемости;
-единицей управления конфигурацией.
Подсистема — это комбинация пакета (может включать другие элементы модели) и класса (обладает поведением). Подсистема реализует один или более интерфейсов, определяющих ее поведение. Она используется для представления компонента в процессе проектирования.
Name already in use
php / 23_Object-class_this-inheritanse_incapsulation.md
- Go to file T
- Go to line L
- Copy path
- Copy permalink
- Open with Desktop
- View raw
- Copy raw contents Copy raw contents
Copy raw contents
Copy raw contents
Программирование, с которым мы уже достаточно продолжительное время знакомимся, сегодня перейдет для нас на новый уровень.
Мы осваивали типы данных, как скалярные, так и структурные, составляли условия, программировали циклы, писали функции и пробовали передавать функции в функции как параметры. Все это было для нас просто программированием, хотя иногда и звучали заумные слова «структурное программирование», «функциональщина», «мультипарадигменность». Сегодня мы попробуем подвести под это все теоретическую основу, и затем освоить новые, соседние высоты.
Существует понятие парадигмы программирования. Парадигма — совокупность подходов, идей, понятий, даже принципов, которые определяют, как писать код. Удобный синоним — стиль, хотя понятие парадигмы несколько шире.
Зачастую парадигма или парадигмы, которые использует программист, определяются языком, проектом и существующим кодом на этом проекте, парадигмой, которой придерживается компания или конкретная команда проекта. Многие языки являются мультипарадигменными, т.е. поддерживают не одну, а несколько популярных парадигм, т.е. позволяют писать в разных парадигмах-стилях.
В различных источниках можно встретить множество названий парадигм, различные, и иногда даже противоречащие друг другу системы классификаций этих парадигм. Здесь мы перечислим самые распространенные из них и попытаемся сформулировать особенности каждой.
Существуют следующие парадигмы программирования:
- Императивная
- Структурная
- Модульная
- Объектно ориентированная
- Декларативная
- Функциональная
- Реактивная и многие многие другие менее известные.
Попробуем в этом многообразии разобраться.

Две основные парадигмы, на которые опираются многие другие парадигмы — это императивная и декларативная парадигмы.
Императивная парадигма и ее виды
Императивная парадигма программирования — это стиль написания кода, подразумевающий подробное описание алгоритма решения задачи и получения искомых данных. Императивный стиль использует много переменных в процессе своей работы и часто сохраняет в них промежуточные результаты вычислений. Императивный стиль является основным и самым распространенным стилем программирования.
В императивном стиле:
- описывают алгоритм решения поставленной задачи
- сохраняют состояния в переменных
- зачастую снабжают код комментариями, поскольку по самому коду бывает сложно понять его итоговую цель
Многие перечисленные парадигмы являются видом императивного подхода, попробуем проследить исторически, как они появлялись и какие вопросы решали.
История императивных парадигм
В соответствии с существовавшей в 1940-х годах архитектурой ЭВМ (архитектура фон Неймана) в программировании использовался процедурных подход, процедурная парадигма программирвания.
Процедурная парадигма подразумевает написание алгоритмов программ пошагово и частое использование подпрограмм, называемых процедурами. Процедуры — практически синонимы функций, которые нам достаточно известны. Единственная разница их в том, что процедуры просто выполняют какие-то действия, ничего не возвращая, а функции могут и должны возвращать значения.
Процедурная парадигма допускает использование оператора goto, достоинства которого уже к шестидесятым годам представлялись спорными. В 1968 году Эдсгер Дейкстра пишет известную статью «О вреде оператора goto», дебаты усиливаются, и к 1970-м годам формулируют новую парадигму — структурную.
Структурная парадигма программирования запрещает использование оператора goto, настоятельно рекомендуя использовать другие подходы:
- последовательность (выполнение программы сверзу вниз),
- ветвление (при помощи условий);
- цикличность (при помощи операторов циклов).
В то же самое время развивалась модульная парадигма. По модульной парадигме, необходимо размещать самодостаточный код в отдельные модули (чаще всего, отдельные файлы), которые могут взаимодействовать между собой.
Большая часть кода, который вы пишете и будете писать, относится к одной или нескольким императивным парадигмам, но велик шанс, что вы затронете и парочку декларативных парадигм.
Декларативная парадигма и ее виды
Декларативная парадигма программирования представляет собой стиль описания того. что вы хотите увидеть в итоге. Не написания алгоритма, как именно вы планируете получить желаемый результат, а подробное описание самого результата. Классические примеры языков с декларативным стилем — HTML, SQL. В декларативном стиле:
- не пишут, как решить задачу, но пишут, что требуется получить
- не сохраняют промежуточные состояния
- пишут так, чтобы по виду кода можно было понять его цель
К декларативным парадигмам часто относят функциональную, логическую и объектно-ориентированную парадигмы.
Основной отличительной чертой функционального программирования являются привелигированные права функций. Это означает, что с функциями можно работать так же, как с любыми другими данными, имеющимися в программе. Функции могут передаваться в качестве аргументов другим функциям, возвращаться в качестве результата или присваиваться переменным. Эта возможность рассматривать функции в качестве данных позволяет перейти на более высокий уровень абстракции и, следовательно, дает больше перспектив в плане многократного использования.(с) Алехандро Серано Мена
Второй важной особенностью функционального программирования является активное использование понятия чистоты выражения. Чистым выражением называется выражение, не зависящее от внешних условий и не меняющее ничего вовне, реагирующее только на те данные, которые ему передают в работу, и меняющее соответственно только результат своей работы.
В последнее время функциональное программирование снова набирает популярность, и по мнению многих более удобно и красиво в использовании, нежели ООП.
Функциональная парадигма программирования совмещает в себе оба подхода, поскольку может не сохранять состояния, довольно наглядна, но может включать в себя и алгоритм решения задачи, а не только описание результата.
И наконец парадигма программирования, «. о необходимости которой все время говорили большевики. «, Объектно Ориентированная Парадигма Программрования.

Все подходы, упоминавшиеся до этого, работают так: есть переменные, в которых хранятся данные, и функции, которые с этими данными работают. С усложнением программ и проектов такие функции становятся либо более сложными, если программисты идут по пути их универсализации, либо, если программисты идут по пути упрощения, такие функции упрощаются, но их становится чрезмерно много.
Объектно-ориентированный подход позволяет объединить данные, с которыми работает программист, с методами обработки этих данных. Благодаря ряду принципов, которые на самом деле не принципы ООП, а принципы правильного построения ООП, данные комбинируются в новые типы данных, функции для их обработки называются удобно, а зачастую их названия совпадают, принципы их применения зачастую идентичны и взаимосвязанны. Но не будем забегать вперед, все по порядку.
Сущности, классы, объекты, this
Начнем с определения сущности.
Сущность — описательное понятие, обобщающее несколько конкретных реализаций этого понятия. Человек — это сущность, Сигизмунд Аристархович Нетудыхата — конкретный человек. Сущность описывает какие-либо свойства человека, но не конкретизирует их. К примеру, у человека есть цвет глаз, рост, вес, пол, возраст, имя, фамилия, но нигде не указано конкретно, какого роста или какого пола человек, потому что сущность описывает общее понятие.
Класс — программная реализация сущности, описание сущности на языке программирования. Класс также называют конструкцией для создания нового типа данных, поскольку на основе существующих данных классы позволяют создавать новые. Так же класс называют чертежом, описывающим конкретную реализацию, но не реализующим.
Объект — реализация описанного в классе, конкретный экземпляр описанного в классе.
Строка — это сущность, у строки есть длина, есть символы, из которых она состоит, можно ее померять, поменять, дописать что-то в конец или в начало, заменить элемент.
Класс в данном случае — тип данных строка, функции для работы со строкой, свойства строки, такие как длина, нулевой элемент, кодировка и так далее.
Объектом будет являться конкретная строка, например, «Добрый вечер». Эта строка — объект класса Строка, но у объекта уже можно получить конкретную длину, 12 символов, найти нулевой символ «Д».
Создадим новый тип данных для описания человека, Person. Для описания человека мы чаще всего используем его имя, возраст, пол. Обычно мы для обработки таких данных передаем их параметрами в функцию, в ООП же мы создадим тип данных Person, а описательные данные придадим классу в качестве свойств.
Далее следует создать обработчик для этих данных, обычная функция нам поможет:
В коде выше мы переменные, которые ранее были просто разрозненными переменными, поместили в рамки класса Person, как и функцию-обработчик, которая ранее работала только с параметрами. Теперь эта функция является методом. У нее на данный момент нет параметров, это просто заготовка.
Person — это класс, программная реализация сущности, описание человека, с которым нам нужно работать, не конкретного человека, а вообще тех свойств человека, которые могут быть нам полезны, и методов для работы с этими свойствами.
Продолжим, создадим объект класса Person и выведем его полное имя, воспользовавшись написанной нами функцией get_info:
В данном коде мы реализовали функцию, передав туда объект и вернув его конкатенированные свойства.
Переменные, которые используются в классе и описывают объект, называются свойствами объекта или просто свойствами. Можно также встретить в литературе термины свойств класса, или переменных — членов класса, но вернее называть их свойствамии объекта.
Функции, которые используются в классе, называются методами объекта или методами класса. И то и то отчасти верно. Выполняются эти функции по-отношению к свойствам объекта, обрабатывают объект, следовательно, это методы работы с объектами. С другой стороны, описываются они в классе.
Обратите внимание на запись и чтение свойств объекта и вызов функции его класса, все это выполняется через оператор «стрелочка».
На данный момент мы не воспользовались ни одним преимуществом ООП, просто перевели код в термины объектов и классов.
Мы передали в функцию класса тот объект, с которым этой функции необходимо работать, так, как мы всегда делали в структурном программировании. Но у нас ООП, и есть специальный инструмент для упрощения этой процедуры, $this.
Ключевым понятием ООП является понятие this.
This — это переменная, которая есть у каждого метода класса. В this попадает объект, для работы с которым вызывался метод. Когда мы у объекта $sasha вызываем метод get_fullname , в this метода get_fullname попадает объект $sasha .
Какой объект вызвал метод, к такому объекту и обращается программист в рамках этого метода, когда пишет this. Каждый раз при вызове метода объекта this заполняется этим объектом. Объект — ссылочный тип данных, то, что вы поменяете в свойствах this, поменяется и в самом объекте.
Изменим кода класс в соответствии с этим пониманием:
Вызов метода у объекта, соответственно, не требует параметра:
Для простоты понимания this рекомендуется считать его невидимым параметром каждого метода, который передается не аргументом метода, а слева от стрелочки.
Принципы ООП: наследование и инкапсуляция
ООП не имеет смысла, если просто оборачивать код в классы и объекты. Настоящее ООП подразумевает использование принципов ООП, которые правильнее понимать не как дополнения, а как важные правила, без комплексного соблюдения которых нет смысла в применении объектно-ориентированной парадигмы.
Наследование — принцип ООП, позволяющий одному классу приобрести все свойства и методы другого класса без их копирования. Реализуется посредством ключевого слова extends. На нашем примере у класса Person будет класс — наследник Student. Сущность Student является в то же время сущностью Person, но с дополнительными свойствами и методами, которые присущи только студентам и доступны только им, а просто объектам класса Person не присущи и не доступны.
Обратите внимание, в новом классе есть новые методы и новое свойство. В унаследованном классе можно как создавать новые методы так и менять существующие. Хорошим тоном считается улучшать методы, унаследованные от родителей, так, чтобы они могли выполнять то же, что и методы родителей, но иначе, иногда лучше, иногда просто по-другому.
Наследование в PHP возможно только одиночное, это значит что у любого класса может быть только один класс — родитель.
Терминология в данном случае проста. Родительский класс, класс-потомок или дочерний класс, дерево наследования.
Инкапсуляцией называется принцип ООП, позволяющий скрывать детали реализации некоторых действий (методов) и доступы к ряду свойств объектов или классов. В языке php самая классическая инкапсуляция.
Реализуется инкапсуляция за счет спецификаторов (другая версия — модификаторов) доступа.
Спецификаторы доступа регламентируют доступность к методам и свойствам классов и объектов.
Public означает, что метод можно запустить откуда угодно: из методов этого же класса, методов классов-потомков или извне дерева наследования.
Protected означает, что метод можно запустить только из дерева наследования: из методов этого же класса или методов классов-потомков.
Private означает, что метод можно запустить только из метода того же класса, а методы классов-наследников такой возможности не имеют.
Аналогично и со свойствами: публичное свойство доступно отовсюду, защищенное из методов дерева наследования, приватное — только из методов того же класса.
Приведенный выше код не работает, php выдает ошибку, т.к. записать извне дерева наследования данные в переменную group он не может.