Обновить
122.55

Качество кода *

Как Макконнелл завещал

Сначала показывать
Порог рейтинга

Баги на всех языках мира. Проверка LanguageTool

Всем привет! Hello, everyone! Hallo zusammen! Hola a tothom! مرحباً بالجميع!

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

В новой статье заглянем в её код и посмотрим на интересные вещи, которые нашёл в нём статический анализатор кода PVS-Studio: от утечек ресурсов и логических противоречий в условиях до дублирующихся ключей в хеш-таблицах, избыточных проверок и мёртвого кода.

Теги:
+4
Комментарии0

Слои валидации

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

Валидация на клиенте (если он есть)

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

Структурная валидация

Это валидация, которая, обычно, происходит на уровне самого фреймворка или в самом начале цикла обработки запроса. Для этого данные прогоняются через валидаторы json схемы, которая в идеале генерируется из openapi спеки. В самых деревянных случаях ручками (так делать не надо). Что важно понимать, это не доменная валидация (бизнес правила). Да тут можно проверить формат, наличие/отсутствие, но нельзя и не правильно пытаться проверять уникальность, выполнение каких-то условий, например количества денег на счету и тому подобное.

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

Доменная валидация

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

Доменные проверки, как и клиентские могут дублироваться, если завязаны на консистентность базы данных. Например во многих фреймворках (с orm) есть валидация на уникальность, которая делает sql-запрос, но в документации у этого валидатора всегда написано, что это не надежно (из-за конкурентности) и в таких ситуациях обязательно делать индексы в базе данных.

В случае провала такой валидации, в api принято возвращать код 422

Валидация на уровне базы данных

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

Проверка корректности данных

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

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

Больше про разработку в моем телеграм-канале Организованное программирование

Теги:
+3
Комментарии0

Участие в нескольких проектах снижает результаты работы — так ли это?

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

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

Почему спрашиваю?

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

Вопрос к сообществу:

Правда ли, что разработчик, участвующий в нескольких проектах part-time, будет менее эффективен, допустит больше багов и в целом ухудшит качество релизов? Или это миф, и всё зависит от процессов, коммуникации и личной организованности?

Теги:
+5
Комментарии17

Этот финт сэкономит вам время и нервы

Хочу написать о финте, который позволит вам сохранить нервы и сэкономить время. Правда некоторые (многие, почти все) впадают в ступор от него. Поэтому тут использована КДПВ с поста. Я наверно чувак слева.

А именно добавление первым условием if единицы:

if (1
    && $cond1
    && $cond2
    && $cond3
)

Использование финта дает нам возможность:
1. Быстро выключать фичу заменой 1 на 0:

if (0
    && $cond1
    && $cond2
    && $cond3
)

2. Быстро выключать любое условие в PhpStorm через горячие клавиши:

if (1
//    && $cond1
    && $cond2
    && $cond3
)

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

if (
    /*$cond1
    &&*/ $cond2
    && $cond3
)

Или такую:

if (
    $cond2
    && $cond3
)

3. Быстро добавлять новое первое условие:

if (1
    && $cond2
    && $cond3
)

легко превращается в:

if (1
    && $cond1 // в изменениях одна строка
    && $cond2
    && $cond3
)

4. Быстро дублировать любое условие.

5. Быстро менять порядок условий.

6. Также у нас будет чистый diff git-а при удалении/добавление первого условия.
Тут должен быть рисунок удаления с финтом и без, рисунок добавления с финтом и без.
Также при конфликте у нас будет более простое его решение, если нужно просто добавить оба условия.

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

Теги:
+10
Комментарии14

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

1. Давать осмысленные имена сразу же

Хорошие названия переменных, функций и классов экономят время всей команде: код проще читать, легче понимать и поддерживать. А еще чем меньше вопросов «что делает эта функция?» или «что содержит переменная?», тем лучше.

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

if внутри if или for внутри for путают: каждое разветвление создает еще одну ветку, которую приходится держать в голове. Лучше разбить логику на небольшие части — код становится прозрачнее и надежнее.

как не надо:

функция заказать_пиццу(адрес):
  если адрес_валиден(адрес):
    если у_ресторана_ингредиенты():
      если клиент_может_платить():
        печать "Пицца заказана!"
      иначе:
        печать "Недостаточно денег"
    иначе:
      печать "Нет ингредиентов"
  иначе:
    печать "Адрес некорректный"

как надо:

функция заказать_пиццу(адрес):
  если не адрес_валиден(адрес):
    печать "Адрес некорректный"
    вернуть
  
  если не у_ресторана_ингредиенты():
    печать "Нет ингредиентов"
    вернуть
  
  если не клиент_может_платить():
    печать "Недостаточно денег"
    вернуть
  
  печать "Пицца заказана!"

3. Регулярно делать рефакторинг

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

4. Настроить линтер и форматер

Линтер — статический анализатор кода, который следит за определенным стилем написания кода. Так как у каждого из нас свой подход, нам нужен «инструмент-судья», который беспристрастно оценит оформление кода. Форматер помогает автоматически исправить код и привести его к единому виду. 

5. Комментировать только неочевидную бизнес-логику

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

Теги:
+1
Комментарии3

Почему нужно использовать DTO

Data Transfer Object, термин, который для разработчиков на статических языках является чем-то самим разумеющимся, но вот остальные его могут не знать (даже если пользуются). Хотя в эпоху интеграций, фронтенд-бекенд, сервис-сервис, очереди, это крайне важная конструкция.

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

  • Модель => DTO => json/protobuf/sql...

  • json/protobuf/sql... => DTO => Модель

Нафига? Почему не сразу преобразовывать из, допустим, json в нашу модель или наоборот? Тем более во всех экосистемах есть механизмы, которые позволяют упаковывать любые объекты, задавая правила преобразования через метаданные, аннотации или еще как-то. Пример из Java:

@Entity
public class User {
    @Id
    private Long id;
    @JsonIgnore              // приходится скрывать
    private String passwordHash;
    @JsonProperty("created_at")
    private LocalDateTime createdAt;

    // getters/setters ...
}

var json = new ObjectMapper().writeValueAsString(dto);

Существует масса причин, почему это плохая идея. Для начала, это банальное нарушение MVC архитектуры. Модель начинает знать как о представлении, о том какие поля надо выдавать наружу, какие нет, как их переименовывать и так далее. Если это кажется натянутым, то вот вам реальные последствия.

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

DTO позволяют отделить представление от модели в коде, создавая по сути промежуточный слой. Имея его, вы можете независимо развивать свою модель и API для взаимодействия с ним. И да, это один из аспектов MVC, конкретно Model-View.

Готовые DTO гораздо легче чем модели конвертировать в типы на TS если у вас есть такая потребность. Например мы наши DTO (используем Alba), превращаем в типы TS с помощью готового инструмента (Typelizer). С моделями так легко не получится.

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

Но это только базовая история. Если мы еще подключаем инструменты генерации из sql (как в go) или openapi как везде, то те самые DTO создаются вообще автоматически на основе описаний.

INSERT INTO links (original_url, short_name)
VALUES (sqlc.arg(original_url), sqlc.arg(short_name))
RETURNING *;

DTO:

type CreateLinkParams struct {
	OriginalUrl string `json:"original_url"`
	ShortName   string `json:"short_name"`
}

Причем для update будет создана своя структура:

type UpdateLinkParams struct {
	OriginalUrl string `json:"original_url"`
	ShortName   string `json:"short_name"`
	ID          int64  `json:"id"`
}

Здесь отличается только id, но в реальных кейсах, отличий в создании или обновлении одной сущности обычно значительно больше, поэтому количество DTO тут становится еще больше.

DTO, кстати, должны быть имутабельны, иначе туда потечет логика

Больше про разработку в моем телеграм-канале Организованное программирование

Теги:
Всего голосов 9: ↑7 и ↓2+6
Комментарии1

Как анализировать C и C++ код без привязки к сборочной системе на Windows

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

Иногда бывает так, что появляется целый "зоопарк" самописных скриптов сборки, а его последний "смотритель" уволился ещё в прошлом году (играет Гражданская Оборона — "Зоопарк").

Хотелось бы всё равно как-то анализировать такой код без необходимости разбираться в хрупкой и непонятной системе сборки. Что же делать?

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

В новой статье посмотрим, как воспользоваться этим механизмом для ОС Windows в анализаторе PVS-Studio, и  как сделать его использование в процессе разработки удобным.

Теги:
Всего голосов 5: ↑4 и ↓1+4
Комментарии0

Статья "Код блокчейн-проектов Neo и NBitcoin VS анализатор кода. Кто-кого?"

PVS-Studio ворвался в мир блокчейн-разработки, и первыми "под удар" попали open source проекты на C# — Neo и NBitcoin!

В статье мы рассмотрели самые интересные ошибки: как явные, так и потенциальные, которые нашли в этом проекте. Если вам интересно, какие ошибки могут находить такие инструменты, как PVS-Studio, или вы желаете прокачать свой собственный "ментальный анализатор", приглашаю к прочтению :)

Теги:
Всего голосов 5: ↑5 и ↓0+6
Комментарии0

А всё таки, когда моки зло, а когда нет?

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

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

Последний случай, описывает процесс мокирования. То есть мок, это когда мы проверяем то, как код что-то делает, а не что он делает. Иногда говорят, что мы тестируем методом white-box, потому что мы знаем как конкретно написан тест и завязываемся на это, а не на результат работы этого кода, как в black-box тестировании.

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

Когда же моки все таки нужны? Допустим мы пишем систему с поддержкой хуков, например фреймворк для тестирования. В тестах такого фреймворка вполне допустимо проверить что хуки setup, teardown, beforeSetup, afterSetup и так далее, вызываются в нужном порядке и с нужными аргументами.

Общее правило здесь такое, если код можно тестировать методом black-box, то лучше так и делать. White-box это вынужденная необходимость, когда по другому ни как. Правда будьте осторожны, нередко программисты только думают, что по другому никак, потому что они не знают других подходов или по каким-то причинам решили, что другие подходы не подходят по идеологическим причинам.

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

Например:

  • База данных, которая хранит данные в памяти.

  • Фейковые сервисы какого-нибудь облака, например AWS

  • Поддельный HTTP клиент, который возвращает заранее заготовленные ответы.  

  • Заглушка почтового сервиса, которая записывает письма в список, а не отправляет их.

Все эти решения делают тесты быстрыми, предсказуемыми и независимыми от инфраструктуры, при этом вы все еще проверяете поведение системы снаружи, не нарушая принцип black-box.

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

Итого

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

Больше про разработку в моем телеграм-канале Организованное программирование

Теги:
Всего голосов 4: ↑2 и ↓20
Комментарии0

Модель искусственного интеллекта с открытым исходным кодом для оценки риска рака молочной железы

FRA-RIG-breast, экспериментально исследовательская модель, построенная на основе Фрактально Референциальной Архитектуры (FRA) — фреймворка, который интерпретирует данные с помощью моделей различий, а не изолированных признаков.

Модель делит входные параметры на три концептуальных блока:

R — особенности морфологической структуры и размера,

I — текстура, симметрия и фрактальные свойства тканей,

G — геометрическая компактность, кривизна и агрессивность.

Каждый блок генерирует свой собственный внутренний индекс (S_R, S_I, S_G), а конечная вероятность вычисляется с помощью логистической регрессии.

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

Ключевые результаты

Средние показатели перекрестной проверки:

Точность — 0,967

ROC-AUC — 0,989

PR-AUC — 0,990

F1-оценка — 0,973

Порог классификации (Youden) = 0,64

Модель сохраняет точность на 96-98% при сгибании и демонстрирует высокую стабильность между запусками.

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

FRA-RIG-breast может быть распространен на другие области, такие как исследования крови, легких или кожи, где понимание влияния факторов так же важно, как и само прогнозирование риска.

Zenodo: https://zenodo.org/records/17492410

GitHub: https://github.com/AdmailFRA/FRA-RIG-breast

Лицензия: MIT бесплатная для использования в научных исследованиях и образовательных целях.

❗️ Это экспериментальная модель, а не медицинский диагностический инструмент.

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

Буду рад обсудить, как можно было бы точно настроить параметры R, I и G для вашего исследовательского контекста. Безвозмездно.

Теги:
Всего голосов 2: ↑0 и ↓2-2
Комментарии1

Почему "давайте писать внимательнее" - плохое решение?

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

Инженерное решение должно быть проверяемым:

  • тест падает - гипотеза неверна;

  • алерт сработал - защита работает;

  • фича-флаг не дал багу уйти - система выдержала.

"Внимательность" не измеряется, не тестируется и не гарантируется. Это не решение, а успокоение.

Теги:
Всего голосов 3: ↑2 и ↓1+2
Комментарии6

Управление сложностью

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

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

Ниже 5 рекомендаций, по тому, как определить, что выстрелит, а что можно отложить на потом и не сильно париться с кодом.

Грамотное управление состоянием

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

Изолированная сложность

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

Приоритеты слоев

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

модели + структура базы => обработчики (контроллеры, сервисная история) => вывод (сюда же переводы и работа со строками)

Публичные контракты (API)

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

Отложенные решения

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

- Все, что можно поменять без боли - оставляем простым.- Все, что будет трудно поменять (API, модели, схемы БД, протоколы взаимодействия) - продумываем особенно тщательно.

Больше про разработку в моем телеграм-канале Организованное программирование

Теги:
Всего голосов 6: ↑4 и ↓2+2
Комментарии2

Какая должна быть длина у функций?

Щас скажу кое-что неочевидное. На эту проблему нельзя смотреть в статитке. Вот правильно 4 строки, 10, 100, поэтому разбиваем как-только доходим до предела. Я смотрю на это в динамике.

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

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

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

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

p.s. Смог тут загуглить исследование сотен миллионов строк на гитхабе: https://arxiv.org/pdf/1806.04556 (на скрине выдержка)

Больше про разработку в моем телеграм-канале Организованное программирование

Теги:
Всего голосов 5: ↑4 и ↓1+4
Комментарии3

Ближайшие события

🚀 Как я решаю сложные задачи

Для меня самое важное — полностью понять задачу ещё до того, как начать её выполнять.

Звучит банально, но под полным пониманием я имею в виду прям ПОЛНОЕ: не только суть, но и все технические детали, вплоть до того, какой код и где нужно написать.

📝 Часто я оставляю туду в коде и фиксирую шаги, которые нужно сделать. После этого перехожу к следующему этапу и разбираю его отдельно.

💡 Почему это работает:
1️⃣ Это помогает точнее оценить время выполнения.
2️⃣ Легче расставлять приоритеты. Если застрял на мелочи — видишь общую картину и не утонешь в деталях.
3️⃣ Быстрее формулируются вопросы. Особенно важно, когда коллеги в другой таймзоне и доступны не всегда. Чем чётче и быстрее задаёшь вопросы, тем быстрее получаешь ответы.

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

👨‍💻 Джуниор

Теги:
Всего голосов 6: ↑3 и ↓3+1
Комментарии3

Как научиться программировать лучше

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

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

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

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

И даже если вы со мной согласитесь, дальше начинается вакханалия. А что является базой, которую надо уметь и знать? Готов поспорить, что больше всего будут кричать про SOLID, чистый код и другое похожее мракобесие. Да, в любых шутках есть какие-то полезные мысли, но это все настолько скрыто за ширмой конкретных кейсов делай раз и делай два, что картинка теряется и все скатывается в срач, одна ответственность у функции или две.

Мой личный топ того, что учит писать грамотный код на высокоуровневых языках, где мы фокусируемся на создании правильных абстракций это SICP/HTDP + попрактиковаться в написании кода на одном из популярных функциональных языков.

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

И это не только мое наблюдение, почти все ребята с кем мы тогда активно тусили в разных комьюнити, пересекались на конфах и дружили, в целом отмечали как фп (в частности clojure, haskell, ocaml, erlang) значительно сдвигали понимание программирования.

Почему это так? А потому что в остатке мы упираемся в побочные эффекты, барьеры абстракции (тут сикп) и грамотное управление состоянием. Вот такие пироги

Больше про разработку в моем телеграм-канале Организованное программирование

Теги:
Всего голосов 10: ↑8 и ↓2+7
Комментарии2

Выводим Бугаенко на чистую воду разбирая ООП

Топ Перлов

  • Любой массив байт должен уметь работать с файлами, сетью и тд.

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

  • Вместо падения в моменте конструирования объекта, надо падать на другом конце программы при каждом его использовании.

  • Я придумал новый язык, и чтобы он не так сильно тормозил, надо встроить GC в CPU.

Упомянутые ссылки

Копилка благодарностей

Теги:
Всего голосов 13: ↑5 и ↓8-3
Комментарии2

Unit-тесты во фронтенде: развеиваем мифы

После статьи о навыках джуниоров многие не согласились с моей оценкой unit-тестов. Давайте посмотрим, где они действительно полезны, а где создают иллюзию ценности.

Если вы начинающий разработчик, вас наверняка убеждали:
«Без unit-тестов никуда! Всё должно быть покрыто тестами!»
Но так ли это на самом деле?

Где unit-тесты полезны:

  • Бизнес-логика и утилиты (форматирование данных, расчёты)

  • Кастомные хуки (управление состоянием, формы)

  • Критичные функции (редкий зверь во фронтенде)

Где они бесполезны (и даже вредны):

  • UI-компоненты (скриншотные тесты часто ломаются из-за изменений вёрстки)

  • API с моками (моки не показывают реальное поведение сервера)

  • Тестирование библиотек (проверяете чужой код)

Что использовать вместо?

  1. Интеграционные тесты — проверяют реальные сценарии

  2. Zod для валидации API — предотвращает ошибки из-за неожиданных данных

  3. Ручные проверки — быстрее и точнее, чем скриншотные тесты

Для джуниора unit-тесты — не приоритет. Важнее:

  • Глубокое изучение фреймворка

  • Умение работать с API

  • Навык чтения и отладки кода

Не стоит тратить время на «тесты ради тестов». Сосредоточьтесь на том, что действительно поможет в работе.

Теги:
Рейтинг0
Комментарии0

Красные флаги в код-ревью: перегибы, которых лучше избегать

  1. Фокус на мелочах. Если уделять много внимания опечаткам и код-стайлу, то времени уйдет много, а реальных результатов будет мало. Главное — это всё-таки архитектура, алгоритмы и производительность, а косметика только на втором плане. Зачем портить настроение себе и команде, если можно ничего никому не портить?

  2. Поверхностный анализ. Забивать на проверку кода — тоже плохая идея. И дело даже не в багах, их отловит тестировщик. Дело в безопасности всей системы. Если какой-нибудь хакер найдет уязвимость, которую QA не нашел, — жди беды. Ну и техдолг никто не отменял: если не делать сразу хорошо, однажды придется переделывать.

  3. Токсичность. Во время код-ревью лучше всё-таки искать потенциальные проблемы с кодом, а не учить коллег работать. То есть фокус внимания — не на поиске недостатков в чужой работе, а на самом коде. А личные предпочтения и вкусы относительно кода лучше обсуждать отдельно.

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

А каким должен быть хорошее код-ревью — в нашем блоге.

Теги:
Всего голосов 8: ↑4 и ↓40
Комментарии0

Мой код, мой кофе, мой хаос

Для ЛЛ: перечислены способы мотивации сотрудников, которые вам могут показаться банальными

Недавно на работе разгорелся жаркий спор. Двое наших разработчиков сцепились из-за выбора библиотеки для работы с датами в монорепе на js. Один был фанатом Luxon, утверждая, что она идеально подходит для сложных задач с датами и временем. Второй клялся, что Date-fns – в это лучший выбор, потому что она лёгкая, быстрая и позволяет использовать только нужные функции, не раздувая проект.

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

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

Разрешение конфликта

Чтобы выйти из тупика, я предложил компромисс: «Ребята, давайте так. Каждый из вас реализует свою часть проекта с использованием своей библиотеки. На проверку идей у вас 2 дня, потом сравним, что получилось». Они согласились, и весь накал спора тут же утих – оба погрузились в работу, стремясь доказать, что их выбор лучший.

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

В таких случаях я обычно:

  • Развожу спорщиков по разным проектам

  • Или принимаю сам решение какую технологию использовать далее

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

Мотивация-шмотивация

Несмотря на подзаголовок, я приведу реально применённые способы поднятия мотивации разработчиков:

  1. Деньги-деньги, решают многое. Сюда же незапланированные премии.

  2. Повышение должности сотрудника (иногда даже без повышения зарплаты, не везде корректно настроены грейды). Был «разработчик», стал «Ведущий разработчик», потом «Старший разработчик» и т.д.

  3. Обновляешь ноутбук работнику. Иногда для сотрудника это долгожданное обновление, и это очень повышает его мотивацию и лояльность к компании (ну или к тому, кто её выбил).

  4. Про лишние дни отдыха тоже понятно.

  5. Оплата билетов на конференции по IT-тематике (а они не всем по карману сейчас), покупка лицензий на удобный софт.

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

Этих пунктов может быть ещё очень много, везде индивидуально.

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

Если есть чем поделиться, как вас мотивировали - прошу в комментарии.

Теги:
Всего голосов 9: ↑4 и ↓5-1
Комментарии0

Gemini 2.5 Deep Think получила первую официальную золотую медаль IMO среди AI-систем

20 июля 2025 года Google DeepMind совершила прорыв: их модель Gemini 2.5 в режиме Deep Think стала первой AI-системой, официально получившей золотую медаль на Международной математической олимпиаде (IMO). Разбираемся, что это значит для развития искусственного интеллекта и когда технология станет доступна разработчикам.

Что произошло на IMO 2025?

Gemini 2.5 Deep Think набрала 35 из 42 возможных баллов, решив 5 из 6 олимпиадных задач за отведённые 4,5 часа. Главная особенность — все решения проходили на естественном языке без формальных переводов в системы вроде Lean или Coq.

Это кардинально отличается от предыдущих попыток. Например, AlphaGeometry от Google в 2024 году достигла только серебряного уровня в геометрических задачах, при этом тратила дни на решение одной задачи и требовала мощных вычислительных кластеров.

Важно: OpenAI заявляла о золотом уровне для своих моделей o1/o3, но официального признания от комитета IMO они не получали.

Архитектура Deep Think: мульти-агентное мышление

Технологический прорыв Deep Think заключается в нескольких ключевых инновациях:

1. Множественные потоки рассуждений

Модель запускает несколько параллельных "агентов", каждый из которых исследует свой путь решения. Затем результаты объединяются для финального анализа — подход, схожий с Grok 4 Heavy от xAI.

2. Увеличенное время на размышления

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

3. Специализированное обучение с подкреплением

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

Доступность и ценообразование

Здесь начинаются проблемы. Google выпустила две версии Deep Think:

  1. IMO Gold версия — доступна только избранным математикам и исследователям

  2. Bronze версия — публично доступна через подписку Google AI Ultra

Стоимость Bronze версии:

  • $124.99/мес первые 3 месяца

  • $249.99/мес в дальнейшем

  • Включает: Deep Think, Veo 3 (генерация видео), 30 ТБ хранилища

Ограничения Bronze версии:

  • Время ответа: 30-60 секунд на сложные запросы

  • Ограниченное количество запросов в день

  • Упрощённые возможности по сравнению с IMO-версией

Критический взгляд: стоит ли овчинка выделки?

Реакция комьюнити неоднозначная. Основные претензии:

  1. Неоправданно высокая цена: многие пользователи отмечают, что подписка Ultra даёт те же квоты API, что и бесплатный аккаунт

  2. Медленная работа: 30-60 секунд ожидания не подходят для продуктивной работы

  3. Неясные перспективы: Google не сообщает, когда IMO-версия станет доступна публично

Значение для индустрии

Успех Deep Think на IMO знаменует переход от "умных автодополнений" к системам, способным к настоящему рассуждению. Это открывает новые возможности:

  • Научные исследования: помощь в доказательстве теорем и решении сложных задач

  • Инженерия: анализ комплексных технических проблем

  • Образование: персонализированное обучение математике и логике

Что дальше?

Google обещает API-доступ к Deep Think "в ближайшие недели", но пока только для "доверенных партнёров". Полноценная IMO-версия может остаться исследовательским инструментом надолго.

Для разработчиков это означает ожидание: пока что Deep Think — это скорее демонстрация возможностей, чем готовый продукт для интеграции.

Выводы

Gemini 2.5 Deep Think действительно совершила исторический прорыв, став первой AI-системой с официальной золотой медалью IMO. Однако коммерческая реализация пока разочаровывает: высокие цены, ограниченный функционал и неясные перспективы развития.

Если вам нужна скорость и код — оставайтесь с GPT-4, Claude или o1. Если же готовы платить за глубокие рассуждения и не спешите — Deep Think может стать интересным инструментом.

Теги:
Всего голосов 1: ↑0 и ↓1-1
Комментарии1

Вклад авторов