Comments 85
Хороший код… Идеальный код… Совершенный код… Что за бред? Нет таких понятий. Нет не одного общего стандарта «хорошего» кода. И не будет. Потому, что само понятие «хороший» изначально субъективно — для кого-то хорошо, а для кого-то плохо.
Есть «не верный» код («говнокод»), где неправильная семантика, где не очевидные ходы, где не оптимальные решения и прочие ошибки. У берите все эти ошибки и получите «правильный» код.
Если не поняли написанное выше, скажу проще: «Не надо говорить о хорошем коде — его нет. Надо говорить об ошибках, которых не должно быть»
Есть «не верный» код («говнокод»), где неправильная семантика, где не очевидные ходы, где не оптимальные решения и прочие ошибки. У берите все эти ошибки и получите «правильный» код.
Если не поняли написанное выше, скажу проще: «Не надо говорить о хорошем коде — его нет. Надо говорить об ошибках, которых не должно быть»
+8
Вы то правы, но сразу же идете вслед за автором — «неправильная семантика, где не очевидные ходы, где не оптимальные решения». А по сути — есть только код рабочий и не рабочий! остальное это уже человеческие категории. Кому-то очевидный будет и для одних условий оптимальный.
+4
Рабочий/не рабочий — слишком узкое понятие для кода.
Вы не можете полностью проверить весь проект, вы не можете протестировать все граничные условия, любая простейшая математика в коде превращает количество комбинаций которые нужно тестировать из гигантского в астрономически-неподъёмное. Всегда стоит помнить, что если это код приложения, а не разового скрипта, то приложение будет так или иначе поддерживаться. Мнение что код пишется для машины — ложное, код пишется для тех кто его будет поддерживать, а значит именно человеческие категории для него — самые важные. ООП, функциональное программирование — воздушные замки в головах людей которые с этими концепциями работают, машине это всё не нужно, она быстрее бы работала без этого.
Хороший код не субъективное, а объективное понятие (но это не значит что критерии хорошего кода одинаковы для всех частей всех проектов), условно говоря, любой код может понравиться одному из сотни, но только хороший код понравится десяти из десяти.
Вы не можете полностью проверить весь проект, вы не можете протестировать все граничные условия, любая простейшая математика в коде превращает количество комбинаций которые нужно тестировать из гигантского в астрономически-неподъёмное. Всегда стоит помнить, что если это код приложения, а не разового скрипта, то приложение будет так или иначе поддерживаться. Мнение что код пишется для машины — ложное, код пишется для тех кто его будет поддерживать, а значит именно человеческие категории для него — самые важные. ООП, функциональное программирование — воздушные замки в головах людей которые с этими концепциями работают, машине это всё не нужно, она быстрее бы работала без этого.
Хороший код не субъективное, а объективное понятие (но это не значит что критерии хорошего кода одинаковы для всех частей всех проектов), условно говоря, любой код может понравиться одному из сотни, но только хороший код понравится десяти из десяти.
+3
>но только хороший код понравится десяти из десяти
Пожалуйста, покажите мне такой код.
Пожалуйста, покажите мне такой код.
+3
i++
-1
А мне больше нравится ++i.
+20
Douglas Crockford настаивает на i += 1, так как эта конструкция позволяет более удобно менять инкремент.
Так что опять – неидеальный фрагмент.
Так что опять – неидеальный фрагмент.
+3
Почемуто, все забыли про i++, интересно, много ли хаброжителей знают разницу между ++I и I++?
+1
Сейчас я пишу под iOS на Objective-C. Вызов метода порой это поиск в таблице и чуть ли не строковое сравнение (связка respondsToSelector и performSelector). Данные хранятся в sqlite файле, потому что так удобнее вытягивать их с сервера и объединять с локальными.
При этом фоновый поток переодически открывает jpeg картинки, отрисовывает их в памяти и отдаёт в главный поток, ведь отображение этой картинки не должно добавлять лагов, когда пользователь просто прокручивает ленту фотографий.
Ещё на фоне всего этого формируется куча временных объектов, например чтобы отсортировать массив, создаются ещё 2 новых, зато код выглядит немного нагляднее. Ах да, работа с базой данный проходит в основном потоке небольшими порциями, и во время этого фоновый поток всегда блокируется и ждёт окончания операции, так как это гораздо быстрее написать и не надо думать об ошибках, связанных с синхронизацией данных.
В тех случаях, когда итерацию по массиву нужно делать всё таки по индексу, а не используя for in конструкцию(for_each), которая выполняется медленнее, но гораздо удобнее, замечу ли я разницу в производительности между photoIndex++ или ++photoIndex (работу оптимизатора пока оставим в покое)?
При этом фоновый поток переодически открывает jpeg картинки, отрисовывает их в памяти и отдаёт в главный поток, ведь отображение этой картинки не должно добавлять лагов, когда пользователь просто прокручивает ленту фотографий.
Ещё на фоне всего этого формируется куча временных объектов, например чтобы отсортировать массив, создаются ещё 2 новых, зато код выглядит немного нагляднее. Ах да, работа с базой данный проходит в основном потоке небольшими порциями, и во время этого фоновый поток всегда блокируется и ждёт окончания операции, так как это гораздо быстрее написать и не надо думать об ошибках, связанных с синхронизацией данных.
В тех случаях, когда итерацию по массиву нужно делать всё таки по индексу, а не используя for in конструкцию(for_each), которая выполняется медленнее, но гораздо удобнее, замечу ли я разницу в производительности между photoIndex++ или ++photoIndex (работу оптимизатора пока оставим в покое)?
+1
Очень верное замечание. У нас на проекте есть человек с опытом работы Java-программистом и он, дай ему волю, нашинкует код в лапшу и соорудит 100500 функций по три строчки и к каждой из них напишет по 10 строк комментариев. Я же в коде, который пишу для себя, скорее напишу пяток функций с типичной длинной строк в 200-300. Где будет строк 10 комментариев в самых сложных местах. Понятно, что никто из нас читать код, который реально нравится другому (каждому из нас свой собственный код, понятно, правится) не может: я тону в этой куче «никому не нужных» функций, он, понятно, умирает не дойдя и до середины одной моей. Нужно ещё учесть, что у нас в точности противоположный подход к комментариям: я их читаю (и, соответственно, пишу) в тех местах, где что-то просто невозможно выразить на таких языках, как C++, Java, Python (они же не зря называются языками, правда?), он считает, что каждые пять строк должны быть снабжены комментарием на «человеческом» языке (и потому вынесены в функцию).
Понятно, что код, который идёт в production лежит где-то посередине между всеми этими крайностями, но, положа рука на сердце, не нравится он никому — просто это тот вариант, с которым все в нашей команда могут как-то работать.
Понятно, что код, который идёт в production лежит где-то посередине между всеми этими крайностями, но, положа рука на сердце, не нравится он никому — просто это тот вариант, с которым все в нашей команда могут как-то работать.
-4
он считает, что каждые пять строк должны быть снабжены комментарием на «человеческом» языке (и потому вынесены в функцию).
Как правило, я выношу «каждые пять строк» в функцию как раз чтобы не писать комментарии на русском, а назвать функцию на (псевдо)английском.
+3
А это, кстати, тоже источник постоянных споров: все ли функции должны ли быть снабжены комментариями или нет. Обычно люди сходятся на том, что простые герреры/сеттеры могут обойтись без комментария… а вот дальше начинаются разногласия.
0
Ну, надо ещё различать комментарии и *doc с прочими аннотациями.
0
Например Роберт Мартин в книжке «Чистый код» настоятельно проповедует самодокументируемый код. Код, который можно читать как книгу, когда имена функций\переменных и т.д. сами отвечают на вопрос «что она делает?». При таком подходе приходится разбивать даже пяти-строчечные куски на отдельные функции. Впрочем, если эти пять строк можно охарактеризовать одним словом, почему бы это не сделать? И тогда комментарии становятся излишними. Само собой не везде, иногда комментарием можно гораздо быстрее обьяснить какой-то изгиб мыслей.
+3
Я целиком и полностью поддерживаю такой подход. И, разумеется, для каждой важной функции, как для главы в книге, нужно придумывать осмысленные названия, иногда стоит описать что вы хотите получить, etc. Но зачем вам придумывать названия для пятистрочной конструкции, которая обходит массив и в нём часть элементов заменяет по шаблону? Неужели из кода оной конструкции не видно что именно она делает?
Когда я вижу, что кто-то в цикле вызывает GetModuleFileName увеличивая размер буфера в два раза, то я сразу понимаю что здесь происходит: ну неудачно сделан интерфейс, что поделать. Всё просто и понятно, но ладно: получили название модуля, дальше поехали. Зато я сразу вижу, что вызывается GetModuleFileNameW, что обозначает, что проблем с Unicode'ом не будет (зато могут быть проблемы с Windows 9X… хотя сейчас это уже не актуально). Когда же вызывается какая-нибудь SafelyGetModuleFileName у меня сразу вопрос: а с какого перепугу оно тут возникло и зачем, собственно, существует? Оно заменяет одни слеши на другие, делает что-то с Unicode'ом или вообще зачем? А если вдруг беда и получить имя модуля «safely» так и не получилось, то что, собственно, должно случиться? Куча вопросов, на которые зачастую документация ответа не даёт, приходится лезть в другую часть программы, чтобы что-то понять (либо положиться на свою интуицию… что зачастую потом кончается интересным развлечением когда программа отказывается «safely» получать своё имя на машине заказчика со странной конфигурацией).
Когда я вижу, что кто-то в цикле вызывает GetModuleFileName увеличивая размер буфера в два раза, то я сразу понимаю что здесь происходит: ну неудачно сделан интерфейс, что поделать. Всё просто и понятно, но ладно: получили название модуля, дальше поехали. Зато я сразу вижу, что вызывается GetModuleFileNameW, что обозначает, что проблем с Unicode'ом не будет (зато могут быть проблемы с Windows 9X… хотя сейчас это уже не актуально). Когда же вызывается какая-нибудь SafelyGetModuleFileName у меня сразу вопрос: а с какого перепугу оно тут возникло и зачем, собственно, существует? Оно заменяет одни слеши на другие, делает что-то с Unicode'ом или вообще зачем? А если вдруг беда и получить имя модуля «safely» так и не получилось, то что, собственно, должно случиться? Куча вопросов, на которые зачастую документация ответа не даёт, приходится лезть в другую часть программы, чтобы что-то понять (либо положиться на свою интуицию… что зачастую потом кончается интересным развлечением когда программа отказывается «safely» получать своё имя на машине заказчика со странной конфигурацией).
+1
GetModuleFileName
Мне кажется, работа напрямую с WinApi не из какой-нибудь обёртки — уже признак того, что могут быть проблемы. Vendor Lock-In Antipattern?
+1
А это смотря что вы делаете. В данном случае речь шла о «заменителе .sh-файла» (ну нет переносимой замены для .sh-файлов под Windows), что во-первых лишало переносимость всякого смысла (для всех остальных платформ, собственно .sh-файл и использовался), а во-вторых иметь вместо файла в 100 байт иметь что-то на мегабайт желания не возникало. И так в конечном итоге результат 9K занял.
0
>>Неужели из кода оной конструкции не видно что именно она делает?
В том-то и дело! Что не следует заставлять программера делать паузу, чтобы понять очевидность функции. Даже если эта пауза в 1-2 сек. В целом из таких вот остановок и пауз происходит множество переключений мозга с одного уровня абстракции на другой. Из-за переключений пусть даже кратковременных человеческий мозг быстрее устает. Куда проще дать такое название, чтобы программер быстро понял «Мне сейчас это не надо».
В том-то и дело! Что не следует заставлять программера делать паузу, чтобы понять очевидность функции. Даже если эта пауза в 1-2 сек. В целом из таких вот остановок и пауз происходит множество переключений мозга с одного уровня абстракции на другой. Из-за переключений пусть даже кратковременных человеческий мозг быстрее устает. Куда проще дать такое название, чтобы программер быстро понял «Мне сейчас это не надо».
+1
Узнать код обхода массива и понять (примерно), что там должно происходить, может быть гораздо быстрее, чем расшифровывать имя функции и угадывать, что бы оно могло значить. Тем более, что это и есть переключение на другой (параллельный) уровень абстракции — с просмотра кода и распознавания конструкций языка и их комбинаций на лигвистический анализ того, что человек пытался придумать «для людей, а не для машины». Хорошо, если он сам вспомнит, как это имя метода расшифровывается. А код остался бы кодом. На языке.
То же и с комментариями. Переключение с чтения кода на анализ комментариев — тоже переключение контекста, которое отвлекает. Комментарии полезны в совершенно незнакомой программе, когда надо быстро найти место, где происходит какое-то действие, которое вроде бы должно происходить, но тогда лучше им жить в параллельном столбике. Как было во времена ассемблера: слева код, справа комментарии. И друг от друга не отвлекают.
То же и с комментариями. Переключение с чтения кода на анализ комментариев — тоже переключение контекста, которое отвлекает. Комментарии полезны в совершенно незнакомой программе, когда надо быстро найти место, где происходит какое-то действие, которое вроде бы должно происходить, но тогда лучше им жить в параллельном столбике. Как было во времена ассемблера: слева код, справа комментарии. И друг от друга не отвлекают.
0
>>Как было во времена ассемблера
Что было то было, а потом вообще будет по-другому. Решать надо с тем что есть в данную минуту!
>>ем расшифровывать имя функции и угадывать, что бы оно могло значить.
А зачем расшифровывать? Более-того никто Вам не запрещает сделать рефакторинг «Rename method», скажу больше удачное название метода может получить в результате 5-7 переименований и это не страшно!
>>Переключение с чтения кода на анализ комментариев
А не надо писать комментарии, есть название методов и переменных. Этого достаточно. Если же этого мало Вы можете всегда дописать в виде: «Алгоритм взят из книги Кнута 2 том стр.135» или вот еще пример «Работаем на основании RFC100500» и этого более чем достаточно!
Впрочем, если Вы пишите исключительно своими силами и при этом вероятность чтения Вашего кода другим программером слишком мала, то пишите так как именно Вам удобно и не парьтесь. В противном случае пишите так: «Как будто Ваш код будет знать придурок с садисткими наклонностями, который знает где Вас найти»
Что было то было, а потом вообще будет по-другому. Решать надо с тем что есть в данную минуту!
>>ем расшифровывать имя функции и угадывать, что бы оно могло значить.
А зачем расшифровывать? Более-того никто Вам не запрещает сделать рефакторинг «Rename method», скажу больше удачное название метода может получить в результате 5-7 переименований и это не страшно!
>>Переключение с чтения кода на анализ комментариев
А не надо писать комментарии, есть название методов и переменных. Этого достаточно. Если же этого мало Вы можете всегда дописать в виде: «Алгоритм взят из книги Кнута 2 том стр.135» или вот еще пример «Работаем на основании RFC100500» и этого более чем достаточно!
Впрочем, если Вы пишите исключительно своими силами и при этом вероятность чтения Вашего кода другим программером слишком мала, то пишите так как именно Вам удобно и не парьтесь. В противном случае пишите так: «Как будто Ваш код будет знать придурок с садисткими наклонностями, который знает где Вас найти»
+1
Я человек эксперимента. После чтения книги Мартина про чистый код решил попробовать в своей практике. Результат меня впечатлил. Даже при отсутствии комментариев код понятен!
Но Мартин отчетливо и ясно говорит: «Хороший код не рождается за 5 мин. Это итеративный процесс». Также он говорит: «Сначала я пишу код, он работает. А потом не беру новую задачу, а провожу чистку кода».
Книга стоит того чтобы на нее потратить время и даже 10% взятые в свою практику из этой книги спасут мягкое место он многих проблем.
Но Мартин отчетливо и ясно говорит: «Хороший код не рождается за 5 мин. Это итеративный процесс». Также он говорит: «Сначала я пишу код, он работает. А потом не беру новую задачу, а провожу чистку кода».
Книга стоит того чтобы на нее потратить время и даже 10% взятые в свою практику из этой книги спасут мягкое место он многих проблем.
+2
Имхо при хорошем наименовании должны быть прокомментированы только публичные методы. Да и то не всегда.
В обязательном порядке д.б. прокомментированы интерфейсы.
Вообще, чем ближе код к «библиотечному», тем лучше он д.б. продокументирован. Т.е., условно говоря, UI можно не документировать, а вот какой-то общий код, используемый во многих местах, — обязательно.
В обязательном порядке д.б. прокомментированы интерфейсы.
Вообще, чем ближе код к «библиотечному», тем лучше он д.б. продокументирован. Т.е., условно говоря, UI можно не документировать, а вот какой-то общий код, используемый во многих местах, — обязательно.
+1
Думаю, разродившееся обсуждение ответит за меня (:
0
Код не только должен быть рабочим (выполнять задачу), но так же должен легко поддаваться изменениям (отвечать возникающим новым требованиям). Вот код, отвечающий этим двум критериям, можно и нужно считать хорошим.
0
Стандарты слов типа «хорошие», «красивые», «милые», «идеальные» есть и всегда были, этому посвящены книги, картины, быт и множество других форм. Просто они достаточно абстрактны, в частности субъективны, не так легко применимы, вернее, перед применением требуют осмысления и наложения на предметную область. Вы же пытаетесь сказать тоже самое, но с другой стороны. Хороший код есть, а вот кода без ошибок — нет. Возможно, я живу в не правильном, своем, выдуманном мире.
+4
Почти для любого языка есть статические анализаторы ошибок\проблем, а также метрики сложности. Они очень хорошо показывают насколько код хорош.
Так вот эти показатели очень сильно коррелируют с одной стороны с читаемостью, с другой стороны с багами. Я это на десятке проектов проверял.
Так вот эти показатели очень сильно коррелируют с одной стороны с читаемостью, с другой стороны с багами. Я это на десятке проектов проверял.
-1
Я надеюсь вы хотели сказать что с багами они антикоррелируют?
А по делу, я последнее время разочаровался в метриках качества кода. Когда на них начинают слишком сильно ориентироваться — получается ситуация когда все методы короткие, имеют xml-комментарий (по большей части не дающий ничего нового по сравнению с сигнатурой и именем метода), каждый класс имеет по меньшей мере один юнит-тест. Но в итоге код непонятный, тесты тестируют не интерфейс класса а реализацию, при малейшем изменении реализации тесты падают, после чего становится непонятно, нужно исправлять тест или же откатывать изменении в тестируемом классе.
Видел и обратный случай — когда оптимизируемым параметром являются не метрики, а способность ревьювера без затруднений понять что в коде происходит, неспособность пользователя библиотеки использовать её неправильно — целью является понятность кода и надежность кода. Когда тесты пишутся для того, чтобы добавить уверенности что сложный участок кода реализован правильно, чтобы тестировался интерфейс, не мешая рефакторингу внутренней части, но отлавливая ошибки приведшие к нарушению видимого поведения. Вот тогда код мягкий и шелковистый, с ним приятно работать!
То моё мнение сейчас, что единственной работающей метрикой является картинка ниже, а также что код работает, и продолжает работать после изменения требований и внесения изменений.
![](https://habrastorage.org/r/w1560/getpro/habr/comment_images/eac/abd/611/eacabd6118a7885bcd8d0272f110d1d4.png)
А по делу, я последнее время разочаровался в метриках качества кода. Когда на них начинают слишком сильно ориентироваться — получается ситуация когда все методы короткие, имеют xml-комментарий (по большей части не дающий ничего нового по сравнению с сигнатурой и именем метода), каждый класс имеет по меньшей мере один юнит-тест. Но в итоге код непонятный, тесты тестируют не интерфейс класса а реализацию, при малейшем изменении реализации тесты падают, после чего становится непонятно, нужно исправлять тест или же откатывать изменении в тестируемом классе.
Видел и обратный случай — когда оптимизируемым параметром являются не метрики, а способность ревьювера без затруднений понять что в коде происходит, неспособность пользователя библиотеки использовать её неправильно — целью является понятность кода и надежность кода. Когда тесты пишутся для того, чтобы добавить уверенности что сложный участок кода реализован правильно, чтобы тестировался интерфейс, не мешая рефакторингу внутренней части, но отлавливая ошибки приведшие к нарушению видимого поведения. Вот тогда код мягкий и шелковистый, с ним приятно работать!
То моё мнение сейчас, что единственной работающей метрикой является картинка ниже, а также что код работает, и продолжает работать после изменения требований и внесения изменений.
![](https://habrastorage.org/getpro/habr/comment_images/eac/abd/611/eacabd6118a7885bcd8d0272f110d1d4.png)
+8
Если быть математически точным, то корреляция отрицательная.
Если вы разочаровались в метриках, то скорее всего просто не те метрики используете. Я, напрмиер, недавно посчитал плотность try с пустым catch(Exception) в проекте. В хороших проектах получилось около 1 на 200 строк, а в плохих 1 на 20 строк, разница в 10 раз. Естественно эти плохие проекты принесли очень много проблем.
Понятно что одними метриками определить качество кода не выйдет. Поэтому я в посте и про метрики ничего не сказал. Но метрики могут сказать очень много. Особенно если их отслеживать в динамике и коррелировать с состоянием проекта.
WTF/s хороший параметр, но слишком субъективный. И, самое главное, только малая часть программистов способны читать код.
Если вы разочаровались в метриках, то скорее всего просто не те метрики используете. Я, напрмиер, недавно посчитал плотность try с пустым catch(Exception) в проекте. В хороших проектах получилось около 1 на 200 строк, а в плохих 1 на 20 строк, разница в 10 раз. Естественно эти плохие проекты принесли очень много проблем.
Понятно что одними метриками определить качество кода не выйдет. Поэтому я в посте и про метрики ничего не сказал. Но метрики могут сказать очень много. Особенно если их отслеживать в динамике и коррелировать с состоянием проекта.
WTF/s хороший параметр, но слишком субъективный. И, самое главное, только малая часть программистов способны читать код.
0
Хм, любопытно, а показатель чего это?
И что такое пустой catch — он совсем пустой или хотя бы имеет запись в лог?
И что такое пустой catch — он совсем пустой или хотя бы имеет запись в лог?
0
Код на C#, отлавливал try\catch(Exception), где внутри catch не было throw. API никогда не кидает Exception базового класса.
Любой такой код проглатывает все ошибки независимо от их природы, даже если писать в лог, то непонятно что произошло, ибо контекста очень мало.
Нашел три модуля, в которых плотность таких try\catch превышена. На всех трех было много ошибок (примерно в 2 раза больше) и огромные затраты на тестирование (в 5-6 раз больше), по сравнению с кодом где плотность таких try\catch ниже.
Иногда такой код оправдан, но обычно это не чаще, чем 1 раз на 300 строк.
Любой такой код проглатывает все ошибки независимо от их природы, даже если писать в лог, то непонятно что произошло, ибо контекста очень мало.
Нашел три модуля, в которых плотность таких try\catch превышена. На всех трех было много ошибок (примерно в 2 раза больше) и огромные затраты на тестирование (в 5-6 раз больше), по сравнению с кодом где плотность таких try\catch ниже.
Иногда такой код оправдан, но обычно это не чаще, чем 1 раз на 300 строк.
+1
WTF/s хороший параметр, но слишком субъективный.А главное — тривиально манипулируемый. Достаточно добавить в проект «воды» и он резко упадёт.
Скажем если у вас есть два куска кода с разницей в WTF/s в 3-5 раз, то какой из них лучше? А если учесть, что вариант с плотным покрытием WTF'ами раз в 100 короче? Пример вполне себе из жизни — и да, таки вариант с плотным покрытием WTF'ами был признан более читабельным. Просто к нему комментариев пришлось добавить побольше, вот и всё. Количество WTF/s упало, но, по большому счёту, просто за счёт увеличения этих самых s :-)
+1
Именно об этом я и писал:
Работа на метрики не дает гарантий качества кода. Именно поэтому программистовнадо бить палками надо обучать писать хороший код и поощрять такое поведение.
Единственный инструмент повышения качества кода – вы сами. Если вы не стремитесь всегда делать хороший код, то вам не помогут ни тесты, ни инструменты статического анализа. Даже ревью других программистов не поможет.
Работа на метрики не дает гарантий качества кода. Именно поэтому программистов
0
Окей, давайте назовёс WTF/фича- количество WTF, которые произнесёт сторонний программист в процессе добавления к коду фичи стандартного размера.
В таком случае код
В таком случае код
100500 функций по три строчки и к каждой из них по 10 строк комментариев.вызовет в процессе его чтения суммарно больше WTF чем короткий код с высокой плотностью WTF.
0
Для текстов на человеческом языке такая градация есть. Откройте любое печатное издание, и вы по крайней мере поймете написанное (соглашаться необязательно) и не будете продираться через частокол грамматических ошибок. Что мешает нам, программистам, ввести подобный стандарт для программного кода?
0
Так вот как это называется! Теория Разбитых Окон. Помню, был проект, в котором учавствовали две команды из разных контор. Начальная часть проекта лежала на плечах нашей команды. Так вот, сделал я в одном месте «плохой код» с комментариями TODO, что это пока хак, что нужно переделать. Подключилась другая команда. Они скопипастили этот код и начали вставлять его в свои модули. Ребята с моей команды тоже заметили, что написал хак и тоже начали писать свои. В общем, проект закончен, но держится на соплях
-1
Но удивляют люди, написавшие отстойный код. Эти люди, с немалым опытом, знают несколько языков, прочитали много книг, знают ООП, SOLID, рефакторинг, паттерны и другие малопонятные слова. То есть примерно такие, как многие из вас, читающих этот пост.
Этих много на весь хабр не более 1%. Так что не нервничайте понапрасну, сходите на иогу.
Этих много на весь хабр не более 1%. Так что не нервничайте понапрасну, сходите на иогу.
-7
Если вы сами пишете “быстро и грязно”, например прототип для уточнения требований, то выкиньте код и перепишите нормально сразу после того, как ваш код сделает свое дело.Вопрос не по теме: а кто-нибудь вообще так делал в реальной жизни? Я ни разу такого не встречал в своей практике за уже 8 лет программирования.
+8
Делал. Набрасывал прототип на рельсах, а потом переписывал на пхп. Правда один раз пршлось допиливать прототип.
-1
Делал. Набрасывал прототип на рельсах, а потом переписывал на пхп.
То есть обязательное требование использовать для прототипирования и разработки несовместимые языки и технологии, чтобы даже мысли скопипастить не возникало? :)
+8
Почти обязательное. Иначе с вероятностью 99% окажется, что ваш код нужен ну-очень-сильно-срочно и нефиг тут возиться с переписыванием.
+3
Типа того. Хотя, как показала практика, это не гарантия того, что не придется допиливать прототип по причине «работает же, а нам срочно надо». Ну и премию за досрочное выполнение пообещали заплатить, если «быстренько допилю».
0
Я всегда заставлял команду смотреть на код и переделывать после того как заработает. Помогало. В релизе, сделанном в таком режиме, тестер нашел всего одну багу за день.
Но часто срабатывает прессинг сроков, как только код начал давать результат похожий на тот, который нужен, он сразу становится священной коровой. Его нельзя трогать, чтобы, ни дай бог, оно не развалиось.
Но часто срабатывает прессинг сроков, как только код начал давать результат похожий на тот, который нужен, он сразу становится священной коровой. Его нельзя трогать, чтобы, ни дай бог, оно не развалиось.
0
> Набрасывал прототип на рельсах, а потом переписывал на пхп
Зачем, позвольте поинтересоваться?
//ответ habrahabr.ru/post/206294/#comment_7106986, ошибся немного :(
Зачем, позвольте поинтересоваться?
//ответ habrahabr.ru/post/206294/#comment_7106986, ошибся немного :(
+2
Теория всегда выглядит красиво, пока это теория. На практике очень часто выглядит так (утрированно):
Менеджер: Ребята, у меня для вас плохая новость… Заказчик попросил добавить 100500 новых фич в проект, но они все небольшие, поэтому сроки сдвигать не стали. Вас не стали подтягивать на встречу, дабы не отвлекать от работы.
Программисты: (забив на читабельность и реюзабельность кода) Нууууууу лаааааааднооооооо…
Это я к тому, что зачастую просто нет времени наводить красоту, когда речь идет о захвате рынка. А вот когда-нибудь потом… когда компания заработает XXX млн рублей, уже можно подумать о рефакторинге и красоте. Самое печальное — что такой подход зачастую выигрывает, ибо перфекционизм в данном случае зачастую является помехой. Сам я тоже сторонник красоты и порядка, но рынок диктует свои правила.
Менеджер: Ребята, у меня для вас плохая новость… Заказчик попросил добавить 100500 новых фич в проект, но они все небольшие, поэтому сроки сдвигать не стали. Вас не стали подтягивать на встречу, дабы не отвлекать от работы.
Программисты: (забив на читабельность и реюзабельность кода) Нууууууу лаааааааднооооооо…
Это я к тому, что зачастую просто нет времени наводить красоту, когда речь идет о захвате рынка. А вот когда-нибудь потом… когда компания заработает XXX млн рублей, уже можно подумать о рефакторинге и красоте. Самое печальное — что такой подход зачастую выигрывает, ибо перфекционизм в данном случае зачастую является помехой. Сам я тоже сторонник красоты и порядка, но рынок диктует свои правила.
+5
Уровень качества кода всегда программисты определяют самостоятельно, если нету формальных ревью. Никакие слова менеджера не помешают им писать так, как хотят. При этом некоторые (например Вы) считают что сделать быстро и грязно выйдет дешевле. Практика показывает что не дешевле.
0
Вы немного не понимаете того, о чем идет речь. Если времени на разработку достаточно, то программисты действительно самостоятельно определяют уровень качества кода. Но в бизнесе довольно часто бывают ситуации, когда программистам ставят задачу с довольно сжатыми сроками и суровыми штрафными санкциями. И виной этому не горе-руководитель или генеральный директор, а обыкновенный рынок: если «завтра» не выйдем на рынок мы, то «послезавтра» это сделают наши конкуренты. В таких ситуациях программисты определяют далеко не все параметры разработки.
Точнее они могут самостоятельно определить, но результат будет плачевен. Ибо исхода, по сути, два:
1. Либо собранное на коленке решение, которое допиливается и рефакторится «потом».
2. Либо «красивое» во всех смыслах решение, которое вышло заметно позже своего конкурента, поэтому не смогло завоевать рынок и кануло в небытие.
Тоесть очень часто бывает так, что рынок диктует условия разработки программистам, а не программисты рынку. И «красота» тогда приходит уже в процессе рефакторинга. Согласен, что появляются доп-расходы на красоту, и в целом расходы на разработку выше, чем если сразу делать «как надо». Но зато мы захватили рынок и у нас есть доход, на который мы можем это делать.
PS: Я сам программист и ни разу не «манагер», и понимание влияния рынка на проекты пришло ко мне не сразу.
Точнее они могут самостоятельно определить, но результат будет плачевен. Ибо исхода, по сути, два:
1. Либо собранное на коленке решение, которое допиливается и рефакторится «потом».
2. Либо «красивое» во всех смыслах решение, которое вышло заметно позже своего конкурента, поэтому не смогло завоевать рынок и кануло в небытие.
Тоесть очень часто бывает так, что рынок диктует условия разработки программистам, а не программисты рынку. И «красота» тогда приходит уже в процессе рефакторинга. Согласен, что появляются доп-расходы на красоту, и в целом расходы на разработку выше, чем если сразу делать «как надо». Но зато мы захватили рынок и у нас есть доход, на который мы можем это делать.
PS: Я сам программист и ни разу не «манагер», и понимание влияния рынка на проекты пришло ко мне не сразу.
+7
Вы тут говорите о другой плоскости. Качество продукта и качество кода хоть и связаны, но не настолько сильно, как кажется.
Качество продукта зависит в первую очередь от восприятия его пользователями. Продукт может решать одну маленькую проблему, при этом не доставлять неудобств, он уже будет хорош. Для того чтобы его сделать не надо пилить 100500 фич в авральном режиме.
Пиление 100500 фич в авральном режиме случается в заказной разработке, когда проект надо сдавать, а ожидания заказчика не согласованы с тем что было сделано, Но и в этом случае нет никакого резона жертвовать качеством. Лучше приоритезировать фичи, сделать 20% самых важных, остальное подвинуть. Окажется что остальное делать и не очень надо.
Я много работал тимлидом в заказной разработке, на моей практике жертвовать качеством — всегда выбор программиста.
Качество продукта зависит в первую очередь от восприятия его пользователями. Продукт может решать одну маленькую проблему, при этом не доставлять неудобств, он уже будет хорош. Для того чтобы его сделать не надо пилить 100500 фич в авральном режиме.
Пиление 100500 фич в авральном режиме случается в заказной разработке, когда проект надо сдавать, а ожидания заказчика не согласованы с тем что было сделано, Но и в этом случае нет никакого резона жертвовать качеством. Лучше приоритезировать фичи, сделать 20% самых важных, остальное подвинуть. Окажется что остальное делать и не очень надо.
Я много работал тимлидом в заказной разработке, на моей практике жертвовать качеством — всегда выбор программиста.
0
расставить приоритеты программисту, проконтролировать качество и прикинуть что с каким качеством успеете сделать и есть задача манагера. Если на программистов вывалили 100500 фич и ожидают что они будут с заказчиком согласовывать что нужно сразу, что нужно потом, что вообще не нужно, что нужно но не в таком виде, что нужно но может поломать что то что нужно ещё больше, что нужно не успевают протестировать… то это мягко говоря очень хорошие программисты нужны…
+1
Менеджер это кто? Добавить в систему CI анализатор кода /требование к юнит тестам (pmd/emma например) не в их компетенции? У нас как то было так закручено что индентацию можно было только пробелами делать и никак не табами (причем проверяются только новые коммиты так что переписывать старое необходлимости нет).
Можно конечно обсуждать является ли это признаком качества кода и нужно ли такое качество за такую цену (потому что поддерживать юнит тесты это отдельный эффорт).
Но чисто технически помешать программистам писать как они хотят вполне можно.
Можно конечно обсуждать является ли это признаком качества кода и нужно ли такое качество за такую цену (потому что поддерживать юнит тесты это отдельный эффорт).
Но чисто технически помешать программистам писать как они хотят вполне можно.
0
Не кто специально не делает «быстро и грязно».
Но когда тебе дают проект который до этого поддерживало 100500 коллег, где нужно «вставить новую кнопочку» все стараются локально в рамках задачи, случайно не задев другой функционал создавать свои переменные, функции, классы т.к. документации никакой нет.
Но когда тебе дают проект который до этого поддерживало 100500 коллег, где нужно «вставить новую кнопочку» все стараются локально в рамках задачи, случайно не задев другой функционал создавать свои переменные, функции, классы т.к. документации никакой нет.
0
Дешевле или дороже программистов как правило не волнует. У них (нас) другие критерии — сроки и качество.
0
А вот зря не волнует, потому что любой код надо:
1) Написать
2) Протестировать
3) Поддерживать
«Сроки» оценивают только «написать». На «протестировать» чаще всего закладывается процент от «сроки», а на «поддерживать» не закладывается ничего. Вот только поддержка кода — очень дорогой процесс, напрямую он отражается на «сроках» других задач проекта.
Иногда наступает момент, когда любые «сроки» становятся гораздо выше ожидаемых и наступает непрерывный аврал.
Слава богу что многие проекты кончаются раньше.
Качество может увеличить сроки на написание и заметно сократить на тестировании и поддержке. Но об этом часто ни менеджеры, ни программисты не думают.
1) Написать
2) Протестировать
3) Поддерживать
«Сроки» оценивают только «написать». На «протестировать» чаще всего закладывается процент от «сроки», а на «поддерживать» не закладывается ничего. Вот только поддержка кода — очень дорогой процесс, напрямую он отражается на «сроках» других задач проекта.
Иногда наступает момент, когда любые «сроки» становятся гораздо выше ожидаемых и наступает непрерывный аврал.
Слава богу что многие проекты кончаются раньше.
Качество может увеличить сроки на написание и заметно сократить на тестировании и поддержке. Но об этом часто ни менеджеры, ни программисты не думают.
0
> Программисты: (забив на читабельность и реюзабельность кода) Нууууууу лаааааааднооооооо…
Не факт. Если это уважающие себя и свой труд спецы, то они свалят. И тогда уже вопрос пойдет не про сдвиги сроков, молниеносный захват рынка и прочий буллшит «эфективных менеджеров», а вопрос будет стоять выживет ли вообще такая фирма.
Не факт. Если это уважающие себя и свой труд спецы, то они свалят. И тогда уже вопрос пойдет не про сдвиги сроков, молниеносный захват рынка и прочий буллшит «эфективных менеджеров», а вопрос будет стоять выживет ли вообще такая фирма.
+1
Грязный код во многих проектах с вами категорически несогласен ;)
Не каждый программист может моментально свалить в силу каких-либо причин. А на место ушедших всегда можно взять новых штрейкбрехеров.
Не каждый программист может моментально свалить в силу каких-либо причин. А на место ушедших всегда можно взять новых штрейкбрехеров.
0
Мне кажется, программист, который ради красивого кода забывает, что результат, ради которого он работает — не код, а продукт… Такой программист даже хуже пишущего говногод, что бы успеть в срок.
По хорошему в такой ситуации нужно обсуждать, что вот эти фичи в срок никак не сделать без потерь, но может у фич что-то отрезать, договориться перенести и т.п., а не ставить ультиматум — «или идеально вылизанный код или никакого кода». Максимализм — зло.
Потому что фирма, перенёсшая пару (десятков) раз сроки из-за таких вот принципиальных и в результате обанкротившаяся — тоже же не жилец.
По хорошему в такой ситуации нужно обсуждать, что вот эти фичи в срок никак не сделать без потерь, но может у фич что-то отрезать, договориться перенести и т.п., а не ставить ультиматум — «или идеально вылизанный код или никакого кода». Максимализм — зло.
Потому что фирма, перенёсшая пару (десятков) раз сроки из-за таких вот принципиальных и в результате обанкротившаяся — тоже же не жилец.
+3
Вы таки приписываете мне того о чем я не говорил.
Причем здесь борьба за «качество» кода?
В примере выше какие то мудаки без программистов обозначали сроки и стопицот фич. Тут уже вопрос не стоит «качественный код писать али некачественный», тут стоит вопрос «работать на таких мудаков или нет».
П.С. ну и парадокс для всяких «эффективных менеджеров» — «писать качественно всегда быстрее и дешевле»
Причем здесь борьба за «качество» кода?
В примере выше какие то мудаки без программистов обозначали сроки и стопицот фич. Тут уже вопрос не стоит «качественный код писать али некачественный», тут стоит вопрос «работать на таких мудаков или нет».
П.С. ну и парадокс для всяких «эффективных менеджеров» — «писать качественно всегда быстрее и дешевле»
0
Это не менеджер, это прокладка между заказчиками и исполнителями. Любой дурак может транслировать самые смелые фантазии заказчика команде. Задача менеджера тут выполнена не была. Это он должен был настоять на изменении сроков или урезании требований.
+1
На хабре не всем очевидно что код пишется для людей.
habrahabr.ru/post/205980/#comment_7098360
habrahabr.ru/post/205980/#comment_7098360
-2
Я использую пару приёмов, чтобы хоть как-то повысить качество своего кода. Это утренний code review и помидорка. Первое достаточно просто — рабочий день начинается с обзора того, что сам написал за вчерашний день. Очень часто помогает самому увидеть недостатки своего кода. Ну, а второе — задаёт удобный (для меня конечно) режим работы. 25 минут кодируешь — 5 минут перерыв, опять 25 минут кодируешь — 15 минут перерыв и по новой. Эти перерывы помогают обдумать, что буду кодировать следующий «спринт». Как-то так.
0
А не бывает такого что таймер прерывает вас в самой середине работы: как раз пишете, пишете код, а тут перерыв?
0
Ссылку не открывал, но я думаю, что вся суть подхода именно в том, чтобы дробить задачу на осязаемые кусочки, который можно сделать как раз за 25 минут.
0
Бывает. И иногда здорово помогает понять, что двигаешься не в том направлении. Тут самое сложное усилием воли заставить себя взять таймаут. А иногда просто понимаешь, что направление в целом верное, но вот здесь можно сделать проще, а этот класс вообще не нужен.
0
Теория разбитых оконЯ бы назвал это не теорией разбитых окон, а теорией хаоса.
В эксперименте с машинами кстати наглядное подтверждение того что энтропия в изолированной системе только растет, и понижать её надо искусственно. Что кстати навевает мысль что:
Есть также и обратный эффект. Поддержание порядка приводит к тому, что окружающие также поддерживают порядок.есть в некоторой степени ложное утверждение, ибо при росте проекта — его энтропия бы понижалась (ведь каждый пишет безкостыльный чистый код, да?). Если каждый будет поддерживать чистоту — код все равно будет в целом становится все грязнее и грязнее. Поэтому имхо очень важно периодически проводить рефакторинги, и выпиливать костыли. Таким образом искусственно понижать энтропию.
+1
Теория хаоса вообще о другом. Она говорит изучает детерминированные системы, наблюдаемое поведение которых очень сложно. Разработка кода не является детерминированной системой.
Сюда бы больше подошла термодинамика и закон неубывания энтропии. Но разработка кода не является системой замкнутой.
Теория разбитых окон не о математике и не о физике, она о психологии. Имеет множество подтверждений как прямое действие, так и обратное.
Устраивать периодические чистки — не работает. Я пробовал. Во-первых неизвестно где чистить, не будешь же 10к трок просто так перечитывать в поисках чего бы почистить. Во-вторых это попытка чинить то, что не сломано, это психологически мешает проводить полезные улучшения.
Сюда бы больше подошла термодинамика и закон неубывания энтропии. Но разработка кода не является системой замкнутой.
Теория разбитых окон не о математике и не о физике, она о психологии. Имеет множество подтверждений как прямое действие, так и обратное.
Устраивать периодические чистки — не работает. Я пробовал. Во-первых неизвестно где чистить, не будешь же 10к трок просто так перечитывать в поисках чего бы почистить. Во-вторых это попытка чинить то, что не сломано, это психологически мешает проводить полезные улучшения.
+1
Теория хаоса вообще о другом. Она говорит изучает детерминированные системыУ нас есть достаточно очевидное понимание для простых случаев — что есть костыли/говнокод, а что нет. Т.е. грубо можно сказать что система у нас детерминирована (грубо, потому что все таки отдельно взятые костыли измерять мы пока не научились). В то же самое время на выходе от толпы программистов — программа, и сложно сказать сколько там костылей.
В общем я более чем уверен, что написанный командой код можно определить как сложную детерминированную систему.
Сюда бы больше подошла термодинамика и закон неубывания энтропии.Всю жизнь считал что термодинамика со своей энтропией может быть рассмотрена как частный случай теории хаоса.
Теория разбитых окон не о математике и не о физике, она о психологии. Имеет множество подтверждений как прямое действие, так и обратное.Вбил в гуголь закон неубывания энтропии. Третья ссылка с выдачи: Теория разбитых окон — Lurkmore. Я понимаю что лурка — не шибко авторитетный сайт, но все же там написано: «Теория была разработана американскими учёными Джеймсом Уилсоном и Джорджем Келлингом в 1982 году и по сути является частным случаем реализации закона неубывания энтропии.»
Я не заглядывал в гугл перед предыдущим ответом вам. Я просто прочел описание теста с разбитыми окнами — и сразу заметил в этом тесте теорию хаоса и закон неубывания энтропии (который кстати относится не только к термодинамике, а вообще к энтропии в целом).
0
Еще один фактор влияющий на качество кода – сложность и несовершенство платформ и фреймворков, используемых в разработке. Из-за этого в коде часто появляются хаки и нелепые workaround-ы. Со временем начинает казаться что эти хаки и есть хороший код. Даже когда проблемы фреймворков исправляют, люди продолжают использовать хаки. Кстати эти хаки со временем могут попадать в интернет через форумы, блоги или pastebin и распространяться далеко за пределы одного приложения.
Вот хорошо что автор не забывает про такие ситуации. Мы пишем на Unity — и без нормальной поддержки дженериков и сериализации приходится делать код действительно страшным.
Вот хорошо что автор не забывает про такие ситуации. Мы пишем на Unity — и без нормальной поддержки дженериков и сериализации приходится делать код действительно страшным.
0
Автору: пожалуйста, исправьте «На последок» -> «Напоследок», а то как гвоздем в глаз.
-3
Существуют системы с прекрасным кодом внутри, но с уродливой мордой и моралью наружу. Те, кто работал с первыми DirectX, а ныне зарабатывает на шейдерах, не могут создавать хороший код.
Надо их всехрасстрелять наградить, кстати.
Надо их всех
+1
Код пишется для людей
Код пишется для машины, а для людей можно писать комментарии. Если «взять в левую руку» классический пример кода, разбитого на небольшие функции с понятными названиями именами переменных, а «в правую руку» — многостраничную портянку, логически разбитую на откомментированные блоки, то я предпочту портянку с комментариями. Ее легче прочитать, быстрее понять, проще найти ошибку.
-1
Для машин код не писали, а задавали тумблерами или дырками на перфокартах.
0
Это в теории. Практика такова, что комментарии тоже надо поддерживать, как и код. Обычно при добавлении костылей и хаков под прессингом времени комментарии не обновляются. Это приводит к том, что комментарии расходятся с кодом.
Кстати написать хороший комментарий сложнее, чем написать хороший код.
Я вот умудряюсь читать разобранные в ILSpy сборки Microsoft SharePoint. Там не то что комментариев, там даже имен переменных нет. Нормально читается, видимо потому что много из этого кода поддерживается уже 10 лет. Нечитаемый код столько просто не прожил бы.
Кстати написать хороший комментарий сложнее, чем написать хороший код.
Я вот умудряюсь читать разобранные в ILSpy сборки Microsoft SharePoint. Там не то что комментариев, там даже имен переменных нет. Нормально читается, видимо потому что много из этого кода поддерживается уже 10 лет. Нечитаемый код столько просто не прожил бы.
+1
Вся суть статьи: открываем The Pragmatic Programmer, читаем главу «2. Software Entropy»
И еще…
![this isn't xkcd. don't look for alt test.](https://habrastorage.org/r/w1560/getpro/habr/comment_images/3eb/bdf/839/3ebbdf83916cb20675740c0f5d9d2c73.png)
И еще…
![this isn't xkcd. don't look for alt test.](https://habrastorage.org/getpro/habr/comment_images/3eb/bdf/839/3ebbdf83916cb20675740c0f5d9d2c73.png)
+1
Один из немногих постов, где комментарии (включая этот) еще более бесполезны, чем сама писанина.
Я сначала подумал что это перевод — однако нет, оказывается и мы умеем писать в нудной манере о очевидных вещах.
Я сначала подумал что это перевод — однако нет, оказывается и мы умеем писать в нудной манере о очевидных вещах.
0
Мне только что пришло в голову отличное словосочетание, характеризующее тенденции у многих представителей современной индустрии ПО. «Управляемая говенность» :) В корпорациях это еще политкорректно называется «good enough». Сотрудников никто по головке не погладит за то, что они все сделали круто, с легко поддерживаемой архитектурой и юнит-тестами. Молодцы те, кто сделал вчера и «good enough», и пусть оно говенное, главное чтобы не слишком…
+2
Sign up to leave a comment.
Как важно писать хороший код