| OberonCore https://forum.oberoncore.ru/ |
|
| Статья "Клиника плохого кода" https://forum.oberoncore.ru/viewtopic.php?f=57&t=4931 |
Страница 1 из 1 |
| Автор: | Илья Ермаков [ Пятница, 10 Январь, 2014 14:08 ] |
| Заголовок сообщения: | Статья "Клиника плохого кода" |
http://web.archive.org/web/200906180318 ... dcode.html Начинается с потрясной реальной истории о том, как из примитивной задачи могут раздуть десятки тысяч строк кода. В середине немного воды, которую может быть скучновато читать, может показаться спорным сравнение с шахматами (типа, "перебор вариантов"). Но, в конечном счёте, если подумать, сходство в анализе ситуации есть - а дальше совершенно правильный вывод, что избежать взрыва вариантов можно только дисциплиной проектирования. Цитата: Лечение: локализация и минимизация
... Лечение: архитектура Кто-то из математиков сказал: если имеется нерешаемая задача, сначала ее надо разбить на подзадачи, решение которых известно. Это есть сущность арихитектуры: для того, чтобы система оставалась управляемой и maintainable для разработчика, ее следует разбить на части и определить интерфейсы и протоколы взаимодействия этих частей. В теории часто говорят о модульности, однако по какой-то непонятной причине наиболее модульные языки, как Паскаль и Ада, постепенно вышли из моды. А ведь они прививали дисциплину стройной древовидной модульности и дисциплину мышления в терминах интерфейс-реализация. Оглядываясь назад, могу сказать, что практика программирования на Turbo Pascal и Delphi заменила мне чтение всевозможных умных книжек по архитекруре. (Ах, да, пресловутые begin...end вместо фигурных скобок - вот что потопило эти замечательные языки.) Но былого не вернешь, и сегодня большинство пишут либо на Си++, где нет понятия модуля, либо на Java/C#, где есть некое подобие модулей, но нет деления на интерфейс и реализацию, хотя бы даже как в Си++. И куда катится этот мир? Полагаю, катится он в сторону какого-то хорошего нового языка, с хорошей модульностью, с лямбда-исчислением и ООП одновременно, и прочими крутыми штуками, - языка, которого пока еще нет. То, что большинство разработчиков и архитекторов (никогда не понимал смысл этой специальности - человек, который не кодирует, но указывает как это надо делать) чаще всего упускают из виду, это следующая важная мысль: функции, особенно часто используемые, становятся частью языка программирования, и следовательно к их дизайну следует подходить примерно с такой же серьезностью, как к дизайну языка. Когда мы излагаем мысль на человеческом языке, мы по сути мыслим понятиями этого языка; аналогично, писать программу на алгоритмическом языке с использованием какого-то набора функций означает излагать мысль на этом формальном языке. Когда мы предлагаем другим разработчикам нашу библиотеку, мы навязываем им некий набор понятий и образ мышления. В реальности же у большинства разработчиков цикл создания библиотеки примерной такой: реализуется какая-то функциональность, и "наружу" выдается набор точек доступа к этой функциональности. При этом считается хорошим тоном выдать наружу как можно больше возможностей на все случаи жизни. Итак, главная дилемма архитектуры - это должны ли интерфейсы каждого модуля быть всеобъемлющими, или наоборот, они должны экономить понятия и давать минимальный набор гибких средств? Если спросить пользователей библиотек, они проголосуют за второе, но - парадокс! - перелезая в шкуру разработчика библиотеки, нам начинает казаться, что "правильнее" первое. Есть о чем подумать, не правда ли? Я вам собираюсь показать, как несколькими легкими движениями можно сильно сократить или даже и вовсе избавиться от довольно громоздкого программного интерфейса. Возьмем Windows Registry. Его предназначение - хранить дерево каких-то числовых и строковых значений, предположительно для хранения конфигурации приложений и самой системы. Эта функциональность описана в виде интерфейса с 41 функциями (!), примерно от 3 до 7 аргументов каждая, плюс какие-то структуры, и как водится, куча констант. ... Какие на самом деле функции нужны для работы с деревом значений? ... И тогда интерфейс работы с Registry сведется к следующим четырем глаголам: create, write, read, delete Но у меня есть еще такая домашняя заготовка, которой мы нанесем Windows Registry удар ниже пояса. Мы решим задачу хранения конфигурационных данных в юниксоидном стиле. Представьте себе, что вы установили в своей UNIX-системе некий продукт под названием UNIX Registry. Вы сразу открываете документацию, чтоб понять как с этим делом работать, и ожидая сотни страниц умного текста, обнаруживаете следующий параграф: Здравствуйте, я ваш путеводитель по UNIX Registry. UR - это специальная файловая система, предназначенная для эффективной работы с очень маленькими файлами. Приложения могут использовать UR для хранения своих конфигурационных данных в виде дерева значений. По соглашению, эта файловая система маунтируется под /var/reg. Каждое приложение создает свое поддерево (напр. /var/reg/xcalendar), в котором рекомендуется также создать отдельные поддеревья для каждого пользователя. Права доступа регулируются как обычно; естественно, в директориях UR вы можете использовать все стандартные файловые утилиты, например find. Для удобства программирования, флаг "x" на файле в UR означает, что файл может хранить только числовое значение. Приятного отдыха. Вот и всё. Всё! Позволю себе дать еще три кратких совета по архитектуре и протоколам: во-первых, используйте технологии Интернета насколько это возможно, например для обмена данными - протокол HTTP. Это дает такую солидную кучу преимуществ, что для их описания понадобилась бы отдельная глава. Попробуйте сами, выберите правильный инструментарий, и поймете о чем речь. В конце концов, не зря технологии Интернета уже победили все остальные технологии. Во-вторых, избегайте XML где возможно решить задачу более простыми текстовыми форматами в юниксоидном стиле. XML is a pain in the ass. Реально, он едва ли что-то упрощает в нашей жизни. Впрочем, может вам как раз надо усложнить? В-третьих, для решения задачи выберите такой язык и такие библиотеки, чтобы основной код состоял исключительно из логики решения этой задачи, и ничего лишнего. Другими словами, никакого метапрограммирования, когда, например, приходится буквально нянчиться с COM/DCOM или же описывать крутые Си++ шаблоны, о которые сам черт ногу сломает. Нужно ли оно вам? Словом, выбирайте такие интерфейсы и протоколы, чтобы пришлось меньше писать кода и зависеть от меньшего количества внешних компонент. Какая простая и очевидная мысль, и как часто мы выбираем в точности противоположную стратегию! ... |
|
| Автор: | Alexey Veselovsky [ Пятница, 10 Январь, 2014 14:30 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Цитата: Но былого не вернешь, и сегодня большинство пишут либо на Си++, где нет понятия модуля, либо на Java/C#, где есть некое подобие модулей, но нет деления на интерфейс и реализацию, хотя бы даже как в Си++. Либо пишут на Обероне или КП, на котором также нет деления на интерфейс и реализацию модуля, увы. (автогенерация оного интерфейса не считается - это и для java/c# есть, и это совершенно, абсолютно не то что нужно) |
|
| Автор: | Иван Кузьмицкий [ Пятница, 10 Январь, 2014 14:37 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Alexey Veselovsky писал(а): Либо пишут на Обероне или КП, на котором также нет деления на интерфейс и реализацию модуля, увы. (автогенерация оного интерфейса не считается - это и для java/c# есть, и это совершенно, абсолютно не то что нужно) Если считать деление на интерфейс и реализацию тем, чем оно и является, то - есть. Интерфейсом пользуются внешние компоненты, реализация недоступна извне.
|
|
| Автор: | Madzi [ Пятница, 10 Январь, 2014 14:39 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
У Java есть полноценные интерфейсы. |
|
| Автор: | Alexey Veselovsky [ Пятница, 10 Январь, 2014 20:13 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Иван Кузьмицкий писал(а): Alexey Veselovsky писал(а): Либо пишут на Обероне или КП, на котором также нет деления на интерфейс и реализацию модуля, увы. (автогенерация оного интерфейса не считается - это и для java/c# есть, и это совершенно, абсолютно не то что нужно) Если считать деление на интерфейс и реализацию тем, чем оно и является, то - есть. Интерфейсом пользуются внешние компоненты, реализация недоступна извне.Я уже много на эту тему писал, так что ввязываться в дискуссию не буду. Просто повторю еще раз - в некоторых случаях (например в случаях небольших программ) действительно удобней писать сразу реализацию модуля, а затем по нему генерить спецификацию. Это один юзкейс. Но довольно часто бывает, что первична спецификация пакета, а его реализация вторична. Так что руками пишется в первую очередь именно спецификация, а реализация может быть даже сгенерирована автоматом (набор заглушек). Эдакие specification driven development. При групповой разработке это бывает оправдано. Я наверно примерно поровну писал на языках где спецификация и реализация разделена, и где не разделена (или спецификация генерируется по реализации), и да, действительно если писать в одиночку и небольшие программы, то в среднем удобней когда отдельной рукописной спецификации на пакет/модуль нет - банально меньше писанины. Но когда людей в проекте чуть больше, и проект сам больше, то рукописная спека (не дока, а именно спека - её понимает компилятор и на этапе компиляции проверяет соответствие реализации и спецификации) становится просто очень удобной. Поэтому например подавляющее большинство шаблонного кода в С++ мне читать не удобно - там спеку и реализацию не разделяют (хотя это возможно сделать). Да и разрабатывать в таком стиле не удобно. Та же беда с java/Go/python/js и так далее. КП с Обероном тут не одиноки. А вот Модула (и 2 и 3) и Ада - реально хороши. |
|
| Автор: | Alexey Veselovsky [ Пятница, 10 Январь, 2014 20:14 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Madzi писал(а): У Java есть полноценные интерфейсы. Это не те интерфейсы. |
|
| Автор: | Madzi [ Пятница, 10 Январь, 2014 20:39 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Alexey Veselovsky писал(а): Madzi писал(а): У Java есть полноценные интерфейсы. Это не те интерфейсы. Ну почему же не те: Код: public interface IScanner { /** * Получение очередного токена. * * @return токен */ Token getToken(); /** * Сброс сканера в исходное состояние */ void reset(); } А дальше используем в коде Код: public class Parser { private IScanner scanner; ... scanner.reset(); ... Token token = scanner.getToken(); ... } При этом можем иметь одну или несколько реализаций, которые пишем сами, либо кто-то пишет по указанному выше интерфейсу. И эти реализации можно при желании менять на лету. |
|
| Автор: | Alexey Veselovsky [ Пятница, 10 Январь, 2014 20:41 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Да, кстати, это была одна из причин почему я отказался от использования D. Да еще и в плюсах некоторые энтузиасты из clang хотят сделать нечто подобное, вместо нормальной модульности. Вообще это смахивает на банальную восторженную недальновидность компиляторщиков - мы теперь МОЖЕМ сделать модули без руками писанной спецификации, значит таким им и быть! Компилятору спеки больше не нужны! А то, что они (рукописные спеки) нужны в первую очередь программисту - их волнует мало. Ведь это ж фича! СМОГЛИ! Тьху! |
|
| Автор: | Alexey Veselovsky [ Пятница, 10 Январь, 2014 20:43 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Madzi писал(а): Alexey Veselovsky писал(а): Madzi писал(а): У Java есть полноценные интерфейсы. Это не те интерфейсы. Ну почему же не те: Код: public interface IScanner { /** * Получение очередного токена. * * @return токен */ Token getToken(); /** * Сброс сканера в исходное состояние */ void reset(); } А дальше используем в коде Код: public class Parser { private IScanner scanner; ... scanner.reset(); ... Token token = scanner.getToken(); ... } При этом можем иметь одну или несколько реализаций, которые пишем сами, либо кто-то пишет по указанному выше интерфейсу. И эти реализации можно при желании менять на лету. Во первых да, это минус - то, что их можно менять на лету (точнее - что нельзя запретить и дать гарантии что на лету их никто не подменит) |
|
| Автор: | Madzi [ Пятница, 10 Январь, 2014 21:35 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Первый вопрос решаем. Хотя не вижу особых проблем, если модуль соответствует интерфейсу. Второй момент спорный. Во-первых, можно экспортировать константы. Во-вторых, нужно ли давать доступ к переменным модуля напрямую? Это ведь можно сделать через гетер/сестер. |
|
| Автор: | Иван Кузьмицкий [ Пятница, 10 Январь, 2014 21:46 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Alexey Veselovsky писал(а): Я уже много на эту тему писал, так что ввязываться в дискуссию не буду. Просто повторю еще раз - в некоторых случаях (например в случаях небольших программ) действительно удобней писать сразу реализацию модуля, а затем по нему генерить спецификацию. Это один юзкейс. Я прекрасно понимаю о чём речь, я сам как-то писал на Модуле. Считаю, что, во-первых, не стоит "авторитетно" утверждать вещи, которые во многом субъективны (удобно-неудобно относится в первую очередь к принятому в конторе developing style).Во-вторых, считаю, что выражаться стоит аккуратнее, а не в стиле "В обероне\КП нет того и этого", потому что прочесть можно двояко. Ну, это я больше про мимоходящих, которых сбивает с толку очередной гуру А всякие технические моменты читать и обновлять в памяти интересно, да. Так что умолкаю, извините, что вмешался |
|
| Автор: | Info21 [ Пятница, 10 Январь, 2014 22:51 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Alexey Veselovsky писал(а): Эдакие specification driven development. При групповой разработке это бывает оправдано. Пож., напомните, почему нельзя в качестве интерфейса модуля в таких случаях использовать (предположительно, для передачи коллеге) вариант модуля реализации с пустыми телами процедур etc.
|
|
| Автор: | Jordan [ Воскресенье, 12 Январь, 2014 17:38 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Статья интересная. Особенно понравился пример с реестром. Цитата: Все что должна была делать эта программка - это копировать файлы с одной Windows-машины на другую. Эта задача была решена в 80,000 строк кода на Си++ (функциональная часть) и в 55,000 строк кода на VB (GUI часть). Всё это переписали в 10 строк кода. Всё же не верю, что такое возможно. Или по мимо копирования нужно ещё, что то делать, к примеру организовать визуальное представление и оперирование файлами. Но почему гуи занимает 55 тысяч. Если поразмышлять, что могло быть написано в остальных 80 тысяч строк? Разруливание прав доступа в windows. Как я вижу задачу, пишется функция с прототипом. FileSend(куда, что, откуда передаём файл) Плюс гуи для удобства. Выбрать файл. Я понимаю, что я намеренно упрощаю. Но разговор идёт о 135 тысяч строк бессмысленного кода. |
|
| Автор: | Alexey Veselovsky [ Воскресенье, 12 Январь, 2014 17:59 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Jordan писал(а): Статья интересная. Особенно понравился пример с реестром. Цитата: Все что должна была делать эта программка - это копировать файлы с одной Windows-машины на другую. Эта задача была решена в 80,000 строк кода на Си++ (функциональная часть) и в 55,000 строк кода на VB (GUI часть). Всё это переписали в 10 строк кода. Всё же не верю, что такое возможно. Или по мимо копирования нужно ещё, что то делать, к примеру организовать визуальное представление и оперирование файлами. Но почему гуи занимает 55 тысяч. Если поразмышлять, что могло быть написано в остальных 80 тысяч строк? Разруливание прав доступа в windows. Как я вижу задачу, пишется функция с прототипом. FileSend(куда, что, откуда передаём файл) Плюс гуи для удобства. Выбрать файл. Я понимаю, что я намеренно упрощаю. Но разговор идёт о 135 тысяч строк бессмысленного кода. Ну представь себе, что ты хочешь абстрагироваться от хост-системы. Поэтому ты пишешь мегалибу-фреймворк, которая абстрагирует конкретные механизмы низлежащей ОСи и твоя программа становится, таким образом, кроссплатформенной. А потом ты реализуешь аж целые 10 строк кода уже конкретной задачи. Ну, грубо говоря, чтобы реализовать подобное на КП мы вначале пишем компилятор КП, пишем ББ, а затем реализуем нужную прикладную задачу. Суммарно получится явно больше 10 строк кода. Это один из вариантов когда раздувают код. То есть мелкая контора/конкретный программист вместо того чтобы решать прикладные задачи начинает лепить фреймворки да мегалибы которые, когда-нибудь, возможно, позволят сделать что-то такое, что прям ух! Кстати подобным страдают абсолютно все, вне зависимости от применяемого ЯП. Ну, разве что не страдают те, кто совсем уж на DSL пишут - они просто не могут на этом мегалибу/мегафреймворк сделать, ибо язык то узкоспециализированный и выпрыгнуть из своей песочницы никак не может. |
|
| Автор: | Comdiv [ Понедельник, 13 Январь, 2014 12:01 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Alexey Veselovsky писал(а): Цитата: Но былого не вернешь, и сегодня большинство пишут либо на Си++, где нет понятия модуля, либо на Java/C#, где есть некое подобие модулей, но нет деления на интерфейс и реализацию, хотя бы даже как в Си++. Либо пишут на Обероне или КП, на котором также нет деления на интерфейс и реализацию модуля, увы. (автогенерация оного интерфейса не считается - это и для java/c# есть, и это совершенно, абсолютно не то что нужно) И это правильно, в самом языке синтаксического разделения нет, но его можно сделать небольшим расширением для тех проектов компиляторов, авторы которых посчитают это нужным, никак при этом не задев основной язык. |
|
| Автор: | Иван Кузьмицкий [ Понедельник, 13 Январь, 2014 12:38 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Alexey Veselovsky писал(а): Это один из вариантов когда раздувают код. То есть мелкая контора/конкретный программист вместо того чтобы решать прикладные задачи начинает лепить фреймворки да мегалибы которые, когда-нибудь, возможно, позволят сделать что-то такое, что прям ух! Легко узнаваемая форма абсолютного всемогуторства, присущего многим программистам Alexey Veselovsky писал(а): Кстати подобным страдают абсолютно все, вне зависимости от применяемого ЯП. Ну, разве что не страдают те, кто совсем уж на DSL пишут ... Ну вот, да, а DSL уже опираются на готовые элементы онтологической инфраструктуры.
|
|
| Автор: | Alexey Veselovsky [ Понедельник, 13 Январь, 2014 13:26 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Иван Кузьмицкий писал(а): Alexey Veselovsky писал(а): Это один из вариантов когда раздувают код. То есть мелкая контора/конкретный программист вместо того чтобы решать прикладные задачи начинает лепить фреймворки да мегалибы которые, когда-нибудь, возможно, позволят сделать что-то такое, что прям ух! Легко узнаваемая форма абсолютного всемогуторства, присущего многим программистам Самое смешное, что бывает так (но это конечно не про данный пример из статьи), что предметная область сложная, там копать и копать, и нужно таки сильно вложиться в проект в интеллектуальном плане. И хорошо замотивированный программист таки вкладывается по полной. Но не в предметную область, а в ту область к которой он привык и в которой у него получается, идет по накатанной дорожке. Обычно начинает архитектуру паттернить. Ну то есть еще даже алгоритма нет (и не известно будет ли!) который будет решать задачу (скажем какую-нибудь задачу по компьютерному зрению), предметка не изучена и по сути задача не поставлена, но зато кода уже написано... МНОГО. Ибо архитектура, паттерны! Одна из форм прокрастинации, полагаю. |
|
| Автор: | Рыжий [ Четверг, 23 Январь, 2014 01:04 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
А мне не понравилось. Пример: объект GET в Clipper-e имеет два "интерфейса" настолько отличные друг от друга по механизмам использования и ..микроскопичности..., что пропадает желание рассуждать на эту тему. Один из "интерфейсов" вполне может служить "реализацией" другого, у одного и того же объекта. Так можно легко дойти до маразма. |
|
| Автор: | Рыжий [ Четверг, 23 Январь, 2014 01:45 ] |
| Заголовок сообщения: | Re: Статья "Клиника плохого кода" |
Jordan писал(а): Всё это переписали в 10 строк кода. Всё же не верю, что такое возможно. В две строчки можно: Цитата: net use ..... xcopy %1 %2 /Y Чистое отделение интерфейса от реализации. Батник вызывай чем хочешь. Правда там есть одна маленькая тонкость, но то все лажа. |
|
| Страница 1 из 1 | Часовой пояс: UTC + 3 часа |
| Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |
|