There are 999 reasons to become levi niner. Find yours at levi9.com/jobs
×Закрыть

Метафора системы: как повысить качество кода

Всем привет!

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

Итак, если вы пишете «Hello world», вы вряд ли столкнетесь с большинством трудностей, описанных ниже. Если вы занимаетесь небольшими проектами, то, скорее всего, найдете в себе силы преодолеть эти трудности за счет морально-волевых качеств и аналитических способностей. Но если вы, как и наши команды разработки в Terrasoft, работаете над большим продуктом или множеством проектов, развивая код в течение длительного времени, вопросы, о которых мы поговорим в статье, могут стать первоочередными, а их неверные решения — блокирующими любую полезную деятельность команды. В этой статье будет много слов, которые, я надеюсь, позволят вам сэкономить много строк кода. Итак, давайте начнем.

Определение метафоры системы

Для начала давайте посмотрим на классическое определение метафоры, описанное в практиках экстремального программирования (XP), к которым приходят компании и команды, занимающиеся разработкой в течение длительного времени и требующие систематизации такого опыта. Мы уже прошли очень долгий путь становления процессов разработки — и, маленький спойлер, эти процессы всегда модифицируются, и нет финальной точки. Расскажу о некоторых этапах внедрения метафоры в систему на конкретных примерах.

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

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

Википедия

Итак, метафора системы. С одной стороны, определение очень общее и не совсем понятно, как им пользоваться, с другой — широко распространенной информации по данному подходу, в отличие от других практик, например TDD, Pair Programming или CodeReview, не очень много, и постигать саму концепцию приходится скорее на практике.

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

К практике

К сожалению, без изначальных вводных подойти к теме метафоры системы довольно сложно, поэтому давайте перейдем к действиям над живым кодом. Примером послужит тот же проект, что и в статье по объему кода, который мы в компании Terrasoft разрабатываем для облегчения работы с внутренними задачами. Сразу определимся, что в данной ситуации нам интересен именно ход изменений и логика их появления, а не конкретное состояние кода в отдельно взятый момент времени. Всем, кому будет интересно обсудить технические аспекты реализации именно проекта, я с радостью отвечу на GitHub-e или по личным каналам, указанным в LinkedIn.

Первое знакомство или структура проекта

Итак, давайте посмотрим на проект с точки зрения структуры классов и файлов.

Я думаю, что многие из нас (а может, вообще все) при работе с такой структурой испытывают желание преобразить ее. Давайте разберемся, что тут не так. Первое, что бросается в глаза, — это плоский список, содержащий в себе названия, не объединенные общей логикой.

Класс Program лежит на уровне с классом PackageConverter и тем самым говорит, что в нашем проекте эти два понятия не разделены на организационном уровне. Т.е. первым признаком отсутствия метафоры системы является структура файлов, следующий признак уже находится на уровне кода, и замечание касается организации namespace-ов, которые используются в рамках проекта. Вот наглядный пример кода, который иллюстрирует взаимосвязь названия файла и его внутренней структуры:

В классе Program добавлено 18 namespace-ов. Вспомним распространенное правило: много зависимостей в классе — это плохо, и это говорит о наличии сильной связности в рамках данной реализации. При этом, если мы посмотрим на количество строк в коде класса, эта цифра близится к 1000, и это уже само по себе становится проблемой даже просто при навигации по нему. Давайте вернемся к вопросу введения метафоры и посмотрим, как отражается ее присутствие на коде.

Тот же проект, те же люди и класс с менее общим названием. Вместо 18 using-ов всего 4, количество строк меньше почти в 5 раз. Вы можете самостоятельно убедиться, что остальные классы проекта будут в разы меньше и проще, чем класс Program. Как же получается, что разработчики в одном и том же проекте пишут код, который так ощутимо отличается по качеству? Все дело в том, что в рамках проектирования отдельно взятой функциональности каждый применяет свои умения без ограничений, а при сведении результатов работы изначально отсутствует договоренность и общие принципы того, как это делать. Если кто-нибудь из вас встречал понятия архитектурных максим проекта — это как раз одно из их проявлений.

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

Предметная область

Итак, давайте посмотрим, какие понятия из нашей предметной области отсутствуют на данный момент в структуре проекта, и постараемся их добавить. Первое, что приходит мне в голову, — это отсутствие понятия Command (а ведь CLI = Command Line Interface :) ). В проекте присутствует класс CommandLineOptions — в нем сосредоточено описание всех параметров для всех команд. В результате чего любому разработчику ничего не остается, кроме как дописывать сами команды в класс, который этого не запрещает напрямую. Новые и новые строки кода добавляются в файл, в результате чего получается своеобразное ассорти, но при этом стоит отметить, что даже такое название класса однозначно определяет его назначение, и вы не встретите в проекте описание параметров команд в другом месте.

Обратите внимание, что объем этого класса не очень большой с одной стороны, а с другой — количество using-ов в нём очень умеренное. То, что внешние показатели класса не кажутся очень пугающими, обусловлено тем, что у него довольно конкретная область ответственности, заложенная в его названии. Это значит, что все разработчики одинаково интерпретируют и используют его в своей работе. Однако давайте построим связи дальше и рассмотрим, как же этот класс связан с упомянутым выше классом Program, который содержит почти 1000 строк. Если мы для описания команд имели хоть мало-мальски выделенную структурную единицу, то для реализации самой команды такой структурной единицы нет. Всю реализацию команд мы найдем в классе Program.

Проблема файлов, которые агрегируют различные классы, сродни проблеме множественной ответственности. Зачастую такие классы визуально от вас скрывают проблему структурной организации кода (стоит отметить, что для вскрытия или обнаружения такой проблемы можно использовать инструменты, встроенные в IDE, которые отобразят диаграмму классов проекта) Данная проблема очень часто встречается в проектах, где есть классы или файлы, названные с помощью общих слов, которые не уточняют их предназначение и не помогают разработчикам идентифицировать ответственность класса в изначальном плане. Например, это Tools, Utilities, Extensions, Helper и им подобные. Часто, рождаясь в проекте как временные, они могут обрастать функционалом, поскольку уже подключены в места, откуда этот функционал можно вызвать — или, что еще хуже, приводят к ситуации, когда возможности использовать полезные функции в этих классах без сложной инициализации зависимостей просто нет. Однако не стоит сразу отчаиваться, если в своем проекте вы столкнулись с данной проблемой. У таких файлов есть одна интересная особенность, о которой нужно помнить и стараться использовать при изменении структуры кода: они легко разделяются при введении метафоры всей системы или хотя бы в отдельно взятой её области. Этот эффект вызван как раз тем, что код внутри такого файла часто бывает очень слабо связан между собой ввиду того, что относится к разным задачам. В тех же местах, где использование такого кода есть, это решается с помощью приёма в рефакторинге выделения нового класса.

Глаза боятся, а руки делают

Теперь давайте попробуем ввести понятие Command в существующий код, для начала только на уровне структуры файлов и директорий. И сразу перенесем туда файл CommandLineOptions.

С точки зрения организации файлов, даже эти действия уменьшают ассорти файлов в корне проекта, и теперь каждый, кто захочет написать новую команду, обязательно откроет этот каталог. Давайте поставим себе цель — для определения/изменения логики команды работать только в этом каталоге. Хочу обратить внимание на то, что по умолчанию IDE нам начнет помогать структурировать наши мысли в области кода:

...при добавлении класса в директорию сразу генерируя для него составной namespace, который включает в себя название директории (поведение, кстати, может быть изменено в настройках проекта). Этот нехитрый прием позволяет вам получать уже на уровне классов систему именований, которая складывается при правильном выборе названий директорий в понятные лексические формы. Более детально о принципах выбора имен можно прочесть, например, в книге

Стоимость и временные затраты на такое действие — ничтожно малы. Создаем класс AppListCommand и переносим из класса Program реализацию метода ShowAppList.

AppListComand

Program

Давайте рассмотрим, что произошло со структурой кода после этих операций, на которые мы потратили всего пару минут:

  • класс Program стал на 10 строк меньше;
  • класс настроек CommandLineOptions стал меньше на 4 строки;
  • функционал отображения списка настроек теперь можно использовать из других мест.

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

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

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


До
После

Вывод

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

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

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

LinkedIn

32 комментария

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

Той випадок, коли важко натягнути сову на глобус (згадуючи, як працювала bpmonline) :)

Метафора системы
Архетип кластера
Эгрегор CI/CD

>Но это неудобство вызвано возможностями внешней библиотеки, адаптацию кода которой я не планировал в рамках этого упражнения.

На самом деле возможность такова есть, но вам нужно самому сделать абстракцию ICommand, которая включает опции, и делать потом .WithParsed(c => c.Execute()).

Но как раз из-за отсутствия четкого идиоматического подхода, я и написал CliFx чтобы решить проблему «миллион способов сделать одно и то же». Там бы просто не получилось писать код в Program.Main хотя бы потому что точка вызыва ICommand.ExecuteAsync() форсируется архитектурой библиотеки.

Как вы очень осторожно начали с малого.

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

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

Уверен мы найдем больше интересного если перейдем к следующему шагу.

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

А вот тут в полный рост встает вопрос описания предметной области и именнования, я не говорю что хорошее именование инфраструктурных примитивов не важно (термин «компонент» — вообще превратился в слово-паразит) , просто инфраструктура часто стабильна и под полным контролем малой группы программистов, а вот реализация задач предметной области — динамична и под влиянием групп с другими ролями — и тут уже давайте говорить про domain mapping и ubiquitous language.

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

А если не использовать try-catch а возвращаемое значение вместо этого то всё станет ещё лучше, короче и чище. 2019 на дворе а все пользуются этим черезмерно громоздким синтаксисом, сколько можно то? Почему нельзя сделать возвращаемый тип Try и использовать в тех местах где возмножна ошибка? А если ошибка доменная то почему не использовать Either? Зачем люди используют жуткие конструкции из форов и прочих циклов если можно использовать map, flatMap, collect и т.д.? Зачем люди используют if(foo == null) если можно использовать Option и тот же набор map, flatMap и т.д.(null условный оператор очень убог по сранвению с Option)? Зачем использовать await когда можно использовать Future или IO? Зачем люди пишут по-дефолту синхронный код а потом обмазываются awit’ами или RX’ами и получают на выходе тяжеловаримую чертовщину, когда можно пользоватся эффектами? . Зачем люди пишут json кодеки и другую серилизацию руками когда есть деривация?

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

Ну а вообще, то книга о том как сделать свой код лучше с конструктивом и без воды уже написана и довольно давно: github.com/...​memcpy/milewski-ctfp-pdf, и многие примеры отсюда можно переносит прямо на сишарп, правда с более громоздким синтаксисом.

буквально на днях заходил по этой ссылке из статьи про монады))

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

Непринужденно это громко сказано, во многих случаях это еще более убого чем тот же null. Возьмем reduce, как ты его сделаешь в чистом виде в c#? Только с анонимными объектами или используя литеральный LINQ синтаксис с несколькими from’ами. В случае с монадами, в C# не поддерживается полимиорфизм высшего порядка, поэтому приходится исхищряться с интерфейсами или преобразованиями. Каррированные функции в C# писать вообще нереально, чтобы это выглядело понятно, так как везде будет Func<Func<Func<...>>>.

C# своими базовыми принципами задает стиль, в котором на нем пишут. Если каждый проект будет начинаться с того что нужно подключить несколько библиотек для того чтобы можно было писать «как надо», то он превратится в что-то типа JS с lodash и подобными. Если хочется писать в фукнциональном стиле на .NET, есть F#.

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

правда с более громоздким синтаксисом.

Вот это и есть ответ на все твои вопросы выше 🙂. Посмотри что Mark Seemann делает с C#. Идеи хорошие, но от C# мало что остается и превращается в нечитаемое нечто. Если начинать заморачиваться тем, то ты написал, то стоит переходить хотябы на F#.

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

По поводу качества кода:
Работал как-то в небольшом проекте лидом. СТО тоже говорил о качестве кода. Людей катастрофически у нас не хватало.СТО вызвался помочь. Написал и отдал мне на код ревью. Я написал комменты, что исправить. Он посмотрел на это и сказал — не буду ничего исправлять, у меня другие занятия есть, сам все исправишь.Поэтому рассказывать как надо делать и делать — это 2 большие разницы.

Олег, на самом деле если посмотреть на то что сделал CTO из данной истории, то он помог создать лучший код, создав первичный работающий вариант, и да процесс работы с кодом не заканчивается на его первом варианте, или правками в ревью. Для того чтобы код с которым идёт работа стал лучше, это должно быть в культуре команды. Есть так называемой правило бойскаута — если ты пришел в лес, оставь место стоянки чище чем оно было до тебя. В нём не регламентируется насколько чище и вы можете хоть одно улучшение сделать хоть 10 за один раз, но если его придерживаться в ходе работы над проектом постоянно вы получите очень приятный ландшафт для работы. Мы например такой подход вовсю применили в одной из задач где надо было после изменения CodeConvention поменять много разных файлов. Сработало на ура :)

Владимир,
я же не говорю,что СТО слелал что-то бесполезное. Мой поинт в том, что он отказался делать то, за что сам ратует. Розиция такая типа мессии: все должны делать, но сам он не делает.
Мне кажется, если за что-то берешься — то делай до конца.

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

Головне, щоб всі зміни призводили до покращення продукту.

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

Все куда банальнее и проще. GitlabCI + Helm + Kubernetes и получается zero-downtime deployment, еще и бабло на серверах экономим благодаря автоскейлингу.

еще и бабло на серверах экономим благодаря автоскейлингу.

то вашему клауд провайдеру скажите спасибо, а не куберу. из-за zero-down time deployments брать кубер напостой тоже выглядит не особо разумно — если уже в клауде то на всем готовом сделать zero down time deployment можно на любом paas хостинге веб-апки без особых усилий на развертывание окрестратора и работу с контейнерами.

Zero downtime делается элементарно даже с простым Octopus Deploy на своих серверах 🙂.

Андрей, привет :) Почитав эту ветку комментариев хочу отметить одну вещь которая касается zero downtime — для того чтобы приложение было действительно ZERO DOWNTIME вам не достаточно инструментов CI/CD вы должны ещё в коде придерживаться особой разработки. Например одно из правил, если вы работаете с данными пользователей и выкатываете новый их формат, то вы должны писать сразу в два формата пока не убедитесь что новый механизм работает без ошибок. В противном случае у вас большой риск лишится всех данных попавших в вашу систему с момента когда был применен новая версия, до момент исправления или отката на предидущую. Этого не стоит забывать в проектах с такими требованиями.

Оці ваші неймспейси з маленької літери залишають враження що до стану дотнетчиків пробрався джавіст і щось мутить )) Подивився на фігурні дужки — точно джавіст ))

По суті статті — колись у давні часи існувало поняття Code Convention. Зараз це назвали Метафорою Cистеми. Ну ок. )

Алексей, мне кажется что CodeConvention решает проблему кооперации над кодом фокусируясь немного в другой области, но некоторые части по реализации Метафоры могут быть донесены и через CodeConvetion. По поводу стиля скобочек и названия, то сказывается разработка на JS и C# :) и если честно, я на нем не зацикливаюсь, особенно ввиду тех возможностей которые позволяют современные IDE

Ну ви ж готуєте статтю, дивитесь на свої картинки... невже не спадає на думку, зробити якісно? Тим більше, що сучасні IDE дозволяють зробити це менше ніж за хвилину. Тим більше, що ви взялись писати про якість коду.
На жаль, прочитавши статтю, я не відчув гострої необхідності введення поняття Метафор. А ось давно відомі та загальновживані домовленості про стиль коду та дизайну одразу спали на думку після прочитання.

Олексей, я готовлюсь к статье не на рафинированных примерах, а используя живой код, которые не идеален и я это признаю :) Есть одна маленькая причина к тому что в коде пока нет единого стиля форматирования — эта причина в том что мы до него просто ещё не договорились, и это кстати хорошая иллюстрация того что проблемы с которыми мы столкнулись и которые нас стали волновать в первую очередь они лежат немного глубже чем форматирование. Но я прекрасно знаю про правило разбитых окон, поэтому такой стиль обязательно у нас появится.
P.S: в последнее время не могу определится какой из стилей написания мне сейчас больше по душе, вроде и C# родной, но используя js,ts,yaml начинаешь думать о некоторой универсализации всего кода которые используешь и тут ещё не ясно кто победит :)

автоформаттинг по шаблону перед коммитом делает все на раз , зачем заморачиваться с расстановкой скобочек вручную

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

Хочешь улучшить качество кода — плати больше денег, меньше работы давай, или обещай сделать гребца Head of development, если будет ударно трудиться.

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

Верно! Был у меня случай — платили неплохо, но по «политическим» мотивам заставляли кодить в VS 2010 express, хотя уже VS 2017 был на дворе. Производительность страдала, но по крайней мере к этому относились с пониманием.
А до этого еще круче было — опять-таки по политическим навязывали IDL — ну есть (был) такой язык, на котором астрОномы NASA работать любят (любили). Там уж я не выдержал, сказал шефу — мол, посадил меня за штурвал кукурузника — так не жди скорости МиГа.

Только не стоит забывать пример сервера приложений пентагона, который до поры до времени был одним из самых стабильных по uptime, написан на чем то вроде кобола и обслуживал все подрядческие заказы министерства обороны США. Поэтому не останавливайтесь в совершенствовании своих навыков даже за рулём кукурузника, эту задачу под силу выполнить только вам самостоятельно.

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

Каждый самолет — под свои задачи. И «кукурузник» По-2 очень неплохо проявил себя как ночной бомбер, но как-то никому не приходило в голову завоевывать на нем господство в воздухе. Хотя по простоте пилотирования и ремонтнопригодности ему равных не было, о чем даже песню написали www.sovmusic.ru/m/tripilot.mp3

остро стоят проблемы в области процессов разработки

Которые в простонародье называются «давайте срочно на вчера очень нужный заказчик бьет копытом сейлзы уже пообещали».

Сергей, я имел ввиду не про такой процесс :) (кстати в такой ситуации я, наверное к счастью, уже более чем за 8 лет работы в компании, не припомню что кто-то бы просил сделать быстро и плохо) В моей практике были примеры waterfall и agile разработки одним и тем же составом команды и результаты их работы как по скорости так и по качеству кода нельзя было поставить рядом, при этом подчеркну что был изменён только процесс разработки. Требования, заказчик, команда и все остальное остались без изменений.

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