Какова ценность сокрытия деталей через абстракции? Разве нет ценности в прозрачности?


30

Задний план

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

Есть еще одно важное «преимущество» абстракции, которое заключается в том, чтобы скрыть логику реализации и детали от пользователей этой абстракции. Аргумент заключается в том, что вам не нужно знать детали, и что на этом этапе следует сосредоточиться на собственной логике. Имеет смысл в теории.

Однако всякий раз, когда я обслуживаю большие корпоративные приложения, мне всегда нужно знать больше деталей. Это становится огромной проблемой, копаясь все глубже и глубже в абстракцию на каждом шагу, просто чтобы точно узнать, что что-то делает; т. е. необходимость делать «открытое объявление» примерно 12 раз, прежде чем найти используемую хранимую процедуру.

Этот менталитет «скрыть детали», кажется, просто мешает. Я всегда желаю более прозрачных интерфейсов и меньшей абстракции. Я могу читать исходный код высокого уровня и знать, что он делает, но я никогда не узнаю, как он это делает, когда, как он это делает, это то, что мне действительно нужно знать.

Что тут происходит? Все ли системы, над которыми я когда-либо работал, были плохо спроектированы (по крайней мере, с этой точки зрения)?

Моя философия

Когда я разрабатываю программное обеспечение, я чувствую, что пытаюсь следовать философии, которая, по моему мнению, тесно связана с философией ArchLinux :

Arch Linux сохраняет врожденные сложности системы GNU / Linux, сохраняя их хорошо организованными и прозрачными. Разработчики и пользователи Arch Linux считают, что попытка скрыть сложности системы на самом деле приводит к еще более сложной системе, и поэтому ее следует избегать.

И поэтому я никогда не пытаюсь скрыть сложность своего программного обеспечения за уровнями абстракции. Я стараюсь злоупотреблять абстракцией, а не становиться ее рабом.

Вопрос в глубине души

  1. Есть ли реальная ценность в сокрытии деталей?
  2. Разве мы не жертвуем прозрачностью?
  3. Разве эта прозрачность не важна?

7
Абстракцией можно злоупотреблять в виде плохого дизайна. Но это не означает, что абстракция в принципе не является ценной.
Бернард

4
Я думаю, что там есть хороший вопрос, однако, он звучит как бред против абстракции. Не могли бы вы преуменьшить это и еще больше подчеркнуть свой актуальный вопрос.
PersonalNexus

4
Вы уверены, что используете правильное определение «скрывать детали»? В этом контексте речь идет о сокращении связей , а не о том, чтобы помешать вам изучить внутреннюю работу чего-либо.
Андрес Ф.

24
Если вы не любите программировать с помощью вольтметра и осциллографа за столом, вы программируете только на абстракциях поверх абстракций поверх абстракций. Есть ли для вас смысл скрывать детали, которыми вы на самом деле манипулируете не битами, а на самом деле напряжениями? Делает ли это жертвой прозрачность? Это прозрачность ценно?
Эрик Липперт

8
Я думаю, с чем у вас проблемы, это не абстракция, это пустые слои косвенности, которые на самом деле ничего не абстрагируют. Да, они часто встречаются в крупных корпоративных системах, и нет, они не очень хороши.
Майкл Боргвардт

Ответы:


47

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

Представьте, что у вас есть список объектов, и у каждого объекта есть Nameсвойство и другие данные. И часто вам нужно найти в списке элемент, который Nameсоответствует определенной строке.

Очевидный способ состоит в том, чтобы перебирать каждый элемент один за другим и проверять, соответствует ли Nameстрока. Но если вы обнаружите, что это занимает слишком много времени (как если бы в вашем списке было несколько тысяч элементов), вы можете заменить его поиском в словаре строковых объектов.

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

Но если у вас есть FindByNameметод для инкапсуляции процесса поиска имени, вы можете просто изменить способ его реализации, и весь код, который его вызывает, продолжит работать и станет намного быстрее бесплатно. Это реальная ценность абстракции и инкапсуляции.


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

3
@ User606723: так и должно быть. Это не означает , что она всегда есть . Некоторые люди не понимают смысла, и они просто складывают больше слоев поверх большего количества слоев и превращают вещи в беспорядок. Вот почему опытные программисты советуют новым разработчикам никогда не применять новую технологию или технику, пока они не поймут ее.
Мейсон Уилер

3
@ user606723: Прозрачность способствует тесной связи, поэтому, возможно, не всегда плохо, но обычно так и есть.
Malfist

3
Проблема, которую Мейсон описывает, из-за того, что люди накапливают слои в форме программ культового груза, является причиной того, что я с подозрением отношусь к слишком большому количеству наследования, и почему состав следует отдавать предпочтение перед наследованием. Кажется, особенно проблематично для программистов на Java.
Джокинг

2
Нет, жесткое сцепление не всегда плохо. Это часто плохо, но если идти на все, чтобы избежать этого, это может привести к еще худшим проблемам, таким как мягкое кодирование.
Мейсон Уилер

16

Я только что закончил читать раздел в Code Complete об абстракции, так что здесь большинство источников.

Смысл абстракции состоит в том, чтобы убрать необходимость спросить «как это реализовано?». Когда вы звоните user.get_id(), вы знаете, что это idто, что вы собираетесь вернуть. Если вам нужно спросить "как это получить идентификатор пользователя?" тогда вы, вероятно, либо не нуждаетесь id, либо get_id()возвращаете что-то неожиданное и плохо разработанное.

Вы используете абстракцию, чтобы позволить вам проектировать:

a house with doors and windows

не дизайн

a box with four walls,
    with 3 holes,
        two of which fit panes of glass surrounded by wood frames,
        one that fits a large plank of wood with hinges and a metal knob,
etc.

Я не говорю об этих интерфейсах. Эти интерфейсы в порядке. Я говорю об огромных сложных системах, которые разделены на множество различных абстракций.
user606723

9
@ user606723 Тогда ваш вопрос о сверхсложном дизайне, а не об абстракциях
Андрес Ф.

3
+1 для завершения кода. Он охватывает как то, почему абстракция необходима для проектирования, так и почему неправильный уровень абстракции мешает дизайну. Чтобы продолжить ваш пример, если я работаю в офисе зонирования, я хочу подумать о ваших домах, не вдаваясь в детали. Но если бы вы думали о домах так, как я, тогда вы не смогли бы их построить.
Спенсер Рэтбун

этот вопрос должен быть закрыт или название изменено
Джейк Бергер

8

Есть ли реальная ценность в сокрытии деталей?

Да. Представляя абстракции, мы можем думать и программировать на более высоком уровне.

Представьте себе моделирование физических систем без исчисления или матричной алгебры. Это совершенно непрактично. Точно так же, если мы можем программировать только на скалярном уровне, мы не сможем решить интересные проблемы. Даже относительно простые веб-приложения могут значительно выиграть от таких абстракций, как библиотеки тегов. Гораздо проще вставить тег, который означает «поля ввода адреса», чем повторно создавать четыре текстовых поля и поле выбора. И если вы решите расширить свою деятельность за рубежом, вы можете просто изменить определение тега, а не исправлять каждую форму для обработки международных адресов. Эффективное использование абстракции - это то, что делает некоторых программистов в десять раз эффективнее других.

У людей ограниченная рабочая память. Абстракция позволяет нам рассуждать о больших системах.

Aren't we sacrificing transparency?

Нет. Если абстракции не используются, то назначение программного компонента скрыто в повторяющихся деталях. Разработчики проводят дни, разбираясь с кодом, подобным этому:

for (i = 0; i < pilgrim.wives.size(); ++i) {
  wife = pilgrim.wives[i];
  for (j = 0; j < wife.sacks.size(); ++j) {
     sack = wife.sacks[i];
     for (k = 0; j < sack.cats.size(); ++j) {
        cat = sack.cats[k];
        for (m = 0; m < cat.kits.size(); ++m) {
           ++count;
        }
     }
  }
}

и думать "о, да еще один четырехуровневый цикл над наборами", вместо того, чтобы видеть

pilgrim.kits.each { ++count; }

Разве эта прозрачность не важна?

Как вы указали, косвенность имеет цену. Нет смысла создавать слои "на всякий случай". Используйте абстракцию, чтобы уменьшить дублирование и уточнить код.


7

Когда люди говорят, что абстракции скрывают детали реализации, они на самом деле не означают «скрывать» в том смысле, что их трудно найти. Они подразумевают отдельные детали реализации от общедоступного интерфейса, чтобы интерфейс был простым, лаконичным и управляемым. Точно так же, как автомобиль «скрывает» большинство своих жизненно важных частей и предлагает лишь элементарный набор элементов управления для управления ими, программный модуль «скрывает» большую часть своей функциональности глубоко в недрах и предоставляет только ограниченное количество методов доступа к ним. водить его. Представьте себе машину, в которой вам пришлось бы вручную управлять всеми внутренностями двигателя (а их очень много), вам будет очень трудно следить за движением и найти дорогу.

Но поддерживать интерфейс простым не просто эстетически; это может иметь значение между успешным проектом и маршем смерти. Давайте сыграем адвоката дьявола на минуту; представьте программный проект без каких-либо абстракций вообще. Если вам нужно сохранить значение, вы используете глобальную переменную. Если вам нужно использовать функциональность более одного раза, скопируйте и вставьте ее. Если вам нужны две разные версии определенного раздела кода, вы копируете, вставляете его в ifоператор и изменяете обе ветви. Технически говоря, это работает, но через несколько месяцев вы будете бороться с несколькими действительно неприятными проблемами:

  • Когда вы находите и исправляете ошибку, она, вероятно, также существует в других экземплярах аналогичного кода, вставленных при копировании, поэтому, помимо поиска и исправления ошибки, вы также должны искать другие случаи и исправлять их.
  • Чтобы найти ошибку или внедрить изменение, программист по техническому обслуживанию должен уметь понимать соответствующий код. Сложность в этом увеличивается с размером соответствующего раздела кода, но еще больше с его областью действия. Держать полдюжины переменных в своей голове, мысленно шагая по некоторому коду, выполнимо; но если у вас их несколько сотен, на вашу производительность сильно влияют (мне нравится сравнивать мыслительный процесс с программой, которая исчерпывает физическую ОЗУ и должна погрузиться в файл подкачки: вместо того, чтобы бегло читать код за один раз программист должен прыгать туда-сюда, чтобы искать вещи).
  • Объем фрагмента кода также влияет на размер кодовой базы, которую нужно найти, чтобы найти ошибку. Если у вас есть функция из десяти строк с двумя параметрами и без глобальных переменных, и вы знаете значения входных данных и строку, в которой происходит сбой, обнаружение ошибки обычно тривиально и зачастую не требует ничего, кроме просмотра кода. Если это несколько сотен строк, двадцать параметров, пятнадцать глобальных переменных и вызывает несколько других функций аналогичного характера, вас ждет серьезная боль.
  • Без надлежащей абстракции любое изменение может потенциально повлиять на большие части кодовой базы, поскольку практически все может зависеть от кода, подлежащего изменению. Типичным симптомом таких кодовых баз является то, что вы вносите небольшое, казалось бы, невинное изменение, и совершенно не связанная с этим функция внезапно ломается. С помощью абстракции вы можете ограничить размер ущерба, который может нанести изменение, и сделать воздействие более предсказуемым. Если вы измените имя частного поля, у вас будет только один исходный файл для проверки; если вы изменяете имя глобальной переменной, вам нужно пройти по всей базе кода.

В плохо абстрагированной кодовой базе влияние обычно растет экспоненциально с размером кодовой базы, то есть добавление постоянного количества кода увеличивает затраты на обслуживание на постоянный коэффициент. Что еще хуже, добавление большего количества программистов в проект не увеличивает производительность линейно, но в лучшем случае логарифмически (поскольку чем больше ваша команда, тем больше накладных расходов требуется для связи).


2

Я думаю, вы должны понимать, как это работает, если это необходимо. Как только вы определили, что он делает то, что, как вы думали, он будет делать, тогда у вас есть душевное спокойствие. Я никогда не думал, что целью было скрыть это навсегда.

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


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

1
Видите ли вы изменения кода для каждой платформы, которую вы когда-либо использовали?
JeffO

1
нет, но я не поддерживаю изменения кода для каждой платформы, которую я когда-либо использовал.
user606723

3
Вы в значительной степени доказали точку зрения Джеффо: вы не заняты обслуживанием будильников. Если вы купите один и начнете его использовать, не разбирая его полностью и не проанализировав, как он работает, вы согласитесь, что внутренности будут для вас абстрактными. Ничто не говорит, что вы не можете разорвать его на части, чтобы узнать, как это работает, но как часто вы находите это необходимым?
Blrfl

2

Чтобы ответить на ваши вопросы конкретно:

Есть ли реальная ценность в сокрытии деталей?

Да. Как вы признаете в первой строке вашего вопроса.

Разве мы не жертвуем прозрачностью?

На самом деле, нет. Хорошо написанная абстракция позволит легко понять детали, если это необходимо.

Разве эта прозрачность не важна?

Да. Абстракции должны быть разработаны и реализованы, чтобы облегчить понимание деталей, когда это необходимо / желательно.


Наконец ответ мне нравится.
user606723

1

Я бы сказал, что скрывать детали - это хорошо, когда скрытые вещи работают.

Например, скажем, мы разработали интерфейс, который определяет поведение (например, GetListItems, SendListItem), которые представляют собой две функции, которые инициируются пользователем с помощью какого-либо нажатия кнопки или чего-то еще. ТЕПЕРЬ, у каждого пользователя может быть свой собственный «ListItemStore» кто-то на Facebook, кто-то на MySpace .. (например) ... и скажем, что он сохранен как пользовательское свойство / настройка где-то в приложении через пользовательские настройки ... и скажем, что разработчики приложений могут добавлять дополнительные ListItemStore в течение время (mybook, facespace и т.д ..)

теперь есть много деталей о подключении к Facebook и получении предметов ... и столько же при подключении к myspace ... и так далее ...

теперь, после того, как начальный код «доступа к магазину» написан, его, возможно, не нужно будет модифицировать (ну, в случае с Facebook, нам, вероятно, нужен полностью занятый разработчик, чтобы не отставать от изменений, zing ..),

поэтому, когда вы используете код, это что-то вроде:

    new ItemManager(user) //passes in user, allowing class to get all user properties
    ItemManager.GetListItems()

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

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


Да, но та часть, которую нужно сохранить, никогда не бывает этими двумя строчками. Это невозможно облажаться. Это всегда 2-й, 3-й, 4-й уровень, который вам нужно изменить. Я согласен, что это здорово, когда у вас есть API, которому можно доверять, чтобы быть стабильным , но что, если он не может быть стабильным только из-за сложности вашего бизнеса?
user606723

1
@ user606723 если ваш API не стабилен, то скорее всего он либо незрелый, либо, скорее, неправильная абстракция
sdg

@ user606723 - Это правда, и в этих случаях сами соглашения об именах должны определять некоторую форму прозрачности, которая скрывает фактическую логику / детали программирования ... и если вам когда-либо придется изменять фактический источник, дальнейшие детали и идеи должны быть выражены посредством информативного именования так что, по сути, прозрачность может быть достигнута с помощью правильного наименования до конца, однако нам не нужно действительно часто проходить весь путь вниз.
Hanzolo

@sdg, или потому что требования системы постоянно меняются. Потому что законы меняются, потому что меняются чужие API, это вне нашего контроля.
user606723

1
@ user606723 - на самом деле я работаю в финансовой системе SaaS и вижу недостатки, связанные с недостаточной абстракцией в каждом цикле выпуска. частично это результат плохого дизайна, но обычно это результат переноса кода туда, где он изначально не был предназначен. Спуск по цепочке может быть болезненным без этих комментариев, имен и инкапсуляции . если бы все, что мне нужно было сделать, это Remeasurements.GetRemeasureType (grant), а затем reMeasure.PerformCalc (), это было бы намного приятнее, чем добавление перегрузок и чтение различных логических ветвей для получения правильного расчета или добавления нового
Hanzolo

1

То, что вы называете «Скрытием», многие рассматривают как разделение интересов (например, «Реализация против интерфейса»).

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

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


1

Во-первых, все, кроме одной инструкции машинного кода, по сути является абстракцией - while...doцикл является последовательным символическим способом представления сравнений и вызовов адресов, необходимых для повторения набора инструкций до тех пор, пока не будет выполнено условие. Аналогично, тип int является абстракцией для количества битов X (в зависимости от вашей системы). Программирование это все о абстракции.

Вы, вероятно, согласитесь, что эти примитивные абстракции очень полезны. Ну, так это возможность построить свой собственный. OOAD и OOP все о.

Предположим, у вас есть требование, когда пользователи хотят иметь возможность экспортировать данные с экрана в различных форматах: текст с разделителями, Excel и PDF. Разве не удобно, что вы можете создать интерфейс под названием «Экспортер» с методом export (data), на основе которого вы можете создать DelimitedTextExporter, ExcelExporter и PDFExporter, каждый из которых знает, как создать свой конкретный вывод? Все, что нужно знать вызывающей программе, это то, что она может вызывать метод export (data), и какая бы реализация ни использовалась, она сделает свое дело. Более того, если текстовые правила с разделителями изменятся, вы можете изменить DelimitedTextExporter без необходимости связываться с ExcelExporter, возможно, нарушив его.

Практически все известные шаблоны проектирования, используемые в ОО-программировании, зависят от абстракции. Я бы порекомендовал почитать Freeman и Freeman's Head First Design Patterns, чтобы лучше понять, почему абстракция - это хорошо


1
даже машинный код - это абстракция, есть реальные, физические процессы, происходящие под логикой, даже цифровая электроника - это абстракция над тем, что на самом деле происходит, о чем может свидетельствовать любой, кто сделал хэш разгона чипа
jk.

Слишком верно, хотя это кажется более конкретным на уровне машинных инструкций.
Мэтью Флинн

1

Я думаю, что понимаю ваши чувства по этому поводу, и я думаю, что у меня похожее мнение.

Я работал с Java-разработчиками, которые превращают 50-строчный класс кода в 3 класса и 3 интерфейса, потому что это легко понять. И я не мог этого вынести.

Это было очень трудно понять, почти невозможно отладить, и никогда не требовалось «переключать реализацию».

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

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

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


1

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

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

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


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


0

Во многих случаях вам просто не нужно знать, как все реализовано. Я почти гарантирую, что вы будете писать такой код people.Where(p => p.Surname == "Smith")много раз в день, но вряд ли когда-нибудь задумаетесь: «Как этот Where()метод на самом деле работает?». Вам просто все равно - вы знаете, что этот метод есть и что он дает вам результаты, которые вы хотите. Почему тебя волнует, как это работает?

Это точно так же для любого внутреннего программного обеспечения; просто потому, что это не написано Oracle, Microsoft и т. д., не означает, что вам нужно искать, как это реализовано. Вы можете разумно ожидать, что вызванный метод GetAllPeopleWithSurname(string name)вернет вам список людей, которые имеют эту фамилию. Он может перебирать список, он может использовать словарь, он может сделать что-то совершенно безумное, но вам просто все равно .

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

Абстракция, если все сделано правильно, замечательна, потому что она позволяет вам отфильтровывать все то, что бесполезно, когда вам придется читать его позже. Не забывайте, что на чтение кода тратится гораздо больше времени, чем на его написание, поэтому основной упор должен делаться на том, чтобы сделать эту задачу максимально простой. Вы также можете подумать, что абстракция означает иерархию объектов длиной до вашей руки, но это может быть так же просто, как рефакторинг метода из 100 строк в 10 методов, каждый из которых состоит из 10 строк. Итак, то, что когда-то было 10 шагов вместе, теперь это 10 отдельных шагов, что позволяет вам идти прямо туда, где скрывается эта надоедливая ошибка.


Эх, но допустим, что вы тот, кто поддерживает реализацию. Я имею в виду, что кто-то заботится о реализации, а этот человек - ты. Вы также являетесь пользователем реализации ... Изменения бизнес-требований (способами, которые вы не можете предсказать) приводят к изменениям, которые находятся на многих уровнях. Я предполагаю, что моя точка зрения заключается в том, что ошибка - не единственное исключение из этого правила.
user606723

ПроблемаPeopleFactory.People.Strategy.MakePeople.(CoutryLaw.NameRegistry.NameMaker.Make()) as People.Female
кодер

@ user606723 Вам не нужно постоянно заботиться о каждой строке кода в вашей кодовой базе. Если в этой реализации есть ошибка или она помечена как нуждающаяся в переписывании (потому что она медленная, плохо написана или что-то в этом роде), и вы переписываете ее, то вы заботитесь об этом. В противном случае, это должно быть в стороне. Возможно, ваша проблема в том, что вы все время пытаетесь владеть всем кодом. Вы должны просто сосредоточиться на коде, над которым вы работаете в определенное время, по моему мнению.
Стюарт Лейланд-Коул

@ Кодер Очевидно, что это довольно экстремальная форма абстракции! Сначала я подумал, что против этого ОП противостоит, но прочитав остальные их ответы, кажется, что они считают всю абстракцию плохой, плохой. Вот почему я попытался объяснить различные уровни абстракции в своем ответе.
Стюарт Лейланд-Коул

0

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

Эти идеи выражаются через три основных закона в архитектуре программного обеспечения:

Закон Саймона: «Иерархии уменьшают сложность». (Иерархии вводят абстракцию)

Закон Парны: «Только то, что скрыто, можно изменить без риска».

Закон Константина: надежные программы нуждаются в слабой связи и высокой когезии


«Иерархии уменьшают сложность». - не обязательно правда.
Кодер

Никакая методология проектирования не является детерминированной. Этот закон не исходит от IT / CS, он сформулирован в гораздо более широком смысле, и на него ссылаются математики, физики и т. Д. Это действительный принцип, но никто не может помешать вам создать бессмысленные иерархии.
ins0m

0

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

Когда я обслуживал большое и сложное приложение для здравоохранения, ты мне просто нравился, я ненавидел все абстракции там. Выяснить, куда идет весь код, была боль в шее. От прыжков по разным классам у меня кружилась голова. Поэтому я сказал себе: «Абстракция - отстой, я минимизирую абстракцию, когда создаю вещи».

Затем пришло время разработать проект приложения (относительно небольшой компонент веб-службы) с нуля. Вспоминая всю боль, у меня был довольно плоский дизайн компонента. Проблема заключалась в том, что, когда требования менялись, мне приходилось вносить изменения во многих разных местах (требования были довольно изменчивы, и я ничего не мог с этим поделать). Это было так плохо, я просто отбросил свой первоначальный дизайн и перепроектировал абстракцию, и все стало лучше - мне не нужно было вносить изменения во многих местах, когда требования изменились.

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

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

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


0

Как уже говорили другие, «скрытие деталей» за абстракцией позволяет изменять их, не затрагивая пользователей. Эта идея взята из «Парнаса о критериях, используемых для декомпозиции систем в модули» (1972) и связана с идеей абстрактных типов данных (ADT) и объектно-ориентированного программирования.

Примерно в то же время, реляционная модель данных Codd для крупных совместно используемых банков данных (1970) была мотивирована (см. Реферат и вступление) желанием изменить представление баз данных во внутренней памяти, не затрагивая пользователей базы данных. Он видел, как программисты регулярно занимали дни, модифицируя страницы кода, чтобы справиться с незначительными изменениями памяти.

Тем не менее, абстракция не очень полезна, если вам нужно увидеть, что внутри нее, чтобы иметь возможность ее использовать. Это может быть очень сложно спроектировать хорошо. Примером хорошей абстракции является дополнение - когда в последний раз вам приходилось думать о том, что происходит внутри? (но иногда вы делаете, например, для переполнения).

Основная проблема (IMHO) заключается в том, что для правильного проектирования модулей (в смысле Парнаса) вам необходимо предсказать, что изменится, а что нет. Прогнозировать будущее сложно, но если у вас есть большой опыт работы с чем-то, и вы это ясно понимаете, то вы можете сделать довольно хорошую работу по прогнозированию. И, следовательно, вы можете разработать модуль (абстракцию), который работает хорошо.

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

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


0

Абстракции в основном в интересах их потребителей (например, программистов приложений). Системные (дизайнерские) программисты имеют больше работы, чтобы сделать их красивыми и полезными, поэтому новички обычно не делают хороший дизайн.

Может быть, вам не нравятся абстракции, потому что они всегда добавляют сложности? Может быть, системы, над которыми вы работали, имели абстракционит (чрезмерное использование абстракций)? Они не панацея.

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

Вы можете практически измерить возврат инвестиций в абстракции, показав, что они со временем «сгибались» в одном или обоих из этих направлений: относительно безболезненные изменения реализации и дополнительные новые клиенты.

Например: используя абстракцию класса Socket в Java, я уверен, что мой код приложения из Java 1.2 все еще работает нормально под Java 7 (хотя они могут иметь некоторые изменения производительности). Начиная с Java 1.2 определенно появилось много новых клиентов, которые тоже использовали эту абстракцию.

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

Что касается прозрачности, в нисходящей стратегии дизайна полная прозрачность делает плохой дизайн. Умные программисты стремятся извлечь максимальную пользу из информации, которую они имеют в своем распоряжении, и тогда система становится тесно связанной. Наименьшее изменение детализации (например, изменение порядка байтов в структуре данных) в модуле может нарушить некоторый код где-то еще, потому что умный программист использовал эту информацию, чтобы сделать что-то полезное. Дэвид Парнас указал на эту проблему в статьях 1971 года, в которых он предлагал скрывать информацию в проектах.

Ваша ссылка на ArchLinux имеет смысл для меня, если вы рассматриваете «внутреннюю часть» операционной системы как сложную реализацию абстракции, которая является ОС для приложений, которые на ней работают. Сохраняйте это простым в духе абстракции.


0

Я отвечу на ваш вопрос вопросом; когда вы ехали на работу этим утром (я предполагаю, что вы действительно это сделали), вас не заботило, как именно двигатель открыл клапаны для впуска топливовоздушных смесей, а затем зажег их? Нет. Вам все равно, как работает двигатель вашего автомобиля, когда вы едете по дороге. Вы все равно , что она делает работу.

Предположим, однажды ваша машина не работает. Не запускается, бросает удочку, разрывает ремень, необъяснимым образом врезается в этот бетонный барьер не по своей вине, пока вы были заняты текстовыми сообщениями. Теперь вам нужна новая машина (хотя бы временно). Тебя не волнует, как именно работает эта новая машина? Нет. То, что вас волнует, во-первых, это то, что он работает, и, во-вторых, вы можете использовать те же знания и навыки, которые вы использовали для управления своей старой машиной, чтобы ездить на новой. В идеале вам должно показаться, что в автомобиле, который вы ведете, не произошло никаких изменений. Реально то, как работает этот новый автомобиль, должно преподнести вам как можно меньше «сюрпризов».

Эти основные принципы являются основным принципом инкапсуляции и абстракции. Знание того, как объект делает то, что он делает, не должно быть обязательным условием его использования, чтобы делать то, что он делает. Даже в компьютерном программировании детали электрических путей в процессоре, на котором выполняется ваша программа, абстрагированы как минимум за полдюжины слоев инструкций ввода-вывода, драйверов, программного обеспечения ОС и среды выполнения. Многие очень успешные разработчики программного обеспечения пишут совершенно хороший код, не беспокоясь о точной аппаратной архитектуре или даже сборке ОС, которая его запустит. Включая меня.

Инкапсуляция / сокрытие информации позволяет менталитету «не заботиться о том, как это происходит, просто заботиться о том, что он делает» Ваш объект должен раскрывать то, что полезно для потребителя, таким образом, чтобы потребитель мог легко потреблять. Теперь, возвращаясь в реальный мир, это не означает, что автомобиль не должен предоставлять пользователю никакой информации о внутренней работе, или что автомобиль должен предоставлять пользователю только самые базовые функции, такие как зажигание, рулевое колесо, и педали. Все автомобили имеют спидометры и указатели уровня топлива, тахометры, идиотские фонари и другие отзывы. Практически все автомобили также имеют переключатели для различных независимых подсистем, таких как фары, сигналы поворота, радио, регулировка сиденья и т. Д. Некоторые автомобили допускают довольно эзотерический ввод пользователя, например чувствительность межосевого дифференциала с ограниченным проскальзыванием. Во всех случаях, если вы знаете достаточно, Вы можете открыть его и изменить вещи, чтобы заставить его работать немного по-другому. Но в большинстве случаев, может быть, просто возможно, пользователь не должен иметь возможность напрямую и независимо управлять топливными насосами из салона? Может быть, просто может быть, пользователь не сможет активировать свои стоп-сигналы, не нажимая педаль тормоза?

Абстракция допускает менталитет «это не то же самое, но, поскольку они оба XI, я могу использовать их так же, как и любой другой X». Если ваш объект наследует или реализует абстракцию, ваши потребители должны ожидать, что ваша реализация даст тот же или аналогичный результат, что и другие известные реализации абстракции. Toyota Camry и Ford Fusion - оба "автомобили". Как таковые, они имеют общий набор ожидаемых функций, таких как рулевое колесо. Поверните его против часовой стрелки, машина едет налево. Поверните его по часовой стрелке, машина едет направо. Вы можете сесть в любой автомобиль в Соединенных Штатах и ​​ожидать, что у автомобиля будет рулевое колесо и как минимум две педали, одна из которых справа - педаль «машина едет», а другая в центре - педаль «машина останавливается» ,

Следствием абстракции является «теория наименьшего удивления». Если вы садитесь за руль новой машины для тест-драйва, поворачиваете рулевое колесо по часовой стрелке и машина поворачивает влево, вы будете удивлены, если не сказать больше. Вы обвинили бы дилера в продаже POS и вряд ли выслушали бы его причины, почему новое поведение «лучше», чем вы привыкли, или насколько хорошо это поведение «задокументировано» или как » прозрачная »система управления. Несмотря на то, что этот новый автомобиль и все остальные, которыми вы управляли, по-прежнему являются «автомобилями», при управлении этим автомобилем вы должны изменить некоторые фундаментальные представления о том, как предполагается управлять автомобилем, чтобы успешно управлять новым автомобилем. Это обычно плохо, и это происходит только тогда, когда в новой парадигме есть интуитивное преимущество. Возможно, добавление ремней безопасности является хорошим примером; 50 лет назад вы только что вошли и ушли, но теперь вам нужно пристегнуться, интуитивное преимущество в том, что вы не проходите через ветровое стекло или пассажирское сиденье, если попадаете в аварию. Даже тогда водители сопротивлялись; многие автовладельцы вырезают ремни безопасности из машины, пока не будут приняты законы, обязывающие их использовать.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.