Организованное программирование | Кирилл Мокевнин
11K subscribers
60 photos
230 links
Как из джуниора дойти до мидла, а потом и до синьора
Ютуб https://youtube.com/@mokevnin
Связь для предложений: @kirillpublic
Download Telegram
План на ближайшие посты по шаблонам проектирования
Тема с шаблонами зашла, она как обычно вызывает разные чувства, но комментариев много и интерес есть. Я хочу сделать цикл прямо обучающих постов, в которых мы кое что разберем. Однако, сразу хочу обозначить. Это ни в коем случае не стандартное вот шаблон вот поехали. Мы попробуем разобраться со смысловой частью программирования, в которой появляются шаблоны с рассмотрением проблемы, альтернатив, плюсов минусов и так далее. И что важно, даже когда мы будем говорить про паттерны, мы не будем говорить про набор классов как это описано в большинстве мест, мы будем говорить про организацию кода, которая решает реальную проблему, не зависимо от того, на каком языке мы пишем. На выходе у вас должно появиться более четкое понимание проблем, которые вызывает сложный код и как это код можно упростить (или усложнить) разными решениями. Первый пост будет завтра, а тут немного комментариев на те комментарии, которые вы оставляли к посту:

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

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

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

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

> Интересно, кто-то на практике сталкивался с потребностью поменять базу во время жизни приложения?

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

> А в чем вообще разница между медиатором и адаптером?)

Поговорим) Однако тут надо идти от проблематики, в которых эти паттерны возникают.

p.s. Знаете ли вы что такое динамическая диспетчеризация и мультидиспетчеризация?
39🔥20👍7🤩2🤔1👌1🤓1
Шаблоны проектирования: Синглотон
Начнем с чего-то наиболее простого, но наиболее известного. Синглотон, это объект, который создается ровно в одном экземпляре и за этим не надо следить, он сам за этим следит за счет того как его реализуют.


public class Singleton {
// The volatile keyword ensures that multiple threads handle the uniqueInstance variable correctly when it is being initialized to the Singleton instance.
private static volatile Singleton uniqueInstance;

// private constructor so no one can instantiate the class from outside
private Singleton() {}

// Method to return an instance of the class
public static Singleton getInstance() {
// First check without locking to improve performance
if (uniqueInstance == null) {
// Locking the class object to only let one thread in to check and instantiate the singleton
synchronized (Singleton.class) {
// Double-check whether the instance is null or not to ensure that no two instances are created
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}

// other useful methods here
}


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

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

Но как это ни странно, все же есть разные экосистемы с разными порядками. Например эталонный пример где синглотоны никак не нужны и не используются почти никогда это spring (boot), так как там крутой контейнер зависимостей, который решает проблему доступа и управляет жизненным циклам объектов. В JavaScript, Python и Ruby подобные синглотоны встречаются, но в другой реализации. В JavaScript и Python иногда делают файлы, в которых формируются данные/объект, который может быть импортирован куда-то и этот объект инициализирован ровно один раз, так как сам файл интерпретируется только один раз. В Ruby такое принято и в самой Rails и в ее библиотеках, когда класс содержит статическое поле с объектом. Да это сильно упрощает написание кода (так как нет контейнера) и помогает новичкам, но иногда больно стреляет и если не следить за абстракциями, делает из кода кашу. Кстати поэтому в тестах на Ruby часто встречается такое когда синглотон меняют в начале теста и потом возвращают обратно в конце. Подобные хаки для синголотон встречаются и в других языках, я точно такое делал сам на php

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

Про альтернативу синголотоном можно прочитать тут: https://en.wikipedia.org/wiki/Dependency_injection

p.s. Вы сталкивались с проблемами в использовании синглотонов?
👍469🫡97
Шаблон проектирования: Команда

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

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

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

В случае Java это объект-команда.


var button = new Button();
// У команды есть один интерфейсный метод execute()
var command = new CopyCommand();
button.setCommand(copy);
// Кнопка добавляется в интерфейс


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


const button = document.getElementById('myButton');

// Adding a click event listener to the button
button.addEventListener('click',() => {
// Тут может быть напрямую зашитая логика
// Если логика повторяется, то она может быть вынесена куда-то,
// а здесь только вызов
});


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

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

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

p.s. Вам приходилось реализовывать команду в своей практике?
👍5366🫡2❤‍🔥1🔥1👌1
Шаблон проектирования: Стратегия

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

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


// ChatGPT
async function fetchUserData(userRole, userId = null) {
let queryOptions = {};

if (userRole === 'admin') {
// Admin gets access to all users
queryOptions = {};
} else if (userRole === 'user') {
// Regular user gets only their data
queryOptions = {
where: {
id: userId
}
};
}

try {
const users = await User.findAll(queryOptions);
console.log(users);
} catch (error) {
console.error('Error fetching user data:', error);
}
}

// Example usage
fetchUserData('admin'); // Fetches all users for admins
fetchUserData('user', 1); // Fetches data for user with id 1


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

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

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

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

p.s. Расскажите про свои ситуации, где стратегия помогала снизить сложность?
35👍203🔥2👨‍💻2🫡1
PHP работы пост: Ищу Laravel-разработчика с фронтенд опытом на проектную работу для нашего колледжа https://mokevnin.notion.site/a62fc9b140df44609ee2b365d70f4e90?v=ecb6fa57cfe84022add265b6b574c2d1&p=a0195e34c32c4c6fb622662cdfe4b83a&pm=c стоимость проекта будет считаться исходя из 2000 руб/час, ориентировочно месяц на разработку, дедлайн 15 мая. Я соучаствую, помогаю с архитектурой, инфрой и ревью
🤔1
Редактор Хекслета: JS => TS

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

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

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

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

p.s. Все нужные фиксы мы внесли в течении дня, щас редактор уже лучше чем был и готов к расширению без боли
🔥63👍1711😁3👀2
Что такое полимофризм?

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

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

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

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

Допустим мы работаем с беком по апи и для этого используется спец либа, а не просто fetch запросы. У гитхаба есть подобная либа: https://github.com/octokit/rest.js Дальше вы решили написать тесты к своему коду и столкнулись с проблемой, что в тестах улетают запросы на реальный github, что не правильно. В тестах во внешние системы не ходят (кстати вы знаете почему?). Как выйти из этой ситуации?

• Либа может сама содержать такую функциональность. Ставится какой-нибудь флаг и она не шлет запросы
• Подход, который довольно популярен в JavaScript (и Ruby) это манки патчинг. С помощью либы https://github.com/nock/nock которая патчит низкоуровневый код и подменяет его фейком, который не делает никаких запросов.
• С помощью ифов
• Как развитие предыдущего пункта, с помощью полиморфизма

Поговорим о последних двух. Мы легко могли бы расставить по коду проверки на окружение:


if (process.env.NODE_ENV === ‘testing’) {
// ничего не делаем
} else {
// реальный запрос
}


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

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


let octokit;
if (process.env.NODE_ENV === ‘testing’) {
octokit = new OctokitFake();
} else {
octokit = new Octokit();
}

export octokit;


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

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

p.s. Мастхев для чтения: https://guides.hexlet.io/ru/usefull-twitter-threads/#мифы-вокруг-ооп

p.s.s. Требуется ли для полиморфизма подтипов наличие ооп?)
👍3295🔥5👎2👏2👌1
Решил попробовать добавлять в вакансию вот такой блок, чтобы кандидаты могли оценить сами себя и понять стоит ли приходить или нет. Как думаете, поможет улучшить воронку?
💩63👏29🔥12👍9🤔7🥴4
В этом году Хекслет стал партнером конференции TechTrain 2024 Spring, которая пройдет 6 апреля онлайн (бесплатно, без смс). Я выступлю спикером с темой использования конечных автоматов в прикладном коде на бизнес задачах. После этого доклада ваша жизнь не будет прежней. Не пропустите https://techtrain.ru/?utm_source=partner&utm_medium=hexlet&utm_campaign=announce
🔥56👍6🤔1
Организованное программирование | Кирилл Мокевнин pinned «В этом году Хекслет стал партнером конференции TechTrain 2024 Spring, которая пройдет 6 апреля онлайн (бесплатно, без смс). Я выступлю спикером с темой использования конечных автоматов в прикладном коде на бизнес задачах. После этого доклада ваша жизнь не…»
Часто встречаюсь со мнением, что раз у нас есть гит, то старый код никогда не надо держать в репозитории, лучше все удалять, мы всегда можем вернуться в истории и увидеть что происходит. У меня на этот счет сложилось другое мнение.

При рефакторинге, я комментирую и не удаляю любой не тривиальный код. Это очень помогает, когда нужно постоянно возвращаться назад или извлекать куски кода, которые ты вроде уже удалил, а оказалось что оно надо. Особенно это актуально если рефакторинг идет не один день и приходится постоянно возвращаться. К тому же если прошло время, то не всегда вспомнишь где был какой код если не будешь постоянно смотреть в историю гита. Вроде бы мелочь, а удобно.
👍65👎19😐9🤔3🐳32🔥2🤯1
Ребят, мы тут проходим в техорду (проект астаныхаба по обучению) и там для заявки нужно подтверждение выпускников из Казахстана. Если вы такой человек, напишите пожалуйста в комментариях. Я с вами свяжусь.
👍9🔥1🤔1
Forwarded from 23derevo (18+)
Смотрю доклад Кирилла Мокевнина на TechTrain, и охреневаю от качества звука и картинки. Непосвященные не догадаются, что это прямой эфир со спикером, который находится на другом конце земного шара.

Я не супер часто хвалю своих, но тут прямо заслуженно :)

Спасибо:
– Кириллу Мокевнину — за ответственный подход к докладу и своему оборудованию;
– командам OK/VK — за отличную реализацию видеозвонков;
– нашим ребятам — за SpeakerRoom;
– эфирным командам — за четкость процессов и профессионализм.

Да, ребят, хороший онлайн это долго, потно и дорого. Но оно того стоит.
🔥41👍10🤡7👏2😁2👎1🤔1
Open Source и рабочее время

На днях Сергей Андреев (Привет!) написал твит по поводу того что он смотрит на гитхаб https://twitter.com/DragorWW/status/1776456741175066801 и, как в таких случаях водится, получил в тачанку, что нет времени/не интересно/не важно заниматься опенсорсом. Среди разных доводов был один про то, что и так на работе пашем, времени на заниматься опенсорсом после работы нет.

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

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

Звучит логично, но на этом этапе появляются следующие возражения.

Я не встречал багов в библиотеках.

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

У меня нет времени коммитить в опенсорс (после работы), бизнесу нужны решения

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

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

У меня есть пулреквесты, которые были приняты через годы после того как я их отправлял (а я про них просто забыл). А еще разок приняли пулреквест в рельсу, после чего меня завалили предложениями о работе в международных компаниях.

p.s. Сколько у вас принятых пулреквестов в опенсорс?
👍36🔥12🤡107👎2🤔1
Мой подход в работе с зависимостями и их устареванию

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

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

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

Что еще важно, чтобы такой подход работал:

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

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

p.s. Как часто вы обновляете зависимости?
👍77🔥146🤔1
Кроме телеги я еще переодически веду твиттер канал, но не совсем понимаю насколько пересекается аудитория. Напишите плс смотрите ли вы его или нет? Потому что в основном это разный контент. Как пример https://twitter.com/mokevnin/status/1778514285917778078
👍13🔥2🤔1