На тему Дерево-Ориентированного программирования я планирую написать несколько статей с постепенным усложнением материала. Это первая статья из серии, она предназначена для начинающих. Хотя надеюсь, что польза ею будет причинена даже опытным программистам.
В программировании есть два способа реализации объектов — наследование и композиция. Про наследование вам много и подробно расскажут в каждом учебнике, но когда речь заходит за композицию, то оказывается, что ничего, подобного объектно-ориентированному программированию в этом направлении не существует.
В сущности, композиция, это составление объекта из других, каждый из которых также состоит из других объектов. И, если задумаетесь, то обнаружите, что удивительным образом по-другому то и быть не может. Злые языки поговаривают, что бывают всякие очарованные кварки и иже с ними бозоны с лептонами, которые уже не делятся. Но это неточно.
Что получится, если попытаться описать составной объект? Как ни старайся, ничего другого, кроме древовидной структуры у вас не получится. Отсюда первый принцип:
Чтобы описать древовидную структуру нужно использовать древовидную структуру.
© Ваш КО
Поскольку любая программа — это всегда составной объект, то все программисты занимаются построением дерева объектов. И, если вам скажут, что Дерево Ориентированного программирования не существует, ответствуйте:
— Несчастные, за деревьями леса не видите! Только оно и существует!
Это и есть второй принцип:
Существует программирование только Дерево Ориентированное. Но бывает оно осознанное, а бывает нет.
С осознанием этих, казалось бы, очевидностей, возникает вопрос:
— А оно нам надо?
— Да-да, а не пошло бы это дерево лесом!?
И тут вот какие соображения имеются:
Все эти сложные объектно-ориентированные, дженерик-типизированные, солид-кисс-блабла-концептуализированные парадигмы созданы с единственной целью — упростить программирование. Дерево-Ориентированное программирование дает ещё одну степень ограничения сложности.
Чем проще программирование, тем сложнее программы мы можем создавать, тем больше денег зарабатывать, чего уж там стесняться этого факта.
Принципы Дерево-Ориентированного программирования просты и понятны, кроме первых двух. Но для начала, давайте определимся, что такое дерево объектов в нашем понимании, и как мы его можем построить в простейшем виде.
Итак, деревом объектов мы будем называть группу иерархически взаимосвязанных объектов.
Дерево объектов состоит из узлов — программных объектов разных классов, поддерживающих иерархическую функциональность.
Таким образом, например, документ 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
, и т.п.
Это позволит нам свободно ходить по дереву и манипулировать им.
Кроме этого, мы реализуем переключатели и множественный выбор узлов, разберемся, с чем это едят. Рассмотрим работу с деревом компонентов и деревом состояний. Возможности типизации дерева, описания и автогенерации кода, инструментов визуального редактирования.
В общем, продолжение следует, я пока обедать, а вы подписывайтесь, чтобы не проворонить выход следующих статей.
Удачи!