На тему Дерево-Ориентированного программирования я планирую написать несколько статей с постепенным усложнением материала. Это первая статья из серии, она предназначена для начинающих. Хотя надеюсь, что польза ею будет причинена даже опытным программистам.
В программировании есть два способа реализации объектов — наследование и композиция. Про наследование вам много и подробно расскажут в каждом учебнике, но когда речь заходит за композицию, то оказывается, что ничего, подобного объектно-ориентированному программированию в этом направлении не существует.
В сущности, композиция, это составление объекта из других, каждый из которых также состоит из других объектов. И, если задумаетесь, то обнаружите, что удивительным образом по-другому то и быть не может. Злые языки поговаривают, что бывают всякие очарованные кварки и иже с ними бозоны с лептонами, которые уже не делятся. Но это неточно.
Что получится, если попытаться описать составной объект? Как ни старайся, ничего другого, кроме древовидной структуры у вас не получится. Отсюда первый принцип:
Чтобы описать древовидную структуру нужно использовать древовидную структуру.
© Ваш КО
Поскольку любая программа — это всегда составной объект, то все программисты занимаются построением дерева объектов. И, если вам скажут, что Дерево Ориентированного программирования не существует, ответствуйте:
— Несчастные, за деревьями леса не видите! Только оно и существует!
Это и есть второй принцип:
Существует программирование только Дерево Ориентированное. Но бывает оно осознанное, а бывает нет.
С осознанием этих, казалось бы, очевидностей, возникает вопрос:
— А оно нам надо?
— Да-да, а не пошло бы это дерево лесом!?
И тут вот какие соображения имеются:
Все эти сложные объектно-ориентированные, дженерик-типизированные, солид-кисс-блабла-концептуализированные парадигмы созданы с единственной целью — упростить программирование. Дерево-Ориентированное программирование дает ещё одну степень ограничения сложности.
Чем проще программирование, тем сложнее программы мы можем создавать, тем больше денег зарабатывать, чего уж там стесняться этого факта.
Принципы Дерево-Ориентированного программирования просты и понятны, кроме первых двух. Но для начала, давайте определимся, что такое дерево объектов в нашем понимании, и как мы его можем построить в простейшем виде.
Итак, деревом объектов мы будем называть группу иерархически взаимосвязанных объектов.
Дерево объектов состоит из узлов — программных объектов разных классов, поддерживающих иерархическую функциональность.
Таким образом, например, документ XML или JSON мы не будем называть деревом объектов, это будет дерево данных. Дерево (Map), полученное в результате их стандартного парсинга, также будем называть деревом данных, поскольку составляющие его объекты не поддерживают иерархические связи.
Иерархическая взаимосвязь у нас будет означать, что каждый узел имеет ссылку на свой родительский узел, а также имеет список ссылок на дочерние узлы. Всё остальное опционально.
Пользовательский парсинг дерева данных с простым установлением иерархических связей между узлами даст нам то самое дерево объектов.
Деревья объектов тоже могут быть очень разными — это может быть дерево модели данных, дерево компонентов или виджетов, дерево состояний, и дерево чего вашей душе угодно.
Для начала возьмем дерево данных в JSON, а затем сделаем из него дерево объектов-моделей данных.
Дерево данных в JSON:
{ "computer": { "system_unit": { "motherboard": { "name": "MSI", "processor": { "name": "Intel" }, "video_card": { "name": "Nvidia" } } }, "monitor": { "name": "Asus" }, "keyboard": { "name": "Logitech" } } }
При парсинге мы преобразуем это дерево данных в дерево объектов, где объекты будут располагаться в аналогичной иерархии, будут типизированы и иметь ссылки на родителя и детей.
В примере ниже реализация иерархических зависимостей находится в родительском классе TreeNode:
class TreeNode { parent; children = []; constructor(parent) { this.parent = parent; this.parent.children.add(this); } } class Computer extends TreeNode { constructor(parent) { super(parent); } } class Monitor extends TreeNode { name; constructor(parent, name) { super(parent); this.name = name; } }
Представляете, какие огромные возможности дает такой подход? Аж мурашки по коже.
На основе этих данных мы сделаем:
Полноценную навигацию по дереву. В частности, на основе
parentиchildrenможно реализовать свойстваroot,first,last,previous,next, и т.п.Операции формирования дерева —
addChild,remove, и т.п.
Это позволит нам свободно ходить по дереву и манипулировать им.
Кроме этого, мы реализуем переключатели и множественный выбор узлов, разберемся, с чем это едят. Рассмотрим работу с деревом компонентов и деревом состояний. Возможности типизации дерева, описания и автогенерации кода, инструментов визуального редактирования.
В общем, продолжение следует, я пока обедать, а вы подписывайтесь, чтобы не проворонить выход следующих статей.
Удачи!
