Абстракция: Мышление разработчика
Самая важная идея, которую должен освоить каждый разработчик, - это абстракция. Это фундаментальное понятие, лежащее в основе всех программных систем, архитектур оборудования и, по сути, всего сложного.
Абстракция помогает управлять сложностью реальных систем, разбивать сложные системы на более простые компоненты и позволяет как создателям, так и пользователям быстро понять "что это такое". Абстракция встречается практически во всех аспектах современного мира, от программных приложений до оборудования и даже в "нетехнических" отраслях, таких как анимационные фильмы. Однако для разработчиков это особенно важно, поскольку они каждый день сталкиваются с этой концепцией и используют ее. В сущности, абстракция должна быть второй природой для всех разработчиков.
Что такое "абстракция"?
В общем смысле, "абстрагироваться" означает примерно "определить, что такое что-то для кого-то, игнорируя всю нерелевантную информацию", и это определение ("что-то") называется абстракцией.
Абстракции иногда синонимично называются "семантикой".
Обратите внимание, что некоторые люди могут дать другое определение "абстракции", например, "абстрактная сущность, общая для нескольких объектов". Вот почему я разделяю это определение на две части: "абстрактная природа" определяется как абстракция; "общая для нескольких объектов" определяется как "стандарты", что будет рассмотрено в следующем разделе.
Исходя из данного определения, возникает несколько важных вопросов при абстрагировании чего-либо:
- Что представляет собой абстрагируемый "объект"?
- Кто этот "кто-то"? Как он/она/оно будет взаимодействовать с "объектом"?
- Что это за "объект" с точки зрения этого "кто-то"?
- Какая информация является релевантной? Какая информация нет? То есть, что этот "кто-то" должен знать?
Обратите внимание, что ответы на эти вопросы зависят от "целевой аудитории" абстракции, то есть от лица (или системы), которое будет использовать абстракцию и взаимодействовать с "объектом". Если ваша аудитория меняется, "объект" может выглядеть иначе, релевантная информация может стать нерелевантной и наоборот.
Абстракция предназначена не только для других людей; иногда (на самом деле, в большинстве случаев) аудиторией может быть сам разработчик, создающий и реализующий абстрагируемый "объект".
Хотя я привел определение выше, сама абстракция - это "абстрактная" идея, которую очень сложно четко определить, и нет широко принятого определения. Поэтому я приведу пример, чтобы проиллюстрировать, что на самом деле означает абстракция.
Пример абстрагирования
Когда вы спешите утром и видите автомобиль, что приходит вам первым на ум? "Я могу водить эту штуку", или шасси, двигатель, шины и бак для топлива?
Думаю, для большинства людей первое представление будет первым. Конечно, второе представление тоже важно, но оно для вас неактуально в данный момент: вы спешите, поэтому все, что вам важно, это то, что вы можете водить автомобиль, чтобы быстро добраться до работы.
Верьте или нет, вы уже создали абстракцию в приведенном выше примере. Давайте немного разберем его:
- Цель абстрагирования: Автомобиль.
- Целевая аудитория: Вы.
- Что это за "что-то" (абстракция): Что-то, что вы можете использовать для езды по дорогам и быстрого перемещения в любое место.
- Релевантная информация: Вы можете управлять этой вещью. Она быстрая.
- Нерелевантная информация: Она состоит из двигателя, топливного бака, шасси и т. д. Она длинна 4,6 метров и высота 1,6 метра, с максимальной мощностью двигателя 140 лошадиных сил. И так далее.
Пояснение выше должно быть легко понятным: целевой аудиторией являетесь вы, и единственное, что вам нужно знать - это то, что вы можете водить автомобиль, именно это и является абстракцией.
Для работников автомобильного завода, однако, представление будет отличаться. Рабочие строят автомобили; им не нужно знать, как управлять автомобилем, но им нужно знать внутреннее устройство автомобиля, чтобы они могли его построить. В этом случае у нас есть:
- Цель абстрагирования: Автомобиль.
- Целевая аудитория: Рабочие автомобильного завода.
- Что это за "что-то" (абстракция): Что-то из двигателя, топливного бака, шасси и остальных деталей.
- Релевантная информация: Внутренняя структура автомобиля.
- Нерелевантная информация: Как водить автомобиль.
Как вы видите, абстракция зависит от целевой аудитории. По мере изменения целевой аудитории, изменяется определение цели абстрагирования, и ранее релевантная/нерелевантная информация может стать нерелевантной/релевантной.
Абстракция также зависит от роли целевой аудитории. Когда вы водите автомобиль, абстракция автомобиля - это "что-то, что вы можете водить"; когда вы ремонтируете автомобиль, абстракция начинает включать двигатели, шины и т. д., потому что такие детали теперь для вас актуальны.
Поэтому всегда важно определить целевую аудиторию и понять, что она будет делать с целью абстракции, а затем решить, какая информация является релевантной/нерелевантной и абстрагировать "что-то" аудитории.
Термины и фразы, связанные с абстракцией
В мире разработки вы встретитесь с некоторыми терминами или фразами, связанными с абстракцией. Вот значения некоторых из них:
Абстракция
В зависимости от сценария "абстракция" может иметь 3 различных значения:
- Первое значение - "абстрактное определение" объекта, как определено в этом разделе. Основное значение этого определения - "как что-то выглядит для кого-то", но "как что-то выглядит" может быть простым или сложным в зависимости от этого "кто-то";
- Второе значение - "упрощенное определение объекта, созданное путем скрытия нерелевантных деталей". Это значение подчеркивает, что "абстракция" - это упрощенное описание, скрывающее детали.
- Третье значение - "антиречийный стандарт, общий для множества объектов"; основное значение этого определения - это то, что абстракция применима ко многим объектам.
Абстракция над
"Абстракция над A" означает, что A является целью абстракции, то есть "что-то", от которого создается абстракция и к которому она применяется.
Абстрагироваться от
Отвлечься от A означает скрыть нерелевантные детали при создании абстракции; A выступает в качестве этих "нерелевантных деталей". Пример: "Языки программирования отвлекают настоящие детали аппаратного обеспечения".
Высоко/низкоуровневая абстракция
Высокоуровневая абстракция - это более абстрактная абстракция, в то время как низкоуровневая абстракция - это более конкретная абстракция. Другими словами, высокоуровневые абстракции обычно более просты, но также отдаляются от реальных объектов, которые абстрагируются; низкоуровневые абстракции обычно более сложны, но также ближе к целям абстрагирования.
Например, если цель абстрагирования - это автомобиль, высокоуровневая абстракция может быть "что-то, что можно водить"; низкоуровневая абстракция может быть "что-то, что имеет двигатель, шасси и некоторые колеса" (да, это тоже абстракция. Так как каждый автомобиль с двигателем на топливе имеет двигатель, шасси и некоторые колеса, и это определение скрывает внутреннее устройство двигателя, шасси и т. д., его можно рассматривать как "абстрактный и общий" в каком-то смысле).
Как выглядит абстрагирование в мире разработчика?
Хотя пример с автомобилем иллюстрирует концепцию абстрагирования, он кажется не связанным с разработкой программного обеспечения. Теперь давайте посмотрим, как абстрагирование выглядит в реальных программных системах и коде.
Вот фрагмент исходного кода из KonnyakuGPT, генератора субтитров аниме на основе искусственного интеллекта (не обязательно разбираться в коде):
def simple_split_subtitles(subtitles: Sequence[srt.Subtitle], max_duration: datetime.timedelta) -> List[srt.Subtitle]:
"""Разделяет слишком длинные субтитры.
Схема разделения проста; предложения вероятно будут разбиты на части.
Args:
subtitles (Sequence[srt.Subtitle]): Исходные субтитры.
max_duration (float, необязательно): Максимальная продолжительность каждого выходного субтитра в секундах. По умолчанию 10.
"""
new_subtitles = []
for subtitle in subtitles:
remaining_text = subtitle.content
current_start = subtitle.start
splitted_subtitles = []
while len(remaining_text) > 0:
expected_text_length = math.floor(max_duration / (subtitle.end - current_start) * len(remaining_text))
actual_text_length = min(expected_text_length, len(remaining_text))
item_text = remaining_text[:actual_text_length]
item_duration = len(item_text) / len(remaining_text) * (subtitle.end - current_start)
splitted_subtitles.append(srt.Subtitle(
index=len(new_subtitles) + len(splitted_subtitles),
start=current_start,
end=current_start + item_duration,
content=item_text
))
remaining_text = remaining_text[actual_text_length:]
current_start += item_duration
new_subtitles += splitted_subtitles
return new_subtitles
Сейчас нет необходимости понимать, что делает этот код и как он выполняет свою работу. В основном этот код составляет функцию (представьте это как инструмент, который можно использовать для выполнения чего-то), который может разделять длинные субтитры на более короткие.
Вы могли заметить, что в начале есть некоторый текст, читаемый человеком, а именно следующий:
"""Разделяет слишком длинные субтитры.
Схема разделения проста; предложения вероятно будут разбиты на части.
Args:
subtitles (Sequence[srt.Subtitle]): Исходные субтитры.
max_duration (float, необязательно): Максимальная продолжительность каждого выходного субтитра в секундах. По умолчанию 10.
"""
Такой текст называется "докстринг", который, как следует из его названия, предоставляет документацию для функции. Такой докстринг служит абстракцией для пользователя функции, поскольку он включает и только то, что пользователь должен знать: что делает функция и как ее использовать. Остальная часть функции, то есть все после докстринга - это все нерелевантно для пользователя, даже если это логический код, который позволяет функции работать. Пользователь должен знать только, как использовать функцию; ему не важно, как функция работает внутренне.
Абстракция является очень важной в этом сценарии, потому что она позволяет пользователю функции быстро понять только те вещи, которые ему нужно понять. Без докстринга единственный способ узнать, что делает функция - это прочитать и понять код. Хотя это возможно, это гораздо более трудоемко, чем чтение докстринга, и большая проблема заключается в том, что если логический код изменяется, пользователи должны менять способ использования функции, что приведет к множеству изменений в коде. С помощью абстракции, однако, независимо от того, как изменяется логический код, пока он поддерживает интерфейс (то есть то, что функция делает и как ее использовать), определенный в абстракции, пользователи не должны менять способ использования функции.
Абстракции важны не только для пользователей программных систем, но и для тех, кто разрабатывает систему. Когда в программе задействовано много кода (например, KonnyakuGPT имеет примерно ~2,000 строк кода на Python), становится сложно запомнить, что делает каждая часть кода. Без абстракций, таких как докстринги, даже вам самим будет трудно понять код, написанный вами ранее; абстракции облегчают понимание, организацию и поддержку программного обеспечения, над которым вы работаете.
Поздравляю! Вы поняли абстракцию, которая является основным понятием всех языков программирования и процессов разработки программного обеспечения. Далее мы рассмотрим иерархию, которая является способом управления сложностью и идеей, используемой во всех аспектах мира разработки.