• Вероятно, хватит рекомендовать «Чистый код»
    0

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

  • Вероятно, хватит рекомендовать «Чистый код»
    0
    Оптимизировать просто нечего, так как всё уже предельно просто.

    Оптимизация, это не всегда упрощение (кеш, предсказание переходов, JIT это усложенение, а не упрощение)


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

    Мне ваш анализ ситуации непонятен. Некешированный доступ к бд — источник тормозов, но, в то же время кеш ничего бы не исправил.


    Я правильно понимаю, что исследование произваодительности показало, что узкое место — доступ к БД (т.е. задача IO/Network bound)?


    А что именно в этом доступе к БД тормозило? Генерация запросов, latency в сети, составление планов? Исполнение запросов?

  • Вероятно, хватит рекомендовать «Чистый код»
    +1

    https://martinfowler.com/bliki/FunctionLength.html


    Smalltalk's graphics class had a method for this called 'highlight', whose implementation was just a call to the method 'reverse' [4]. The name of the method was longer than its implementation — but that didn't matter because there was a big distance between the intention of the code and its implementation.
  • Вероятно, хватит рекомендовать «Чистый код»
    0

    А как это связано с разбиением на функции?

  • Представляем .NET 5.0 Preview 6
    0

    Есть еще проект MAUI планируется на .NET 6, судя по странице, как-то Linux может поддерживаться (там написано community, как у Xamarin Forms, вероятно, это будет делать не MS, а классический opensource)

  • Вероятно, хватит рекомендовать «Чистый код»
    0

    undel.


    но, к слову, почему-то заметно тормозит в некоторых случаях

    Может зависеть от платформы, напримерп, поддерживает ли компилятор инлайнинг. А может было что-то еще. Надо профилировать.

  • Анатомия юнит тестирования
    0

    Тут вопрос, что вы называете моками и что юнит тестами.


    Вот терминология у Фаулера моки


    Моки
    • Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
    • Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
    • Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test.
    • Spies are stubs that also record some information based on how they were called. One form of this might be an email service that records how many messages it was sent.
    • Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

    Юнит тесты


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


    Так же см разные паттерны у Шора. Например, использование signature shielding.


    Еще можно сохранить совместимость с boolean либо просто добавив новый метод вместо переделки существующего, либо сделав imlicit cast к булеан. Последним, правда, я не пользовался, если у кого-то есть какой-то опыт, было бы интересно узнать.

  • Что я узнал после более чем 1000 code review
    0
    Вы пытаетесь использовать ветки для документации истории изменений. Но они для этого не предназначены. Они нужны для изоляции кода.

    Как раз для изоляции — фич друг от друга.


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

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


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


    Мердж коммит находится «вдалеке» от основного коммита и надо искать где находится тот, про который написано в мердже.

    Делается squash merge и я вижу только один коммит. Если не хочется сквешить, то можно проребейзить перед мерджем и они будут рядом.


    А в мастер не обязательно мержить, когда вся фича готова. Можно замерджить и 10 фич и полфичи.

    Чем больше объем мерджа тем больше разбираться что сломало CI, меньше гранулярность при черрипике, если надо будет, больше объем ревью и так далее.


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


    Необязательно: она может быть сделана, но непроревьювена.

    Зачем ее тогда брать, после ревью может быть сильно изменена?


    Я бы сказал, что это нетипичный случай.

  • Что я узнал после более чем 1000 code review
    0
    Почему нельзя взглянуть сразу в коммит сообщения, где так же будет ссылка на таску в джире (если коммит связан с таской). Зачем мне идти в мердж коммит, который фиг знает где, открывать пул реквест и только там смотреть конкретные таски?

    Что значит фиг знает где? Он составляет историю мастера.


    Я совершенно не против, чтобы там были и идентификаторы фич. Просто если их много удобнее видеть ссылку PR в целом и текстовый осмысленный коммент, если нужны детали можно открыть PR и ходить по ссылкам на фичи если их несколько.


    Если она одна, наверное, иметь ссылку на PR чуть менее удобно, чем на фичу в джире на один дополнительный клик. Зато имея ссылку на PR можно посмотреть и дополнительные вещи (типа кто ревьюил и какие были замечания.)


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


    Зачем что-то мержить в мастер пофично?

    Потому, что вы можете работать, как вы сами говорили, над несколькими фичами, одна может быть готова отправке в мастер, другая не готова — тесты не дописаны, не компилируется, нет документации или какие там у вас характеристики проверяет билд еще.


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

    Если она не вмерджена в мастер, значит не готова. Берите всегда из мастера. (Кроме того случая, когда вы работаете над долгоиграющей фичей — тогда берите из фичи, над которой работаете)

  • Что я узнал после более чем 1000 code review
    0
    Совершенно верно. Собственно так это и задумывалось

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


    Merge commit будет содержать название ветки, но что мне это даст?

    Обычно он содержит ссылку на PR которую можно открыть и посмотреть все детали


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

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


    Но зачем засорять гит тысячами мелких бренчей мне непонятно.

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

  • Что я узнал после более чем 1000 code review
    0
    Что значит зачем? Программирование — это творческий процесс. Разработчики работают, как им удобнее. Если у меня есть 2 задачи по фронту и бакенду для фичи A и фронт+бакэнд для фичи B.
    То мне может показаться удобнее написать сначала бакэнд для обеих фич а затем фронт для обеиз фич.

    Ок тут согласен — вполне допустимо в каких-то случаях создавать ветку на несколько связанных задач, если их удобнее сделать как одну.


    Но вы-то предлагает ветку на разработчика — т.е. там должны быть вообще все зачачи разработчика даже логически не связанные или как?


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

    Наверное тут какое-то недопонимание. Я подразумеваю, что ветки сливаются в какой-то момент в основную. Соответсвтенно, merge commit будет содержать описание и ссылку на задачу и можно будет посмотреть в истории по master.


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


    Я например постоянно переписываю документацию. И что мне для каждой опечатки таску и отдельную ветку создавать?

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

  • Что я узнал после более чем 1000 code review
    0
    Во первых возникает туева хуча веток. Часто работу нельзя правильно разбить по этим веткам, да и не нужно.

    Что такое "правильно разбивать" и почему их невозможно разбить?


    Кроме того разработчики часто работают над несколькими задачами одновременно. Надо постоянно переключаться между ветками.

    Что их заставляет так делать? Как они поступают когда одна задача готова, а другая — еще нет? Как потом в истории разобраться зачем именно было сделано конкретное изменение?


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

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


    С моей точки зрения, все коммиты связаны с задачами, если у вас нет никакой задачи не создавайте коммит. Если у вас есть задача, оформите это в багтрекере. Если у вас коммит связан с закрытой задачей, значит в багтрекере вранье — либо задача не закрыта, либо это новая задача, связанная с данной.

  • Что я узнал после более чем 1000 code review
    0

    Вы имеете ввиду что на одного разработчика ровно одна ветка? Или что ветка на фичу И разработчика?


    Ссылка на forking workflow она про создание форков репы а не про ветки.


    Если разработчик заводит ветку на инкремент (багу или новую фичу) то все плюсы, которые у вас упомянуты уже соблюдаются.


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

  • Анатомия юнит тестирования
    0

    Возможно, вам помогут идеи Джеймса Шора

  • Что я узнал после более чем 1000 code review
    0

    Какое у вас тестовое покрытие? Как оно измерено?

  • Что я узнал после более чем 1000 code review
    +1

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


    Наверное здесь "локально" означает "в тестовой среде" она может быть нелокально, а в облаке, просто код в тестовом инстансе развернут из данного конкретного бранча. Судя по тексту, автор имел ввиду "я провел ручное End-To-End тестирование этого кода"

  • Что я узнал после более чем 1000 code review
    +1

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


    Просто у нас это настолько повсеместно, что считается нормальным.

  • История архитектуры Dodo IS: путь бэкофиса
    +1
    Это места стыковки с остальной системой. Само по себе взаимодействие клиента с сервером не изменилось.

    То есть при выделении сервиса никаких новых сетевых взаимодействий не возникло?


    Чтобы выделить сервис, вовсе не обязательно выковыривать код его бизнес-логики из старой системы.

    Попробуйте заменить в этих рассуждениях "сервис" на "модуль" или "сборку" — получится то же самое, нет?


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


    Но логически можно выделить отедльный модуль и без выделения в сервис. Кроме, того, что сетевое взаимодействие накладывает дополнительные ограничения на связанность (например, в DDD есть правило, что нельзя делать ссылки внутрь агрегатов, но, насколько я знаю, нет способа проверять это правило. В случае сервисов не получится его не соблюдать так как нельзя делать ссылок внутрь сервиса)


    Я пытаюсь понять, что для вас было главным — технические проблемы или логические.


    Где-то у Фаулера я видел рекомендации сначала, выделять отдельные модули, потом, отделять хранилища (условно, чтобы модули взаимодействовали внутри с ограничениями характерными для микросервисов, но in-process), потом, выделять микросервисы.

  • История архитектуры Dodo IS: путь бэкофиса
    +1

    А где тут "сетевое взаимодействие"? Этот отдельный домен может быть модулем, а не сервисом. Если никто не знает всех нюансов, то как они потом переключат использование на сервис — там будут абсолютно те же самые проблемы что и в случае использование отдельного модуля + дополнительные проблемы связанные с сетевым взаимодействием.


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


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


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

  • История архитектуры Dodo IS: путь бэкофиса
    0
    Оценка выделения сервиса из монолита более предсказуема и надежна, чем оценка рефакторинга того же монолита, поэтому сделали, что успели.

    Почему? Разве это не то же самое + накладные расходы на то, что с сервисом надо учитывать все особенности сетевого взаимодействия?

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0
    С чего вы решили, что из приведенной цитаты этого не следует?

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

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    +1
    В его случае принцип LSP будет соблюдён, так как в обоих случаях Close() описывает финализирующюю операцию

    В данном случае это значит, что среди двух методов можно найти что-то общее, а не то, что они тождественны. Так же можно сказать, что они оба методы.


    метод sub(x, y) будет возвращать сумму при аргументах sub(-2, -2).

    Да он будет возвращать число равно сумме, но других чисел: -2 и 2. Оно так же будет равняться произведению 1 и 0

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    +2
    Нет, это не правда. Проблема вашего непонимания в том, что вы говорите о Классах и Типах как об одном и том же.

    С чего вы решили, что автор считает что это одно и то же. Из приведенной цитаты этого не следует.


    Если множество запросов совпадает — значит у объектов Тип будет общим, независимо от того к какому Классу эти объекты принадлежат.

    Метод void Close() и метод void Close() это один и тот же запрос?


    А вот так:


    /*  Закрывает окно, потом его можно переоткрыть при помощи Open()
    */
    void Close()

    /*  Закрывает поток, поток нельзя больше использовать. Изменения сбрасываются в файл на диске.
    */
    void Close()

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


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


    Нет таких понятий.

    https://en.wikipedia.org/wiki/Structural_type_system


    Любой ЯП это просто текст в файлике, который так или иначе в итоге станет машинным кодом.

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


    Нет «серьёзных» и «несерьёзных» языков программирования,

    Есть несерьезные языки программирования, например шуточные


    За 7 лет рабочего опыта пора уже отучится от таких детских взглядов на программирование и код.

    Вы очень категоричны и неуважительны.

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0

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


    Можно скомпилировать DLL из исходного текста и подгрузить в процесс.


    В стандартной библиотеке регекспы компилятся.

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0
    берём юнит, который содержит код, ходящий в http или в Database.
    его тест — юниттест или не юниттест?

    Юнит тест это размытое понятие. Что конкретно имел ввиду 0xd34df00d под ним — надо спросить у него.


    "многие не любят" — это что-то странное.

    Почему. Многие не любят острую пищу. Чем это странное понятие? В реальности такое считается.


    Напоминаю, мы не обсуждаем нужны ли юнит тесты, мы обсуждаем считает ли 0xd34df00d что никаие автоматические тесты не нужны. По его посту очевидно, что он считает что какую-то часть тестов он считает избыточной при статической типизации а не то, что никакие тесты не нужны.

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    +2

    Он написал о ненужности юнит тестов, а не тестов вообще. Юнит тесты многие не любят

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    +2

    Что такое "вполне типизированный"? Как F# в котором есть поддержка единиц измерения? Или как C?

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    +1

    Можно убрать return и фигурные скобочки


    static string Display(object o) =>
        o switch
        {
            Point p when p.X == 0 && p.Y == 0 => "origin",
            Point p                           => $"({p.X}, {p.Y})",
            _                                 => "unknown"
        };
  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0
    А в каком языке (кроме Idris 2) вы это можете делать?

    C#

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0

    Насколько я понимаю, хаскеллевские алгебраические типы компилируются во что-то подобное. 0xd34df00d, вероятно, не считает kind информацией о типе

  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0

    https://en.wikipedia.org/wiki/Tagged_union#1970s_&_1980s


    enum ShapeKind { Square, Rectangle, Circle };
    
    struct Shape {
        int centerx;
        int centery;
        enum ShapeKind kind;
        union {
            struct { int side; };           /* Square */
            struct { int length, height; }; /* Rectangle */
            struct { int radius; };         /* Circle */
        };
    };
  • Объясните мне, как вы для себя разобрались в моделях типизаций — они же все размыты
    0

    А этот инт логически не будет информацией о типе?

  • Программист не должен решать задачи бизнеса
    +1

    Программист вообще ничем заниматься не обязан кроме программирования. По определению слова "программист".


    Но, у работодателя есть свобода договориться с программистом на что-то еще и предпочесть такого программиста, который что-то еще делает. И тогда конкретный программист становится обязан.

  • Программист не должен решать задачи бизнеса
    +1

    Т.е.


    • Вам это нравится
    • Для вас это необременительно
    • В качестве постоянного занятия это было бы много.

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

  • Программист не должен решать задачи бизнеса
    0

    Почему вы пишете на форум сами а не наняли специального флеймера?

  • Хватит натягивать сову на глобус
    +1
    Какую проблему в этом процессе может решить канбан?

    Доска отвечает на вопрос чем именно занимается команда и "есть ли что потестить"


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

  • Хватит натягивать сову на глобус
    0

    Почему?

  • Хватит натягивать сову на глобус
    +1
    вы будете держать на доске все когда-либо выполненные задачи на случай вдруг потребуется, что-то посмотреть?

    Доска электронная она сама держит n последних задач. Если мне не хочется видеть, я эту колонку сворачиваю


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

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

  • Хватит натягивать сову на глобус
    0

    Источник вы не сообщили.


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

    Оно готово, но, например надо посмотреть какие-то детали для выполнения следующей задачи.


    В контексте данного топика, отдел — это группа работников, решающая одного рода задачи.

    Если один человек занимается разными колонками в канбане он меняет отделы в зависимости от текущей колонки?

  • Хватит натягивать сову на глобус
    +1

    Вы ранее, если я не путаю, писали что есть еще заявки от пользователей — или им занимается не ваш отдел?


    Например, может быть такое, что с инфраструктурой что-то не так, а алерт не прилетел? Или алерт прилетел, но надо посмотреть что происходит в системе и приходится узнавать зачем пользователь Х запустил Y можно ли его сейчас прервать для перезагрузки и так далее.