Как определить, что код более абстрагирован?

Какими должны быть меры, которые следует использовать для определения того, что код более абстрагирован и очень трудно понять, и что нужно сделать для сокращения абстракции?

Ответ 1

"Простота в отношении сложности, сложности над сложностью"

Итак - есть возможность отвлечь что-то только в том случае, если вы "уклоняетесь" от сложности сложности. Причины этого могут различаться: улучшенная модульность, лучшая инкапсуляция и т.д.

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

Если вы ищете инструмент, который мог бы сделать это на вашем месте - больше не смотрите, только разум может надежно судить об этом.

Ответ 2

Я дам ответ, который получит много голосов!

Если код написан на языке OO, он обязательно сильно перечеркивается. Чем чище язык, тем хуже проблема.

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

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

Некоторые слабые тесты для чрезмерной абстракции: если структура данных является типом продукта (struct in C), и программист написал метод get и set для каждого поля, они полностью не смогли обеспечить какую-либо реальную абстракцию, отключенные операторы, такие как C, для цели и просто не понимал, что имена полей структуры уже являются абстрактным представлением продукта. Дублирование и поддержка интерфейса - это не очень хорошая идея.

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

Чтобы исправить код, я рекомендую следующие шаги:

  • Документируйте инварианты представления, которые абстракция поддерживает

  • Удалите абстракцию (методы), если вы не можете найти сильные инварианты

  • Перепишите код, используя метод прямого доступа к данным.

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

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

Ответ 3

Загрузите Magento и посмотрите код, прочитайте некоторые документы на нем и посмотрите их ERD: http://www.magentocommerce.com/wiki/_media/doc/magento---sample_database_diagram.png?cache=cache

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

Ответ 4

Лично я бы сказал, что "Каков идеальный уровень абстракции?" является субъективным вопросом.

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

Мне нравится использование рекурсивных функций, но я не ценю рекурсию только ради рекурсии.

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

Это вопрос личного мнения, а также здравого смысла. Отвечает ли это на ваш вопрос?

Ответ 5

Я полностью согласен с тем, что написал @ArnisLapsa:

"Simplicity over complexity, complexity over complicatedness"

И это

an abstraction is used to "de-level" those, from complicated to complex

(и от сложного к простому)

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

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

  • Для людей, которых это касается, абстракция должна быть концептуально проще, чем другие альтернативы, не глядя на реализацию. Если вы обнаружите, что думать обо всех возможных случаях проще, чем рассуждать с использованием абстракции, то эта абстракция не подходит (для вас)
  • Его реализация должна основываться только на абстракции, а не на конкретных случаях, для которых она будет использоваться. Как только в реализации абстракции есть части, созданные для конкретных случаев, это указывает на "непригодную" абстракцию. И усиление обобщения, чтобы справиться с каждым новым случаем, идет неправильным путем (и имеет тенденцию падать к следующему вопросу).
  • Очень распространенным показателем чрезмерной абстракции, которую я обнаружил (и на самом деле понизил), являются абстракции, которые представляют больше, чем нужно сейчас. Насколько это возможно, они должны позволять делать именно то, что требуется, но не более того. Например, предположим, что вы думаете или уже имеете абстракцию "2d point", для которой вы можете определить множество необходимых вам операторов. Тогда у вас есть еще одна потребность, которая действительно может быть "точкой 4d", аналогичной 2d. Не начинайте использовать абстракцию "Ndimensionnal point", особенно думая, что она вам может понадобиться позже. Возможно, у вас никогда не будет ничего, кроме 2 и 4d (потому что это остается "хорошей идеей" в отставании навсегда), но вместо этого появляются некоторые требования для преобразования 4d точек в пары 2d точек. Это будет трудно обобщить в n-измерениях. Таким образом, каждая абстракция может быть проверена, чтобы покрыть и покрыть только фактические потребности. В моем конкретном примере сложность "n-мерная" на самом деле используется только для того, чтобы справиться со 2-м и 4-м случаями (а 4-й может даже не использоваться так много).
  • Наконец, с более глобальной точки зрения, кодовая база, которая имеет много не связанных абстракций, является индикатором того, что команда разработчиков стремится абстрагироваться от каждой маленькой проблемы. Так что, вероятно, многие из них являются или стали слишком отвлеченными.