Что влияет на качество продукта и на время, которое на него затрачено

Меня зовут Денис Деркач, и я сотрудничаю с Dev.Pro в роли Senior Software Engineer. В этой статье я хочу рассказать вам о том, какие практики используют разработчики в мировом комьюнити и что нужно учитывать, чтобы разработать хорошее приложение в адекватные сроки.

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

Когда можно считать, что с нашим приложением все в порядке?

Есть несколько критериев, по которым стоит измерять то, насколько качественным можно считать код.

  • Код исполняет задуманное. Даже если можно поспорить с тем, что функция важнее формы, вряд ли получится опровергнуть то, что функция является основополагающей. Если код не исполняет задуманное, то это проблема.
  • Следует одному стилю описания. Лучше, когда код написан в одном стиле — так будет легче и вам, и коллегам, которые будут взаимодействовать с ним после вас.
  • Его легко понять. Это важный пункт, поскольку с этим кодом в дальнейшем будут взаимодействовать специалисты разного уровня, и стоит учитывать, что не все смогут разобрать тяжело написанный код.
  • Наличие документации. Код может меняться, и единственное, что позволяет нам понять, как правильно поступать в разных ситуациях — это документация, которая сохраняет много времени и нервов. Поэтому вести ее следует регулярно.
  • Код может быть протестирован. И желательно, чтобы сделать это можно было без рефакторинга, ведь рефакторинг — это дополнительный риск.

Практики, признанные мировым комьюнити

Принцип YAGNI. С английского аббревиатура расшифровывается как «You aren’t gonna need it». Идея принципа заключается в том, что не стоит реализовывать возможности, которые не были описаны в требованиях к системе. Придерживаясь этого принципа, заказчику не придется оплачивать лишние функции, а разработчики не потратят свое время на реализацию ненужного компонента.

Fail fast. Этот принцип утверждает, что проверять инпут стоит как можно раньше. К примеру, у нас может быть UI и бэкенд, и оттуда нам могут отправлять определенные данные, которые должны сохраниться в базе данных. В теории мы можем оставить валидацию на уровне базы данных, и БД подтвердит, что эти данные не валидны и их не стоит обрабатывать. Но если подумать о том, какую длинную цепочку прошел невалидный инпут от юзера, браузера и до базы данных, то сделаем вывод, что обработка инпута на UI заняла бы значительно меньше ресурса.

Защита кода. Всегда нужно писать код секьюрно, не забывая о разных видах атак, ведь даже в небольших продуктах можно столкнуться с проблемами такого рода. Существует два надежных способа избегать атаки: использовать только проверенные пакеты и выполнять проверку своего кода на наличие уязвимости. И то, и другое может предотвратить большие проблемы в будущем.

Используйте рефакторинг по предназначению. Сперва нужно оценить риски и понять, к чему рефакторинг может привести. Код, который вы видите, не обязательно плохой изначально, он может быть просто написан по-другому. Рефакторинг же стоит делать, когда есть риски в коде.

Работайте с tech debt. Когда мы видим часть, которую стоит улучшить, то очень важно опираться на существующие процессы в команде и говорить о них. Оптимально, если в команде выделяется время для работы с техническим долгом. Порой заказчик не видит необходимости переходить на новый тест-фреймворк, аргументируя это тем, что существующий также рабочий. Но по итогу техдолг может привести к проблемам в приложении.

Нефункциональные требования и способ их описать

Нефункциональные требования — это точные критерии, определяющие, как система должна работать. Они включают в себя системные атрибуты, которые устанавливают, что система может и не может сделать.

Главные типы нефункциональных требований включают в себя:

  • вместимость;
  • масштабируемость;
  • эффективность;
  • доступность.

Представим, что мы разрабатываем бэкенд и понимаем, что выдержим 1000 реквестов в секунду. И хорошо это понимать и учитывать, но задача усложняется, если мы никогда об этом не думали. В таком случае 100 реквестов, свалившихся на голову, могут принести много нежелательных проблем.

Как же тогда описать нефункциональное требование, если у вас его на проекте нет?

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

Как разработчики мы не знаем точно, что случится с нашим бэкендом, если он получит 10 000 реквестов в минуту. А это значит, что лучше еще до начала использования приложения сделать performance test и утилизировать имеющиеся тулы для того, чтобы определить нефункциональное требование. Если в той точке мира, где клиент использует приложение, завтра будет праздник, то мы можем предположить, что стоит ожидать много реквестов. И у нас есть два варианта: либо показать клиенту цельную картину, указав, сколько реквестов система точно выдержит, или заранее предложить помощь и готовность подключиться в любой момент и решить проблему, если такая нужда возникнет.

Что еще влияет на качество и время, затраченное на разработку?

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

Работа в команде, где мы можем поделиться своим мнением, может улучшить конечный результат продукта. Часто бывает, что мы не можем сказать о своих болях и не знаем точно, к кому можем подойти и поговорить. Сложности, с которыми разработчики сталкиваются, могут быть с разными и касаться не только кодинга, но и профессионального и личного развития, что тоже влияет на производительность специалиста и, как следствие, всей команды.

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

Еще один важный пункт в разработке — release cycle. Он дает более точное понимание того, когда наша работа должна быть закончена. Если этого нет, то создается впечатление, что неважно, когда будет релиз, и мотивация падает. Помните: Less fire is always better than more fire, поэтому планирование и подготовка имеют значение.

Разработчики — разрабатывают

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

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

Если чего-то нет, то значит ли это, что наше приложение плохое?

В предыдущих главах мы обсудили best practices и условия, при которых работа будет выполняться наиболее эффективно и быстро. Но должны ли мы считать, что наше приложение плохое, если нет какого-то из перечисленных ранее пунктов?

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

Поэтому вопрос, который всегда стоит задавать себе: «Пробовал ли я что-то изменить в приложении?». Если, к примеру, вы видите, что используется старый тест-фреймворк, который не поддерживается, то первое, что следует сделать — поговорить с кем-то из команды. Это уже шаг в сторону того, чтобы ваше приложение стало лучше. Скорее всего, после этого проблема решится. Главное — говорить, если вас что-то беспокоит в коде.

Если же вы сделали все, что могли, но вас не слышат, есть несколько решений:

  • Продолжить работу.
  • Взять отпуск.
  • Найти ответ на вопрос, почему так происходит.

Представим: мы хотим улучшить наш CI/CD процесс и добавить pull-request jobs, и оцениваем эту задачу примерно в одну неделю. Стоит помнить, что нужно подготовить весомые аргументы, прежде чем идти с предложением к менеджеру или клиенту. Примеры плохих аргументов:

  • Так делается везде.
  • У меня было так на предыдущем проекте.
  • Мне это нравится/не нравится.

Вместо этого вы можете сказать: «Мы потратили Х часов и Y часов на исправление ошибок. В сумме мы потратили Х + Y часов на решение определенной проблемы, и я уверен, что если мы выполним эту задачу, то в будущем у нас таких проблем не будет».

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

Далее важно понимать, в каком состоянии сейчас находится проект.

  • Если команда сейчас часто сталкивается с проблемами в продакшене, то, скорее всего, улучшение CI/CD не стоит в приоритете.
  • Стоит уточнить, может ли заказчик выделить вам время и входит ли это в бюджет.
  • Понять, есть ли человек, который может это осуществить технически, и кто именно сможет это сделать.
  • Выбрать момент. Просите рассмотреть вашу идею в те дни и встречи, когда это уместно.

Как найти баланс и писать код, который удовлетворит и разработчика, и заказчика?

  1. Всегда держите фокус на том, в каком состоянии находится ваш проект. Если он длинный и должен выехать в продакшн через год, то есть время, чтобы использовать все best practices. Если же это proof of concept, то тратить много времени — это не совсем то, что нужно продукту, и приемлемо, даже если там будет несколько багов, поскольку этот продукт только тестируется и его работоспособность только определяется.
  2. Старайтесь готовить эстимейты. Реализация чего-то более сложного — это дороже, так как занимает больше времени. Тем не менее это может сэкономить еще больше времени и денег в будущем, поэтому риски стоит учитывать заранее.
  3. Определитесь, какие именно best practices из тех, которые вы хотите применить к продукту, действительно важны и без них никуда, а от чего можно отказаться. Один из трюков — стараться делать два эстимейта на какую-то большую задачу. Тогда это даст вам видение того, что можно улучшить и как этого достичь оптимально.
  4. Просите фидбэк и общайтесь с участниками команды. У вас может быть большой опыт, но все равно есть моменты, которые вы один не всегда можете учесть.

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

👍НравитсяПонравилось6
В избранноеВ избранном5
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Забыли про главный момент. 50% успеха правильно поставленное задание.

Главные типы нефункциональных требований включают в себя:

вместимость;
масштабируемость;
эффективность;
доступность.

Все-таки цікаво, як ви в своїх проектах описуєте ці вимоги? І як їх перевіряєте?

Код может быть протестирован. И желательно, чтобы сделать это можно было без рефакторинга, ведь рефакторинг — это дополнительный риск

А якщо код може бути протестований, але тестів немає, то продукт якісний чи ні?

то сделаем вывод, что обработка инпута на UI заняла бы значительно меньше ресурса.

Валідація вхідних даних може бути досить складним завданням і частиною бізнес-логіки. Ви в своїх проектах пишете бізнес-логіку в UI?

и выполнять проверку своего кода на наличие уязвимости.

Цікаво, а як ви це робите? І у вас в проекті закладається час під таке тестування?

Используйте рефакторинг по предназначению. Сперва нужно оценить риски и понять, к чему рефакторинг может привести

Взагалі-то рефакторинг призводить до спрощення коду та зменшення складності дизайну. А до чого він ще може привести?

Как разработчики мы не знаем точно, что случится с нашим бэкендом, если он получит 10 000 реквестов в минуту.

А чому не знаємо? Є десятки утиліт для performance тестування, їх налаштувати і запустити для найпростішого тесту з 10000 запитів/секунду — це 10 хвилин роботи.

какие практики используют разработчики в мировом комьюнити

Мені здається, краще було б описати практики, які використовуються у вас в команді/компанії. Світові практики і так вже описані мільйон разів.

Есть несколько критериев, по которым стоит измерять то, насколько качественным можно считать код.

У заголовку йдеться про якість продукту. Або це те ж саме, що і якість коду?

Код исполняет задуманное

Мені чомусь здається, що код, що не виконує задумане, не те щоб неякісний. Він просто не правильний.

Следует одному стилю описания.

А звідки цей стиль візьметься? Який наприклад в ваших проектах використовується стиль?

Его легко понять.

Мені здається, що тут треба більш жорстку вимогу — щоб його було легко змінити

Наличие документации. Код может меняться, и единственное, что позволяет нам понять, как правильно поступать в разных ситуациях — это документация, которая сохраняет много времени и нервов. Поэтому вести ее следует регулярно

А хто цю документацію буде підтримувати? І що це за документація? Якщо це про архітектуру системи, то така потрібна. А якщо це коментарі до коду, то тут не згоден. Якраз світова практика говорить, що код повинен бути self-describing

Главные типы нефункциональных требований включают в себя:
вместимость;
масштабируемость;
эффективность;
доступность.

Это точно все возможные типы NFR?
И как по-английски звучит «вместимость»?

Это основные типы не функциональных требований.
вместимость — capacity

А що таке capacity наприклад для REST сервica ?

"

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

"

...ну, я би тоді питання якості продукту віддав відділу якості, у якого в цьому плані найвища експертиза, а розробники б займалися своєю роботою в більшій мірі. Кажу «в більшій», бо як ми пам’ятаємо за якість відповідає вся команада звісно.

А загалом, викладення думок направлено в даній статті лише по відношенню до коду в основному.
Що теж недокінця комільфо. Такими голосними заголовки неварто робити

По поводу «качества» самого кода:

Фактор № 0: Документирование НАМЕРЕНИЙ. Напишите, что должен делать код, и цена ошибки упадёт на два порядка. Её быстро найдут и быстро исправят. А скорее всего — сразу покроют тестом тест, и это будет правильный тест, а не имитация.
Фактор № 1: Именование сущностей. Чем дальше область видимости, тем длиннее должны быть имена. А кто назовёт переменную с дальней видимостью в 3 буквы, типа NHZ, CVP и так далее — типа это ж «всем понятно» — запакуйте его в скотч, в мешок от боксёрской груши, и отдайте Кожаеву на час.

Фактор № 2: Разделение на блоки. У человека память оперативная очень короткая, зато гиперассоциативна. НЕ ЗАСТАВЛЯЙТЕ читать кучу херни, память будет исчерпана очень быстро, ассоциации затёрты, и всё остальное будет восприниматься мусором. Код не нужно читать, его нужно видеть, что и зачем, без разбора. Для того и документация — кстати, её тоже нужно НЕ читать целиком, пишите вменяемые заголовки.
Не {
размазывайте (
&говно
по >
тарелке.
— не получите говнокод на выходе. Да, код богатых фирм, внезапно, тоже может быть говнокодом. И писанным очень даже индусами, в лучшем случае румынами. А вы на него анонируете как на образец вселенской мудрости.

ЗЫ. Лучший эксперт по качеству кода — это админ. Сам он код уже не пишет (он так думает, на деле он тоже кодит), но вынужден своими руками взвесить цену ошибки. Потому, сделайте доброе дело: оставляйте контакты или адреса площадок, где админ сможет дать вам обратную связь. Если бы я ставил пиво каждый раз, когда они экономят мне день работы — они бы спились.

Влияние № 0: Насколько уникальную вещь вы творите? Разница по затратам времени в 100 раз и более. Грубо говоря, код одной и той же сложности, но зависимо от того, давно ли вылизанный, может быть выполнен либо гуру самостоятельно (и не мешайте ему), либо командой обезьян по 500 баксов за штучку.

Потому, хотите взять профит — ищите то, что совсем недавно ушло в серию. Где цена ещё не успела упасть, а затраты упали радикально. И помните, что время играет против вас.

Разумеется, львиную долю этого профита берут большие галеры, способные быстро переформатировать команды. Вернее, ЗНАЮЩИЕ, что они на это способны (бюрократизм весьма мешает этому знанию). Либо маленькие галеры, умеющие делать вид, что они большие и зрелые.
--------------------------------
Фрилансерам же, увы, эта ниша не светит. Мы берём вкусняшку в другом месте: когда галера закончила работу, зачастую дальнейший саппорт в плане изменения стоит неоправданно дорого — потому что команда давно переведена в другой проект, а тот кого посадили на саппорт — совершенно левое чучело. А галера выставляет рейт как за капитана. Вот собственно фрилансер и говорит, что давайте я вам за вменяемый прайс прикручу свистелку-перделку, покрашу холодильник в чёрный цвет, а для чего — а просто так. Притом не задавая лишних вопросов, кроме одного: получится так-то и так-то, уверены ли что это стоит сделать. Если клиент уверен, что получится по-другому, то он либо готов слушать и обсуждать (коротко, разумеется, до 1/8 времени исполнения), либо он не клиент — за конфликты мне не платят.

Влияние № 1: Экспертиза заказчика. Знать чего хочешь — половина дела, а то и 3/4. А если ещё и проверить может, и видеть на ранних стадиях когда дело идёт не туда, когда делают то, что делать не нужно... в общем, работать без головы тяжёло. А когда вместо неё жопа с позицией «вы сделайте, а я вам заплачу если мне понравится» — вот прям сразу готовьтесь к задаче подключить юриста. А то и просто послать нахер такого клиента, потому что такие формируют выгорание команды. Велосити упадёт и для следующих проектов, а оно вам надо?

Влияние № 2: Цена: время и деньги. Внезапно? Если вы подождёте чуточку дольше, мы обслужим вас чуточку лучше. Но разумеется, не имейте дел с реселлерами. Вас тупо продадут индусам, и сольются раньше чем задача будет допилена.

Ну и вишенка на тортик: НЕ ДОПУСКАЙТЕ оценивать качество посредников в работе. Качество может оценить только тот, кто пользуется продуктом. В лучшем случае у работы есть какие-то показатели. При желании такие показатели можно сделать (требуется экспертиза менеджмента заказчика). Но когда лезут оценивать те, кто не в зуб ногой в деле, ждите качества «на два с плюсом». Это когда делают «на три с минусом» (главное сроки, а «потом» допилим, но выделения сроков на «потом» не существует), и первая же бага обрушивает лавину неудовлетворения. Мнение, что продуктом невозможно пользоваться, искоренять вы будете долго и дорого, даже если допилите.

ЗЫ. Заткните рот ссаной тряпкой всем, кто кричит про MVP. Есть крайне ограниченное пространство рынка, где MVP оценят. Там, где только вы, и других нет (либо они такие же). Во все остальные дела вы с недоделкой только суньтесь — замахаетесь убытки считать. Одни затраты на продажи выйдут дороже профита.

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