Продолжаю продолжать рассказывать о работе над своим проектом. В одну каску пилить скучновато и хочется с кем-то делиться процессом :)
В этой серии: о выборе стэка фронта и бэка и немного по подходе к архитектуре.
Ну и сперва пара слов об архитектуре. Фронт, понятное дело, SSR. Мне ведь нужно отдавать в парсеры поисковиков и нейронок публичные посты и комментарии и всякие другие публичные сущности типа статей, рассказов, аннотаций и т.д…
Так как я наиболее комфортно себя чувствую с vue, взял Nuxt. В качестве ui либы пока взял Nuxt ui kit. Он выглядит довольно зрелым и удобно кастомизируемым. Если появится необходимость, в будущем плавно перееду на собственную компонентную базу. Пока не горит вот совсем.
По бэку интереснее. Требований ту больше: 1. У меня нет ни желания, ни возможности тратить кучу бабла на инфру, а значит нужен язык, который создаёт минимальную нагрузку на оперативку и эффективно утилизирует вычислительные возможности машины, строго типизированный, не сложный в освоении, с хорошим тулкитом и чтобы с ним легко было работать нейронке. JS сюда не попадает сразу по ряду признаков. TS тоже отваливается из-за пухлого node_modules, тяжеловатого рантайма js и плохой работы с многопоточностью. Да и ORM у JS тяжеловаты. Rust хороший вариант, но его механизмы заимствования меня порой всё ещё ставят в тупик. C++… свят-свят! Выбрал go с gin роутером и sqlc как комфортным для меня балансом между абстракциями и ручным контролем кода. Единственное, чем мне не нравится нынешний go — плохая работа с дженериками, но это можно пережить.
2. Непосредственно архитектура. Как уже писал выше, я не готов тратить кучу денег на инфру, поэтому микросервисы отпадают сразу. На них нужно выделять кучу ресурсов, оркестратор, брокер… это дорого. При этом я не хочу полностью отказываться от удобства модульной разработки, поэтому решил пилить модульный монолит. То-есть, фактически у меня монолит, но каждая значимая бизнес-сущность выделена в максимально независимый модуль, который общается с другими модулями через consumer абстракцию и in-memory симуляцию шины событий. Это позволяет относительно безболезненно выделить модуль в микросервис, когда это мне реально понадобится. consumer меняет прямые вызовы публичного api на grpc запросы к нужным сервисам, а in-memory шина подменяется каким-нибудь NATS. За счёт фасада сами сервисы подмены вообще не заметят.
3. БД.
Конечно, Postgres. Сначала размышлял над тем, чтобы каждому модулю сделать выделенную схему, но пришёл к выводу, что ебли проблем это добавит больше, чем пользы. Потому сделал единую базу. И пока не жалею. Так намного удобнее делать кросс-модульные инкременторы через процедуры.
Ну и пока хватит. Продолжение в следующей серии. Могу рассказать о том, как сделал аутентификацию или начать рассказывать о процессе разработки через нейронку. Конечно вариация спек-драйвен :D