• Flipper Zero — давайте пилить вместе. Приглашаем разработчиков
    +2
    Может я повторюсь или фигню скажу, но подскажите пожалуйста, а что с анонимайзингом самого флиппера (устройства)? Не знаю как правильно донести свою мысль, но можно будет как-то понять с какого именно устройства идет скажем подмена wi-fi пакетов, или при подключении к компьютеру для загрузки прошивки будет светиться id-устройства, уникальное в разрезе всех выпущенных флипперов? Или при общении 2 флипперов между собой. Не подумайте неправильно, но есть ли такой режим, полное обезличивание на всех возможных этапах идентификации устройства? Спасибо.
  • Контролируем и сохраняем сессии, используя Spring
    0
    Мне вот тоже интересно, а вообще нельзя удалить все неактивные сессии за 1 раз, при этом ничего не выбирая из БД? Что-то типа… principal_name = :userName AND session_id <> :currentSessionId
  • Контролируем и сохраняем сессии, используя Spring
    0
    не закрывать старую сессию и не открывать новую сессию

    Правильно ли я понимаю, что при таком выборе пользователя одна сессия шарится между 2мя устройствами? И если да, это условно означает, что 2 и более <разных> пользователя могут работать под одной учетной записью с одной общей сессией? Опять же, если да, то чем продиктована такая необходимость?
  • Практики хорошего code review, или что такое code review за 15 минут. Доклад Никиты Соболева на DUMP в Казани
    +1
    А давайте с другой стороны посмотрим на цели:

    многие люди контролируют выполнение какой-то задачи при помощи code review
    Захожу в патч (пулреквест), вижу описание задачи с номером на багтреке, перехожу в багтрек, вижу статус в багреке: Задача закрыта или Задача на обсуждении.
    Чем не контроль выполнения?

    контроль качества кода
    Из быстрого, что вспоминается:
    — SQL-выражения, некачественное отсеевается сразу.
    — Структура SQL-таблицы: на лицо качество или ее отсутствие, когда видишь ее описание.
    — JUnit тесты — задача конкретного метода тестом не покрыта.
    Чем не контроль качества кода?

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

    многие делают code review для архитектурного review
    Не встречался с таким, поэтому без комментариев

    многие через code review обучают людей.
    Не является целью, согласен, но как следствие — обучение через код ревью неизбежно. Будет происходить само по себе.
  • Как я закрыл трехлетний issue в TypeScript
    +1
    Что думаете по поводу условного workaround решения как подход к устранению таких базовых ограничений

    1. Создаем файл lib_extends.dom.d.ts
    /** Первый вариант */
    interface CustomMessageEvent<T = any> extends MessageEvent {
        data: T;
    }
    interface Worker {
        addEventListener<T>(message: string, handler: (message: CustomMessageEvent<T>) => any, options?: boolean | AddEventListenerOptions): any;
    }
    
    /** Второй вариант */
    interface Worker {
        addEventListener<T = any>(message: string, handler: (message: Omit<MessageEvent, "data"> & {data: T}) => any, options?: boolean | AddEventListenerOptions): any;
    }
    

    2. Добавляем в tsconfig.json в секцию include строку
        "include": [
            "./путо до lib_extends.dom.d.ts",
        ]
    

    3. И далее в коде проекта используем
    const worker = new Worker(...);
    
    worker.addEventListener<string>("message", (message => {
        message.data // (property) data: string
    }))
    
  • Заворачиваем в Promise модальное окно подтверждения действия
    +4
    В комментариях как всегда жду конструктивную и обоснованную критику.

    1) Почему не используете async, await? Ваш код будет гораздо проще.
    2) Из своего опыта скажу, что делать reject на отмену действия пользователя — не самый удачный вариант. Бывает так, что в коде идет последовательная цепочка действий, при которой, если произойдет ошибка необходимо режектить. И тогда может случиться каша из состояний — то ли отмена пользователя, то ли прикладная ошибка. Суть думаю уловили.

    Но идею с обобщением решения поддерживаю. Я использую чаще такую конструкцию, если переложить ее на Ваш пример
    async delete(data): Promise<void> {
        const userAnswer = await this.deleteModal.showAsync();
        if (userAnswer === UserAnswer.YES) {
           await this.deleteUserEndpoint.execute(data);
        }
     }
    


    Пример выше без обработок ошибок, так ак это другая история
  • Новые возможности TypeScript, повышающие удобство разработки
    +2
    1) Сухо, но лучшее что я видел и всем рекомендую про optional-chaining

    2) >> function foo(s: readonly string[])
    Будьте внимательны с readonly в конструкторах (для краткости объявил их в одном классе)
    // 3 конструктора: readonly делает совершенно разные вещи
    class TestReadonly {
        // неизменяемая публичная переменая s (можно менять содержимое)
        constructor (readonly s: string[]) {}
        // массив только на чтение
        constructor (s: readonly string[]) {}
        // неизменяемая публичная переменая s с типом массив только на чтение
        constructor (readonly s: readonly string[]) {}
    }
    
  • Могучие Typescript Декораторы — как работают, во что компилируются и для каких прикладных задач применимы
    +1
    Могу дополнить про декораторы свои наблюдения, для тех кто их пишет:
    1) Если декоратор допускает использование его без аргументов — не поленитесь написать реализацию, чтобы можно было писать и так @SomeDecorator и так @SomeDecorator()
    2) Будьте внимательны при реализации декораторов для методов, которые могут быть асинхронными — это особая магия.

    Привет декоратору LogTime
  • #ЯМыРабота. Решение, которое может оказаться правильным
    +5

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

  • Вывод типов в TypeScript с использованием конструкции as const и ключевого слова infer
    0
    Спасибо за альтернативу. Единственное что VS Code показывает IvanUser, но суть уловил
  • Вывод типов в TypeScript с использованием конструкции as const и ключевого слова infer
    0
    >> Вывод типов в дженериках
    Немного дополню. Иногда вывод типа нужно сделать для экземпляров некоторого класса, например:
    class User {
        constructor(readonly lastName: string, readonly firstName: string) {}
    }
    // Хочется, чтобы IVANOV имел строго то, что написано в конструкторе (lastName - "Иванов", firstName - "Иван")
    const IVANOV = new User("Иванов", "Иван");
    // Вывод типа >> const IVANOV: User
    // Не заработает const IVANOV = new User("Иванов" as const, "Иван" as const);
    

    На помощь приходит простое решение, но почему-то про него забывают
    // Тогда  конструкции нужно видоизменить. Декларация конечно монстр
    class User2<LN extends string, FN extends string> {
        constructor(readonly lastName: LN, readonly firstName: FN) {}
    }
    const IVANOV2 = new User2("Иванов", "Иван");
    // Вывод типа >> const IVANOV2: User2<"Иванов", "Иван"> 
    


    Если кто подскажет как сделать такое без дженериков буду признателен
  • Роскосмос опубликовал бортовой журнал Леонова о первом выходе в открытый космос и полетные документы корабля «Восход-2»
    +3
    Настолько затянуло чтиво по ссылкам, что совсем забыл про работу. Спасибо.
  • Декларативная фильтрация данных на фронте. JS/TS
    0
    По всей видимости я упускаю вашу мысль насчет сложных объектов, но разве это не решается таким образом:
    const attrsFilter = `$attributes.name == ${filter.attribute.name}`;
    
  • Декларативная фильтрация данных на фронте. JS/TS
    +1
    А что думаете по поводу шаблонных языков в качестве фильтров для поиска и решения Вашей проблемы? Для указанных в статье данных это могло бы выглядеть так:
    // Человеко читаемый фильтр по пользователям
    const usersFilter = `$age == 23 AND $name CONTAINS 'mary'`;
    const filteredUsers = yourLib.filter(users, usersFilter);
    
    // Человеко читаемый фильтр по группам
    const groupFilter = "$list.name CONTAINS 'Li' OR $groups.groups.list.name CONTAINS 'Li'";
    const filteredGroups = yourLib.filter(groups, groupFilter);
    
    // Можно заменить константы, например, через template строку
    const userFilters2 = `$age == ${filterValue.age} AND $name CONTAINS '${filterValue.searchText}'`;
    
  • 7 привычек, которые превратят любого интроверта в мастера коммуникации
    +1

    Мастером коммуникации на мой взгляд можно стать в 2 случаях:
    1) У Вас талант от природы к коммуникациям и вы его развиваете (явно не про интроверта)
    2) У Вас неотложные обстоятельства требующие быть мастером, например, должность президента при наличие внутренней мотивации к изменениям (интроверт? — мало вероятно)
    Все остальное — это подорожание и издевательство над собой: Вы ведь другой — тихая гавань снаружи и безграничная фантазия внутри)


    Очень странно, что пункт Узнавайте себя стоит на 6 месте, почему не на первом???

  • Как правильно делать код-ревью? Часть 2: навигация по ревью, скорость, комментарии, конфликты
    0
    Понять, нужен ли представленный функционал в принципе и есть ли у него хорошее описание

    Зачем вообще ставить задачу на функциональность, которая не нужна?

    Обратить внимание на самое важное в измененном коде и то, насколько хорошо решение спроектировано в целом

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

    Скорость проведения ревью: отвечайте быстро

    Мне кажется это самый важный пункт из статьи, если не в ущерб качеству. И чем быстрее будет получен ответ тем лучше.
  • 10 строк кода, которые уменьшат боль от вашего проекта на Vue
    +5

    Если честно, немного не понятно, зачем плодить модульные broadcast и сами $module, когда можно общаться через единую шину (в примере $rootBroadcast) с помощью сообщений, одним из обязательных параметров которого будет имя модуля. причем, если нет желание писать имя модуля в событии явно, его также можно задекларировать в прототипе вуя как $moduleName. Наличие класса типа ModuleEvent даст возможность понимать где какие события отсылаются/обрабатываются. Это может быть полезным при погружении и фикса багов.

  • Новый фронтенд Одноклассников: запуск React в Java. Часть II
    –2

    Вы бросили достойный вызов легаси. Могу пожелать терпения и удачи.


    В рамках эксперимента, нашей команде была поставлена обратная задача — запустить java(апплет) приложение в браузере (разумеется никак апплет, а как js приложение. В апплете более 5тыс классов, свой LookAndFeel, Swing и прочие вещи. В это трудно поверить, но с помощью CheerpJ и 2 напильников нам удалось за 2 дня достичь успеха в этом деле.


    По проделанной Вами работы, хочется понять в целом — это разумно js под граалем запускать?

  • Обзор 5 систем управления задачами для наведения полного порядка
    +1

    волшебная кнопка
    А можно узнать сколько стоит эта волшебная кнопка? Есть ли триал версия и остальную важную информацию о продукте?
    Например, решения оффлайн/облако(как сервис)

  • Чем меня разочаровал Typescript и стоит ли он того?
    +5
    Чем меня разочаровал Typescript и стоит ли он того?

    Отвечу за автора — да стоит и всем советую.
  • Чем меня разочаровал Typescript и стоит ли он того?
    +2
    Красивый ответ. Я бы добавил еще про номинативную типизацию как подход. Даже стать я на хабре есть
  • TypeScript. Мощь never
    0
    Да, а еще так :)
    validate(<OneField> badData)
    validate(badData as OneField)
    


    К сожалению, я не нашел способа запретить указание дженерика
  • TypeScript. Мощь never
    +1
    Спасибо, действительно хорошее дополнение для статьи. В продолжение — попробовал добавить тип, который допускает передачу только объектов того же типа.
    type OneField = {
        id: string;
    }
    type TwoField = {
        id: string;
        data?: string;
    }
    
    type DiffType<Free, Strong> = Omit<Free, keyof Strong>
    type Constraint<Free, Strong> = Record<keyof DiffType<Free, Strong>, never>
    type DirectType<Free, Strong> = Free & Constraint<Free, Strong>
    
    function validate<Free>(data: DirectType<Free, OneField>) {
        // do some work
    }
    
    const okData: OneField = null;
    const badData: TwoField = null;
    
    validate(okData);
    validate(badData); // Ошибка!!!
    
  • Максимальное количество значений в enum Часть I
    +2
    В 2017 году мне тоже был интересен этот вопрос, тогда я решил задачу в лоб с помощью кодогенерации и проверил эмпирически для java7. Статья на хабре здесь — ответ в секции Эксперимент. У меня получилось
    столько
    2746

    Убрал под спойлер из уважения к автору этой статьи, так как он обещает продолжение
  • История эволюции интерфейсов в Java
    +1
    В месте с дефолтными методами в интерфейсе появилась и очень интересная задача — как вызвать дефолтный метод у интерфейса через рефлексию? Ответ здесь
  • Тимлид — Таков путь
    +2
    В конце статьи не хватает эпичной фразы из упомянутого сериала: Я все сказал.
  • Исследуем записи в Java 14
    0
    Из интересного, на мой взгляд, можно отметить еще и шаблоны (дженерики)
    public class Records {
        public static void main(String[] args) {
            new Point<Integer>(1, 2).print();
            new Point<String>("11", 2).print();
        }
    
    }
    
    record Point<T>(T x, int y) {
        void print() {
            System.out.println("" + x + " - " + y);
        }
    }
    
  • Еще потасовать или хватит?
    –1

    Если кто не видел сюда про 52!

  • Опыт перевода Maven-проекта на Multi-Release Jar: уже можно, но ещё сложно
    0
    Как идея, что думаете над таким подходом взамен multi-release jar?
    package one.util.streamex;
    
    class VersionSpecificDetector {
    
        static VersionSpecific get() {
            boolean j9 = System.getProperty("java.version", "").compareTo("1.9") > 0;
            if (j9) {
                try {
                    Class<?> j9class = Class.forName("one.util.streamex.Java9Specific");
                    return (VersionSpecific) j9class.newInstance();
                } catch(ClassNotFoundException | InstantiationException | IllegalAccessException mixe) {
                    // Обработка ошибки должным образом
                    // use j8 impl
                }
            }
            // j8
            return new Java8Specific();
        }
    }
    
    interface VerSpec {
        VersionSpecific VER_SPEC = VersionSpecificDetector.get();
    }
    


    Где VersionSpecific — это интерфейс
  • Обработка ошибок в Kotlin/Java: как правильно это делать?
    +1
    Ваша правда. С нашей стороны, более жизненный кейс — когда заказчик присылает скриншот от клиента, Внутренняя ошибка сервера и все. Требуется разобраться срочно, а логов нет, или не дают или присылают через 3 дня. Тогда, наличие дополнительного кода — это просто подарок.
    С другой стороны, тот же заказчик выставляет определнные требования к ошибкам, отдел безопасности выставляет требования к сокрытию данных, да и самих клиентов порой выбешивает — Внутренняя ошибка сервера. EA125. Вот и получается, что не все так однозначно… :)
  • Обработка ошибок в Kotlin/Java: как правильно это делать?
    +2
    Если проект ориентирован на GUI, то ошибки подразделяются в прикладном смысле еще на 2 вида: Пользовательские и Системные.
    Пользовательские — те, которые должны отображаться клиенту с нормальным текстом.
    Все системные ошибки пользователь видит всегда как одну, например, Внутренняя ошибка сервера.
    У большинства разработчиков, начинаются трудности в понимании, какую ошибку нужно выбрасывать в том или ином случае.

    Вот здесь бы пару рецептов и лучших практик услышать…
  • TypeScript. Мощь never
    0
    Всегда пожалуйста :)

    Какой прием, если не секрет?
  • Ещё раз об ImmutableList в Java
    0
    Я думаю, самое время послушать Вас: Как Вы оцениваете предложенную реализацию в данном посте? Плюсы, минусы разумеется…
  • Ещё раз об ImmutableList в Java
    0
    Добро пожаловать в наш клуб.
    1) В java SDK нет контракта на неизменяемую (немодифицируемую) коллекцию, пожалуй основная проблема.
    2) Если такой контракт добавлять, то неизбежно придется ответить на вопросы:
    2.1) Какой интерфейс должен быть у неизменяемой коллекции?
    2.2) Должен ли этот интерфейс/контракт наследоваться от Collection/List?
    2.3) Должен ли Collection/List наследоваться от неизменяемой коллекции?
    2.4) Можно ли ввести понятие неизменяемой коллекции, не сломав обратную совместимость с ранними версиями?
    2.5) Должна ли неизменяемая коллекция порождать новую в методах add/remove и т.д. или бросать исключение?
    Я осветил ключевые вопросы и проблемы. У каждого ответа есть свои последствия, которые могут влиять на всю эко систему SDK.
  • Ещё раз об ImmutableList в Java
    0
    Вы чертовски проницательны: Если кому-то нужны гарантии — пусть явно попросит неизменяемый вариант коллекции.

    Так эта одна из ключевых проблем, в которую упирается автор первоначальной статьи, автор этой и я с Вами. И за кажущейся простотой, скрывается далеко непростая задача.
  • Ещё раз об ImmutableList в Java
    0
    Во-первых, с методом я не спорю (только с людьми)

    А во-вторых:
    >> 3) В любой части программы, работая с абстракцией (CharSequence), мы не можем сказать, какими свойствами данное представление обладает и какие гарантии может обеспечить (в общем случае)

    Метод isImmutable — это следствие моих рассуждений по части пункта 3 и в контексте статьи, которую в качестве исходного материала я указал в начале.
  • Ещё раз об ImmutableList в Java
    0
    Меня восхищает Ваша напористость и желание сделать SDK лучше.
    Сразу скажу, что я согласен с автором поста Неизменяемых коллекций в Java не будет – ни сейчас, ни когда-либо
    И это согласие есть результат статьи, которую я практически написал, но в последний момент отказался публиковать — так как изменил свое мнение на мнение автора :)
    Вот совсем кратко мои рассуждения на тему списков:

    Чтобы ответить на этот вопрос, сначала нужно поискать уже существующие решения в самом SDK, а во-вторых, посмотреть на потенциальное решение с практической точки зрения. Начнем с поиска.
    Классическим представителем неизменяемых объектов в SDK являются экземпляры класса java.lang.String. Строки спроектированы таким образом, что поменять их через публичное API — невозможно. Строки имеют отношение к поиску истины и потому, что их можно рассматривать через призму коллекций. Фактически, строка — это набор символов. Но сейчас вернемся к самому типу String. Важно понять, что в SDK нет MutableString. Или перефразировав, прийти к тому, что нет такой полной иерархии как ImmutableString, UnmodifiableString и MutableString. Плохо это или хорошо — каждый решает сам.
    Что касается иерархии, то я немного слукавил — иерархия есть, только не для типа String, как чего-то целого и завершенного, а для набора символов. Это всем известные StringBuilder и StringBuffer, которые как и String растут от CharSequence. Фактически, у нас есть 2 ветки: изменяемые и неизменяемые последовательности символов. Причем во главу угла поставлен контракт на чтение данных, так как CharSequence содержит только методы получения данных.
    После ознакомления с готовым решением по строкам в SDK можно сделать несколько важных выводов про mutable и immutable:

    1) Каждая реализация сохраняет свое свойство навсегда — нет перехода от immutable к mutable или обратно внутри одной реализации.
    2) В любой части программы, работая с реализацией, мы можем точно сказать о ее свойствах — изменяемая (StringBuilder/StringBuffer) или неизменяемая (String).
    3) В любой части программы, работая с абстракцией (CharSequence), мы не можем сказать, какими свойствами данное представление обладает и какие гарантии может обеспечить (в общем случае).
    4) Логичным и подтвержденным реализацией подходом является переход от mutable к immutable, т.е. изменяемый набор порождает неизменяемый, но не наоборот.

    Выводы как постулаты мы будем использовать для реализации неизменяемых списков. Но сначала, я хотел бы проанализировать сами выводы и понять их сильные и слабые стороны. Мой любимый — это пункт 3. На мой взгляд, для проектирования безопасного api — это огромный недостаток. Когда мы спускаем в engine некоторую абстракцию, вполне логичным, для меня, является то, что этот engine имеет право потребовать определенные гарантии надежности от источника, взамен, обещает сделать свою работу должным образом. Такие отношения можно формализовать с помощью простого метода, спросив с помощью него, какие гарантии несет реализация. В плоскости рассматриваемой проблемы им может стать контрактный метод isImmutable;
        boolean isImmutable();
    

    Если мы используем фундаментальные принципы проектирования, то делать такой метод — неправильно. Но если мы ищем больше практичное решение, нежели фундаментальное — то допустимо.
    Так как пункт 1 гласит, что свойство immutable/mutable сохраняется навсегда, то вмести с ним сохраняется и гарантия неизменяемости/изменяемости тоже — навсегда.
    Рассматривая пункт 3, мы столкнулись с первой дилеммой — фундаментальность или практичность?
    Пункт 2, можно интерпретировать и по-другому, что не должна одна реализация рости от второй. Т.е. ссылочное присвоение в обе стороны запрещены (ошибка компиляции).
    Пункт 4, опять таки заставляет нас разобраться с дилеммой: фундаментальность или практичность? Потому что требует, наличие метода toImmutable в общем контракте. Можно читать toImmutable здесь как метод toString в классе CharSequence, с одной оговоркой.
        List<T> toImmutable();
    

    Я утверждаю, что пункт 4 больше рожден из практической плоскости, нежели фундаментальной. И это важно. В противном случае, неизменяемая реализация должна порождать изменяемую, но на примере String, мы видим, что такого нет.
    Есть еще одна особенность в типах String, StringBuilder и StringBuffer, если рассматривать их как набор символов, про которую я нарочно умолчал. Мы всегда работаем с реализацией, что сильно упрощает контекст восприятия.
    Это недопустимо для списков в общем случае.
    Если подытожить выше изложенную философию мысли, для решения проблемы с неизменяемыми коллекциями нам требуются в арсенале 2 метода isImmutable и toImmutable. Разумеется, исходим из того, что по факту сейчас есть в SDK.
    interface Collection<E> extends Iterable<E> {
        // ...
        boolean isImmutable();
        Collection<E> toImmutable();
        // ...
    }
    

    Правильно? Не совсем. Потому что toImmutable возвращает контракт совместимый по апи с коллекциями в оба направления, что делает не возможным ограничение по типу.

    И так далее, пока я не пришел к выводу, что новых коллекций не появится.

    Если попытаться выдать желаемое за действительное — то в SDK все же неизменяемые коллекции могут быть и мне точно известно время — когда в java появится система типов, подобная TypeScript. Тогда различия между 2мя коллекциями будет в наличие значение у поля mutable: или true или false;
    Но это совсем другая история, не находите?

  • Диалоговые окна на Promise
    0
    Может я избалован vue, но мне приведенные примеры кажутся непосильно сложными, возможно из-за субъективного восприятия react. Приведу пример, как мы работает с модальными диалогами в vue и ts:
    // Класс, отвечающий за логику сохранения документа
    class SaveDocumentEngine {
    
        async saveDocument(doc: Document): Promise<void> {
            const docCount = 1; // константа введена для наглядности
            const userAnswer = await new SaveDocsConfirmDialog().show(docCount);
            // Если пользователь передумал
            if (userAnswer !== UserChoice.SAVE) {
                return;
            }
            // логика сохранения и проверки документа
        }
    }
    

    Явное создание диалога, вызов с параметрами и обработка результата — ничего лишнего. А вся специфика спрятана в самом диалоге.
    /** Диалог подтверждения сохранения документа/документов */
    @Component({
        // language=Vue
        template: `
    <dialog-form title="Предупреждение" :width="500">
        <template slot="content">
            Вы действительно хотите сохранить {{data > 1 ? "документы" : "документ"}}?
        </template>
        <template slot="footer">
            <button class="btn btn-primary" @click="onSave">Сохранить</button>
            <button class="btn" @click="onCancel">Отмена</button>
        </template>
    </dialog-form>
    `
    })
    export class SaveDocsConfirmDialog extends CustomDialog<DocCount, UserChoice> {
        /** Желание сохранить */
        private onSave() {
            this.close(UserChoice.SAVE);
        }
        /** Желание отменить */
        private onCancel() {
            this.close(UserChoice.CANCEL);
        }
    }
    
    // Тип - Количество документов
    type DocCount = number;
    
    // Тип - Выбор пользователя
    export enum UserChoice {
        SAVE, CANCEL
    }
    
  • Используем статические ссылки на свойства объектов при помощи лямбд
    0
    Хотелось бы увидеть реальные прикладные задачи, где нужен такой подход. И как в конечном счете это помогает/ухудшает код.
  • Рефакторим параллельно с разработкой: наш опыт и два чек-листа
    0
    >> А у себя как решаете, нашли такого человека?

    У нас стратегически другой подход: была сделана ставка на жесткий код-ревью. Это не значит 'взамен' рефакторингу. Но время на такой код-ревью существенно сокращает свободное.