Полгода назад у меня был один бот для поиска лидов — LeadFinder. Он жил в Telegram: парсил публичные чаты, ловил людей по ключевым словам, передавал в работу. Один сервер, один docker-compose, всё помещалось в голове.
Потом случился MAX. Российский мессенджер, который начал расти, и в котором сидит часть аудитории, до которой через Telegram не достучишься. Возник вопрос: делать ли там то же самое.
Сначала очевидное решение — взять LeadFinder, склонировать репозиторий, переписать парсер под MAX, назвать leadfinder-max. На это уходит вечер. И ты получаешь второй бот, который теперь надо поддерживать отдельно. Нашёл баг в AI-оценке лидов — чини в двух местах. Добавил новую интеграцию — катай в две репы. Это работает ровно до момента когда захочется в третий мессенджер.
Я сел и сделал нормально. Вытащил общее в ядро: AI-оценка, рассылка, база лидов, интеграции с CRM, фильтры. А специфика мессенджера ушла в отдельный слой — «источник». Telegram-источник умеет ходить через MTProto и Playwright. MAX-источник ходит через свои методы. Сверху всё одинаково: лид это лид, неважно откуда он пришёл.
В итоге LeadFinder остался в Telegram. MaxSurge живёт в MAX. Снаружи это два продукта, под капотом — общий двигатель. Когда я улучшаю фильтрацию лидов, она автоматически улучшается в обоих. Когда чиню баг в рассылке — он чинится один раз.
Звучит банально — «вытащи общее, оставь различное». Но именно эту банальность 90% проектов не делают вовремя. Сначала кажется «ну ещё один клон, я быстро скопирую». Потом ещё один. И ты — разработчик-многостаночник, который чинит одну и ту же проблему в семи репозиториях.
Один баг чинится один раз. Это и есть разница между продуктом и ремеслом.
