Перейти к содержанию

Иерархия: способ управления сложностью

Вторая по важности идея после абстракции - это идея иерархии. Иерархия - это способ управлять сложностью, и она присутствует практически в каждом программном приложении.

Что означает "иерархия"?

В широком смысле, идея иерархии заключается в группировке вещей вместе и формировании дерева абстракций; это "дерево абстракций" называется "иерархией".

Это очень абстрактное определение, давайте посмотрим на пример.

Предположим, что вы студент колледжа и у вас есть следующие файлы для курсовых заданий, слайды PPT и т.д.:

introduction-to-ai.pdf
calculus-assignment-1.pdf
programming-assignment-2.py
literature-textbook.epub
introduction-to-ai-lecture-2.pdf
calculus-assignment-2.pdf
programming-assignment-3.py
literature-review-article.epub
introduction-to-ai-project-outline.docx
calculus-final-exam-review.pdf
programming-code-snippets.txt
literature-essay-draft.docx
introduction-to-ai-research-paper.pdf
calculus-quiz-answers.docx
programming-tutorial-slides.pptx
literature-poetry-analysis.pdf

Ого, это много файлов. И выглядит это беспорядочно, не так ли?

Естественной идеей было бы группировать их в папки, например:

course-files/
  AI/
    introduction-to-ai.pdf
    introduction-to-ai-lecture-2.pdf
    introduction-to-ai-project-outline.docx
    introduction-to-ai-research-paper.pdf
  Calculus/
    calculus-assignment-1.pdf
    calculus-assignment-2.pdf
    calculus-final-exam-review.pdf
    calculus-quiz-answers.docx
  Programming/
    programming-assignment-2.py
    programming-assignment-3.py
    programming-code-snippets.txt
    programming-tutorial-slides.pptx
  Literature/
    literature-textbook.epub
    literature-review-article.epub
    literature-essay-draft.docx
    literature-poetry-analysis.pdf

Выглядит лучше, верно? Файлы по одной и той же теме сгруппированы вместе, и таким образом, вы можете найти то, что вам нужно намного легче.

Это и есть идея иерархии. Вспомним определение иерархии: идея иерархии заключается в группировке вещей вместе и формировании дерева абстракций. Здесь мы группируем файлы вместе в соответствии с темой, к которой они относятся. Вы можете спросить: "где 'дерево абстракций'?" Что ж, вышеуказанная структура каталогов также может быть представлена следующим графом:

mindmap
  root((course-files))
    AI
      introduction-to-ai.pdf
      introduction-to-ai-lecture-2.pdf
      introduction-to-ai-project-outline.docx
      introduction-to-ai-research-paper.pdf

    Calculus
      calculus-assignment-1.pdf
      calculus-assignment-2.pdf
      calculus-final-exam-review.pdf
      calculus-quiz-answers.docx

    Programming
      programming-assignment-2.py
      programming-assignment-3.py
      programming-code-snippets.txt
      programming-tutorial-slides.pptx

    Literature
      literature-textbook.epub
      literature-review-article.epub
      literature-essay-draft.docx
      literature-poetry-analysis.pdf

Теперь это выглядит как ветви дерева. Каждый узел в дереве представляет собой абстракцию, и абстракция дочернего элемента связана с абстракцией его родителя. Например, абстракцией папки "course-files" могло бы быть "все файлы для университетских курсов"; ее дочерние элементы - "AI", "Calculus", "Programming" и "Literature", а каждая из этих папок абстрагирует "все файлы для определенного курса", который является частью "всех файлов для курсов".

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

Распространенные типы иерархий

Композиция

Композиция, вероятно, является самым распространенным типом иерархии. Иерархия композиции - это иерархия, где, в дереве абстракций, родитель содержит детей.

Предыдущий пример с файлами курсов является иерархией композиции. В этом примере папка "course-files" является родителем папок "AI", "Calculus", "Programming" и "Literature"; папка каждого курса является родителем файлов этого курса. "course-files" содержит папки курсов; каждая папка курса содержит файлы этого курса. То есть, родитель содержит детей.

Еще один пример - автомобиль. На самом верхнем уровне автомобиль состоит из кузова, двигателя, шасси и колес. Затем кузов автомобиля содержит двери и окна, двигатель содержит передачи и цилиндры, и так далее.

graph TD

A([Car]) --> B([Car-Body])
A --> E([chassis])
A --> F([Wheels])
A --> C([Engine])

B --> G([Doors])
B --> H([Windows])

C --> I([Gears])
C --> J([Cylinders])

Иерархия от общего к частному

Еще один распространенный тип иерархии - иерархия от общего к частному. В иерархии этого типа родитель обобщает детей, а его абстракция является пересечением характеристик детей.

Например, рассмотрим следующую иерархию:

graph TD

A([Creatures]) --> B([Plants])

B --> G([Trees])

B --> H([Grass])

A --> C([Animals])

C --> D([Insects])

C --> E([Mammals])

E --> F([Humans])

В этой иерархии "Анималс" является типом "Кричерес"; "Маммальс" является типом "Анималс"; и "Хьюманс" является типом "Маммальс" и т.д. То есть, каждое дитя является типом родителя, плюс некоторые характеристики, специфичные для него самого; характеристики родителя общие для всех его детей.

Зачем важна иерархия?

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

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

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

С учетом идеи иерархии, мы бы разбили автомобиль на более управляемые части. Например, мы можем иметь одну команду инженеров, работающих над двигателем, другую команду, работающую над шасси, и т.д. И команда, работающая над двигателем, может еще дальше разбить двигатель на более мелкие части, чтобы убедиться, что они все работают вместе. Команда, работающая над двигателем, не должна знать, как работает шасси (в общем); и наоборот.

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

В разработке программного обеспечения "замена неисправной части" примерно соответствует исправлению неправильного куска кода; "объяснение, как работает автомобиль" примерно соответствует пониманию того, из чего состоит программное обеспечение, чтобы знать, как написать для него код.

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

Поздравляю! Теперь вы узнали идею иерархии. Далее мы поговорим о последнем концепте в этом модуле: стандарты.