Вы определили действительный компромисс
Таким образом, здесь действительно есть компромисс, и он присущ абстракции в целом. Всякий раз, когда кто-то пытается вставить N строк кода в свою собственную функцию, чтобы назвать его и изолировать, он одновременно облегчает чтение вызывающего сайта (ссылаясь на имя, а не на все кровавые подробности, лежащие в основе этого имени), и более сложный (теперь у вас есть смысл, который запутан в двух разных частях кодовой базы). «Легкий» - это противоположность «сложному», но это не синоним «простого», который противоположен «сложному». Они не являются противоположностями, и абстракция всегда увеличивает сложность, чтобы вставить ту или иную форму легкости.
Мы можем увидеть дополнительную сложность непосредственно, когда некоторые изменения в бизнес-требованиях заставляют абстракцию начинать течь. Возможно, какая-то новая логика была бы наиболее естественной в середине предварительно абстрагированного кода, скажем, например, если абстрагированный код пересекает какое-то дерево, и вы действительно хотели бы собирать (и, возможно, действовать) некоторую информацию, пока вы пересекая дерево. Между тем, если вы абстрагировали этот код, тогда могут быть другие сайты вызовов, и добавление необходимой логики в середину метода может нарушить эти другие сайты вызовов. Видите, всякий раз, когда мы меняем строку кода, нам нужно только смотреть на непосредственный контекст этой строки кода; когда мы меняем метод, мы должны Cmd-F весь наш исходный код искать что-то, что может сломаться в результате изменения контракта этого метода,
В этих случаях жадный алгоритм может потерпеть неудачу
Сложность также сделала код в определенном смысле менее читабельным, чем более, В предыдущей работе я имел дело с HTTP API, который был очень аккуратно и точно структурирован в несколько уровней, каждая конечная точка определяется контроллером, который проверяет форму входящего сообщения, а затем передает его какому-то менеджеру «уровня бизнес-логики» , который затем сделал некоторый запрос некоторого «уровня данных», который отвечал за выполнение нескольких запросов к некоторому уровню «объекта доступа к данным», который отвечал за создание нескольких делегатов SQL, которые фактически ответили бы на ваш вопрос. Первое, что я могу сказать по этому поводу, было то, что примерно 90% кода было шаблоном копирования и вставки, другими словами, это не было никаких операций. Поэтому во многих случаях чтение любого фрагмента кода было очень «легким», потому что «о, этот менеджер просто перенаправляет запрос к этому объекту доступа к данным».много переключения контекста и поиска файлов и попытки отследить информацию, которую вы никогда не должны были отслеживать, "это называется X на этом уровне, он становится называемым X" на этом другом уровне, затем он называется X "на этом другом другой слой. "
Я думаю, что когда я остановился, этот простой CRUD API был на той стадии, когда, если вы напечатали его по 30 строк на страницу, на полке потребовалось бы 10-20 учебников по пятьсот страниц: это была целая энциклопедия повторяющихся код. Что касается существенной сложности, я не уверен, что там была даже половина учебника существенной сложности; у нас было всего 5-6 диаграмм базы данных, чтобы справиться с этим. Внесение в него каких-либо незначительных изменений было гигантским начинанием, изучение того, что это было гигантским начинанием, добавление новых функций стало настолько болезненным, что у нас фактически были шаблоны шаблонных файлов, которые мы будем использовать для добавления новых функций.
Так что я воочию видел, как сделать каждую часть очень читабельной и очевидной может сделать целую очень нечитаемой и неочевидной. Это означает, что жадный алгоритм может потерпеть неудачу. Вы знаете жадный алгоритм, да? «Я собираюсь сделать любой шаг, который локально улучшит ситуацию, и тогда я буду верить, что попал в глобально улучшенную ситуацию». Это часто прекрасная первая попытка, но она может и пропустить в сложных ситуациях. Например, на производстве вы можете попытаться повысить эффективность каждого конкретного шага в сложном производственном процессе - делать большие партии, кричать на людей на полу, которые, похоже, ничего не делают, чтобы чем-то заняться своими руками, - и это часто может разрушить глобальную эффективность системы.
Лучшая практика: используйте СУХОЙ и длины, чтобы сделать звонок
(Примечание. Заголовок этого раздела в некотором роде шутка; я часто говорю своим друзьям, что когда кто-то говорит: «Мы должны сделать X, потому что лучшие практики так говорят », они в 90% случаев не говорят о чем-то вроде внедрения SQL или хеширования пароля. или что-то еще - односторонние лучшие практики - и таким образом утверждение может быть переведено в эти 90% времени на «мы должны сделать X, потому что я так говорю ». Как будто у них может быть какая-то статья в блоге от какого-то бизнеса, который сделал лучшую работу с X, а не с X ', но, как правило, нет гарантии, что ваш бизнес похож на этот бизнес, и, как правило, есть какая-то другая статья из другого бизнеса, которая лучше справилась с X', чем с X. Поэтому, пожалуйста, не берите название слишком шутки в сторону.)
То , что я рекомендовал бы основан на разговоре Джек Дидерих называется Классы Stop Пишущие (youtube.com) . В этом выступлении он сделал несколько важных замечаний: например, вы можете знать, что класс на самом деле является просто функцией, когда у него есть только два открытых метода, и один из них - конструктор / инициализатор. Но в одном случае он говорит о том, что гипотетическая библиотека, которую он заменил строкой для разговора как «Маффин», объявила свой собственный класс «MuffinHash», который был подклассом встроенного dict
типа, который есть в Python. Реализация была совершенно пустой - кто-то только что подумал: «Возможно, нам понадобится добавить пользовательские функции в словари Python позже, давайте на всякий случай представим абстракцию прямо сейчас».
И его вызывающий ответ был просто: «Мы всегда можем сделать это позже, если понадобится».
Я думаю, что мы иногда притворяемся, что в будущем станем программистами хуже, чем сейчас, поэтому мы можем захотеть добавить какую-то мелочь, которая может сделать нас счастливыми в будущем. Мы предвидим будущие потребности нас. «Если трафик будет в 100 раз больше, чем мы думаем, этот подход не будет масштабироваться, поэтому мы должны направить предварительные инвестиции в этот более сложный подход, который будет масштабироваться». Очень подозрительно
Если мы серьезно относимся к этому совету, тогда нам нужно определить, когда наступит «позже». Вероятно, наиболее очевидным было бы установить верхний предел длины вещей по стилевым причинам. И я думаю, что оставшийся лучший совет - использовать DRY - не повторяйте себя - с этими эвристиками длины линий, чтобы исправить дыру в принципах SOLID. Основываясь на эвристике из 30 строк, являющейся «страницей» текста и аналогией с прозой,
- Реорганизовать проверку в функцию / метод, когда вы хотите скопировать и вставить его. Например, иногда есть веские причины для копирования-вставки, но вы всегда должны чувствовать себя грязно. Настоящие авторы не заставляют вас перечитывать большое длинное предложение 50 раз на протяжении всего повествования, если только они действительно не пытаются выделить тему.
- Функция / метод в идеале должна быть «абзацем». Большинство функций должно занимать около половины страницы или 1-15 строк кода, и только 10% ваших функций должны иметь диапазон от полутора страниц до 45 строк или более. Когда вы наберете более 120 строк кода и комментариев, эту вещь нужно разбить на части.
- Файл в идеале должен быть "главой". Большинство файлов должно быть 12 страниц или меньше, так что 360 строк кода и комментариев. Только 10% ваших файлов должны иметь длину до 50 страниц или 1500 строк кода и комментариев.
- В идеале большая часть вашего кода должна иметь отступ базовой линии функции или один уровень глубины. Исходя из некоторой эвристики относительно дерева исходных текстов Linux, если вы не сомневаетесь в этом, только 10% вашего кода должны иметь отступ с 2 уровнями или более в пределах базовой линии, менее 5% с отступом 3 уровня или более. В частности, это означает, что вещи, которые должны «обернуть» некоторые другие проблемы, такие как обработка ошибок в большой попытке / уловке, должны быть извлечены из реальной логики.
Как я уже упоминал, я проверил эти статистические данные по текущему дереву исходных текстов Linux, чтобы найти эти приблизительные проценты, но они также своего рода аргументы в литературной аналогии.