Debitoor is hiring. No bureaucracy, no legacy code, no bullshit, fury continuous deployment, trips #js #node #react #mongo
×Закрыть

О качестве кода и профессионализме

На встрече ДОУ Егор Егоров делал доклад об «этике программирования» и о том, что писать плохой код нельзя. Код должен иметь тесты, документацию, обрабатывать всевозможные исключительные ситуации и т.п.


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


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


И совсем последний вопрос: как вы определяете профессионального разработчика? Тот, кто пишет качественный код? Тот, кто знает какого качества код у него получится? И связан ли профессионализм с качеством кода вообще?

Допустимые теги: blockquote, code, em, pre, i, li, ol, strike, strong, u, ul, a.
Ctrl + Enter
Допустимые теги: blockquote, code, em, pre, i, li, ol, strike, strong, u, ul, a.
Ctrl + Enter
Не знаю скільке вже років, але існує Software Engineering Code of Ethics and Professional Practice (коротка та повна версії на одній сторінці).
Отже, етика програмування включає в себе набагато більше ніж написання коду.

P.S. «Seek ground truth», панове.

Понравился график Потребности-Профессионализм.

На тему профессионализма разработчиков ПО, качества (пожалуй, проектов в целом, не только кода) и этики есть хорошее эссе Архипенкова www.citforum.ru/...ect/psychology (содержит определение профессионала)
Того же автора www.citforum.ru/.../antipatterns/ «Слова не мальчика, но мужа».

Рекомендую — не пожалейте времени на прочтение!:). Там же есть ссылки на подобное чтиво.

Достал с полки одну из любимых книг по программированию: Герб Саттер, Андрей Александреску, «Стандарты программирования на С++».
Цитата из предисловия:
В напряженной обстановке, при жестких временных рамках люди обычно делают то, чему их учили, к чему они привыкли... Когда на нас давит график работ..., мы работаем так, как приучены. Неряшливые программисты, которые даже при обычной неспешной работе не помнят о правильных принципах разработки программного обеспечения (а то и вовсе незнакомы с ними), при нехватке времени окажутся еще небрежнее, а их код будет изобиловать ошибками. Соответственно, программист, который выработал в себе хорошие привычки и регулярно ими пользуется, при «повышенном давлении» будет продолжать выдавать качественный код.
Доки писать не люблю — пытался когда-то, но слишком много времени уходит на поддержку их актуального состояния. Докстринги — пишу для public интерфейса. Поскольку они в самом коде, то читаются постоянно (и поддерживаются в адекватном состоянии). Юниттесты тоже пишу. В начале разработки подсистемы — много. Часть из них — dev acceptance. Оформленный как unittest пример использования, но таковым не являющийся. Потому что зависит от окружения (лезет в базу данных, общается с миром, требует предварительных настроек, исполняется долго). Не может быть исполнен на системе автоматического тестирования.
Потом — на каждое внесение новой функциональности и на каждый обнаруженный баг. Юниттесты — для библиотек. Чем выше уровень (ближе к пользователю) — тем юниттесты писать сложнее. У нас для этого fit тесты, и пишут их тестеры.
Хороший код — максимально простой, но не проще (почти по Эйнштейну). Меньше багов и проще понимать другим. Остальное дополняется простым человеческим общением (и работой в паре, конечно). Эффективно заменяет горы документации.
Вопрос «правильной» нотации для меня выглядит странно. В рамках модуля нотация должна быть единой, а дальше — как повезет. Уговорить всех — невозможно (мы используем библиотеки сторонних разработчиков, а у них тоже свои предпочтения). Да и не важно это. Ширина строк — должна вмещаться на экране вашего редактора. И если у всех программистов экраны по 32 дюйма — можно писать очень длинные строки.

P.S. Хороший код — не тот, который правильно работает в «стандартной» ситуации. А который надежно и внятно обрабатывает нестандартные — connection порвался, commit/validation не прошел... Все сложности программирования кроются именно в обработке ошибок — остальное, ИМХО, частности:)

2 Anton Naumov, мы не разошлись во мнении:). Вы конкретизировали систему целей («...важно, что бы продукт не только работал, но был прост в поддержке и улулчшении...»), которая является generic’овой в контексте следующих (будущих) проектов либо поддержке при текущего, и является, как раз, технической целью. Конечно, хорошо покрытый и документированный код, скорее всего окажется и более подходящим под более мощное множество целей. В этом смысле такой код более «этичен». Моё утверждение можно уточнить так: примерять к коду эмоционально-окрашенные атрибуты (этичный, хороший, плохой) и определять его качество вне контекста — это не практично, исходя из постанвки вопроса в теме: можно увлечься ложными (нецелесообразными) ценностями и перерасходовать энергию-время. Так что ответить на вопрос темы «как оценить, окупятся ли дальнейшие усилия...», вне контекста, как правило, практически нет возможности. Качество — это не абсолютная, а условная характеристика кода. Либо, тогда его (качество) надо определят через нечто инвариантное вроде коэффициентов покрытия юнит-тестами и т.п. А потом сопоставлять эти показателями с расходами и прочими внешними (по отношению к коду) вещами. В любом случае, профессионалы интересны не как «сферичекие кони в вакууме» (в том числе и друг другу), поэтому и подчёркнута важность контекста. Если в контексте стоит во главе угла технический аспект, как например, возможность использования кода другими, и все готовы на сопутсвующие этому затраты, то Егор Егоров прав на все 99% — это очевидно и статистически доказано. Поскольку командная разработка — явление весьма распространённое, то такая постановка «этики» оправдана. Главное, чтобы эти сопутсвующие затраты не стали самоцелью, а для этого и нужно понимание и контекста, возвращаясь к профессионализму. По теме: стандарты должны быть, но уровень следования ним, должен быть постоянно под контролем и сопоставлением с условиями внешней среды:)

2Андрей Фесуненко, в данном конкретном случае существует два и более мнения о том, что есть код, и что считать качественным кодом. если говорить с позиции бизнеса, целей и задач производства — то Вы безусловно правы. однако, с точки зрения бизнеса код есть абстракция, он не есть конечной целью и даже средством является опосредованно. целью есть получение бОльшей прибыли от автоматизации каких-то бизнесс-процессов, средством — программный продукт. код, с точки зрения бизнеса, есть неизбежное зло, и он просто должен быть и просто должен работать. иерархически, чем выше уровень абстракции субъекта, тем меньше требований непосредственно к коду, и больше к бизнес-задачам.

таким образом, я считаю корректным в данном случае говорить о коде на уровне абстракции Developer -> Senior Developer -> Tech Lean -> Architect, иначе говоря инженерных специалистов, которым важно, что бы продукт не только работал, но был прост в поддержке и улулчшении. задачи соотвествия продукта требованиям, ожиданиям и бюжетам заказчика решаются на уровне Project Manager -> Business Analyst -> QA -> Customer.

Чтобы ответить на вопросы темы, нужно сформулировать что такое «код». Предлагается определить так: код — это модель вычислительного процесса, записанная на формальном языке. Конечный пользователь (заказчик) потребляет не код, а вычислительный процесс (конфигурацию). То есть код, прежде чем стать процессом должен быть помещён в конкретный контекст (конфигурация + пользователь), пройдя в общем случае через ряд преобразований, которые, в общем случае (на самом деле, в большинстве случаев) не полностью контролируются командой.
Говорить о «качестве кода» в отрыве от целей, для которых он создавался (от контекста) — полная бессмыслица. Пример: код на 99, 9% покрыт юнит-тестами, а будучи компилированным и установленным у заказчика вызывает только возгласы: «это не то, что мне надо!».
Профессионализм в случае разработки ПО — это способность понимать контекст создаваемых моделей («кода») и, как раз, умение находить баланс в системе целей, как технического характера, так и не-технического (конечно, при всех прочих равных условиях и навыках команды. Признак профессионализма также в том, что необходимо уметь вываливаться из этого контекста и обозревать его не «изнутри», а «снаружи». То есть, кроме того, что создавать модели своей разрабатываемой системы (код), удерживать ещё и модель собственного процесса (метамодель), корректируя и то и другое в соответствии с системой целей.
Интегрально, более профессиональной командой можно считать ту, которая за каждый, отдельно взятый, промежуток времени меньшими усилиями добивается наибольшего продвижения в системе целей, удовлетворяя при этом как можно большее количество пользователей (не только с помощью кода:).

«Этичен» и «хорош» тот код, который будучи помещён в конечную конфигурацию, максимально удовлетворяет своего пользователя. При этом, если понадобится помещать код в конфигурацию другому пользователю, а вы к этому окажетесь не готовы, то это скорее «неэтичность» по отношению к себе в будущем или по другому «неэффективность» (а следовательно и непрофессионализм). Тогда в этом смысле код окажется «плохим», а команда «непрофессиональной». Это к тому что, понятие профессионализм и качество кода — вещи условные. Хотя, конечно и бесспорно, выполнение предусловий в виде best practices («стандаров»), повышают априорную вероятность быть профессиональным в указанном выше смысле. Но, думается, это НЕ необходимое и НЕ достаточное условие — это просто эмпирическое знание по множеству команд и проектов, которое НЕ обязательно сработает в каком-то конкретном случае и не обязательно является определяющим фактором в достижении целей конкретного проекта.

2Щетинин Сергей, хм, интересная идея, спасибо. попробую на практике, вобщем-то привентивное тестирование архитектуры в любом случае не будет вредным.,

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

Интересно, никогда не пробовал так систематизировать разработку, но последовательность выглядит разумной.
Насчет тестов к несуществующему коду. На самой ранней стадии, еще думая над API можно писать код который бы его использовал, уже на этом этапе могут стать заметными вещи что мол «так не выйдет сделать» потому что явно недостаточно информации куда-то передается итп. Этакий способ «думать руками». Код понятное дело не исполняется. В какой-то момент большая часть его закомментируется и можно писать саму либу чтобы код стал исполняться, по мере продвижения раскомментируя больше кода и добавляя всякие проверки. Тут же проявляются ошибки и есть такая рекомендация, чтобы еще до исправления или добавлять на эту ошибку тест-кейс или добавить в эту нашу программку какую-то проверку на внутренее состояние. В общем по мере работы над библиотекой вырастает несколько таких вот маленьких программ в каком-то приближении повторяющих будущее использование этой либы. В целом можно использовать их вместо тестов (но тут понятно никакой автоматизации) или превратить их настоящие тесты, что очень просто. Если либа совсем маленькая и тест-сьют у неё независимый то можно включать его в сам модуль.

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

2Щетинин Сергей, ну серебрянных пуль в нашей индустрии еще не отлили ни по одному вопросу. так что универсальных рецептов нет и врядли появятся. опять-таки здравый смысл рулит. я сам пишу код итеративно — сначала сам код; потом юнит-тесты потока success; потом добавляю в код логи, много логов, хотя сейчас хочу попробовать заменить эту стадию использование АОП; потом юнит-тесты потоков exception/error; потом документацию к API. собственно после этого считаю, что функционал готов. если мне приходится менять логику, я вместе с логикой класса меняю и API документацию. мне так удобно, уж не знаю правильно я делаю или нет.:)

p.s. насчет юнит-тестов все знаю, но не могу никак понять, как можно писать тесты к тому, чего еще нет:) по этому поводу буду рад совету:)

Всё-таки это тоже меняется от случая к случаю. Если работа организована таким образом что API замораживается очень рано, то почему бы сразу и доки не написать. У меня случай другой, я сам пишу огромные куски кода и получается какое-то время имею полный контроль как на поставщиком API так и над его потребителями. Это позволяет подкручивать его чтобы исправить недочеты или включить новые находки. Момент когда всё «just right» и есть момент когда я считаю уместным писать доки (какие-то мелкие доки правда и по ходу пишу). Когда этот момент наступил понятно только интуитивно, не могу представить чтобы можно было найти ему какие-то формальные критерии. Ну и конечно нужно чтобы были «час та натхнення» =)

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

  1. документирование API, пишется программистами и изменяется вместе с кодом. на это уходит не так много времени, если делать все одномоментно. тоже справедливо для юнит-тестов. и эти же процессы занимают колоссальное количество времени, если делать их постфактум.
  2. guides, help, возможно финальные диаграммы классов. кроме диаграмм классов пишется техническим писателем в соавторсвте с программистами после завершения итерации. разумеется эта работа должна быть оплачена заказчиком.
Я так понял вопрос на самом деле не только в именовании и форматировании кода. С одной стороны я согласен что качественный код это хорошо, особенно потому что облегчает будущую работу с ним. Но с другой, я не согласен с постановкой вопроса что кто-то «должен». В каждом случае по разному же, понятно что опытный разработчик и одноразовый скрипт напишет гораздо внятней чем новичок, тут вопрос о «должен» не стоит, и не писать же к нему сразу доки и тесты. Точно так же и в бОльших проектах что оправдано, а что нет становится ясно с опытом. Я вот как-то писал документацию сразу вместе с кодом — код буквально через пару дней придумал как повернуть лучше, документация получается насмарку или вообще будет устаревшая лежать путать. Т.е. по факту выясняется что писать доки сразу глупо.

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

стандарты качества на самом деле одинаковы для всех. если соглашения по написанию кода описанные в стандартных Code Conventions, эти соглашения можно слегка модфицировать на уровне конторы (для Java я все-таки предпочитаю 4 проблема в табуляции вместо 8 и 120 символов в строке вместо 80). все остальное — Camel-style notation, понятные имена классов и переменных, JavaDocs — не изменяются ни за что и никогда. даже если заказчик явно не требует такого кода, он всегда рад такой код видеть. более того, это однозначно полезно для проекта в целом, для команды вообще. юнит-тесты и обработка исключений полезны для проекта почти всегда (единственным известным мне исключением является софт для мобильных дейвайсов, где ручное тестирование по соотношению цена/качество значительно эффективнее эмуляции всех сред для юнит-тестов, хотя наверное и тут возможны варианты). и опять таки, даже если заказчик этого не требует, то имеет смысл это делать, проект без базы юнит-тестов мегадорог в поддержке, это случай из моей практики.

  1. да, команда должна стремиться писать качественный код
  2. да, я определенно уверен, что хороший код лучше плохого. хотя бы только потому, что а) плохой код очень не понятен, а следовательно его тяжело поддерживать и улучшать; б) очень часто внутри плохого кода кроются ошибки дизайна, влияющие на стабильность и производительность приложения и эти ошибки очень тяжело выявлять.
  3. самый простой способ выяснить, окупятся ли дальнейшие улучшения кода — peer review. если новому человеку, знающему язык, понятна структура, назначение и алгоритм, если новый человек-эксперт не нашел при review откровенных lack of desing, то можно на этом этапе остановиться. хотя если такового человека нет, то сильно помогают наборы метрик, которые можно сбаллансированно настроить.
  4. любые стандартны всегда определяются с точки зрения common sence. в идеале — это экспертная группа, которая вырабатывает правила написания кода, действующие в компании по-умолчанию. чаще всего — начинает кто-то один, остальные обсуждают и дополняют. если заказчик не предлагает своих метрик — действуют конторские или командные, если речь идет о команде контракторов-удаленщиков.
  5. профессионал — тот кто пишет качественный код. т.е. код соотвествующий на 75−90% публичным Code Conventios. безусловно, качество кода напрямую связанно с профессионализмом и квалификацией разработчика. иначе говоря, если человек высокопрофессионален, он пишет качествнный код. обратное НЕ верно. это лишь один из параметров, который отличает профессионала он не профессионала.

Подписаться на комментарии