Известно, что ошибки проще не допускать, чем исправлять и чем позже найдена ошибка, тем сложнее ее исправить. Не смотря на это у всех нас есть менеджеры дедлайны и тот кусок кода, который надо бы исправить после релиза.
Так вышло, что я бываю и разработчиком и менеджером время от времени, и поэтому вынужден смотреть на код с двух противоположных точек зрения. Как разработчику мне хочется, чтобы все было красиво и работало быстро, а вот как менеджеру мне очень хочется, чтобы релиз был во время. То есть, я как-бы страдаю легким раздвоением личности, потому что эти два человека хотят немного разных вещей. И вот, что я заметил. Стратегия идти на поводу у менеджера очень хорошо работает в средне-срочной перспективе и начинает трещать по швам в долгосрочной. Напарываться на мины замедленного действия, которые я заложил несколько месяцев, а то и лет назад было достаточно больно, поэтому я решил записать свой шорт-лист того, что надо было точно делать сразу.
Если не хоите ходить по моим граблям, добро пожаловать под кат.
База данных
Это место, которое будет больнее всего менять. С ростом приложения вы накопите некоторый объем данных. И ошибки в проектировании бд окажутся самыми дорогими, потому что все эти данные нужно будет сохранить. Первое на что стоит обратить внимание — возможность масштабирования вашего слоя бд. Добавить web-сервер сейчас не проблема: кругом облака и виртуализация. С базой данных все сложнее. Во первых, на ваш выбор две принципиально разные стратегии: репликация или шардинг. Кластеры я оставляю вообще за кадром. То есть нельзя просто так взять и досунуть сервер БД. Так что если есть вероятность того, что данных у вас будет не просто много, а очень много, все эти вопросы лучше продумывать заранее.
Кроме этого, БД-традиционно самое узкое место с точки зрения производительности. Как вы будете это разруливать? Может быть хватит слегка денормализовать БД или воткнуть CQRS или можно все удачно закешировать? Серебряных пуль, как обычно нет. Все зависит от специфики приложения. Все эти вопросы лучше задат себе заранее. Я не призываю стрелять из пушки по воробьям. На начальном этапе все это может казать жутким оверхедом и реализовывать супер-архитектуру сразу не нужно. Гораздо разумнее писать достаточно хороший на этом этапе код, но держать в голове план развития приложения на пару шагов вперед все-таки следует, чтобы не было мучительно больно потом.
Слои приложения и юнит-тесты
Вот этом место я уж никогда не буду менять… Так думал я когда-то, пока как-то раз мне не пришлось сменить фундаментальную логику приложения. Софт продает билеты и, в общем, однажды пришлось поменять логику заведения тех самых билетов. Это стоило мне двухнедельного рефакторинга, в ходе которого, я выстроил в приложении новый слой бизнес логики, потому что предыдущий мы тестировали только на уровне интеграционных тестов и замокать БД было просто невозможно. Слои DTO и Entity были перемешаны. Невозможность тестирования при этом не самая большая головная боль сильно связанности. Отсутствие порядка в слоях приложения говорит об отсутствии порядка в голове разработчика. Каждый новый фича-реквест начинает представлять собой очередной хак в самом неожиданном месте и вот уже бизнес-логика приложения равномерно размазана по всему коду. Такой код просто невозможно поменять, не создав при этом какой-нибудь побочный эффект, как всегда неожиданный, и в самый неподходящий. Так что ни одного серьезного приложения без тестов я уже давно не пишу. С юнитами просто невозможно перемешать слои приложения. У вас просто не получится написать тест, а это заставит вас критически переосмыслить текущую архитектуру.
Швы приложения и SRP
Как и в случае с БД слои приложения служат лишь одной цели — дать возможность в будущем быстро и безболезненно заменить часть вашей системы. Создать IFileStorage с единственной реализаций SimpleFileStorage гораздо проще, чем прочесывать все приложение в поисках записи в файловую систему, потому что вы решили переехать в облако. С опытом начинаешь уже кишками (или иными частями тела) чувствовать места, которые вероятнее всего изменятся. Каждый раз, нарушая SRP вы экономите минуты или часы своего времени сейчас, которые выльются в дни и недели потом. Быстро да, менеджер рад… сейчас. Потом возникнут вопросы, почему внести это мааааа-ленькое изменение так долго.
Масштабирование web-сервера
Невозможно постоянно наращивать мощности сервера. Рано или поздно вы упретесь в возможности канала. И вот тут ВНЕЗАПНО всплывут все статические переменные, которые вы использовали напрямую. Вообще горизонтальное масштабирование системы на всех уровнях это то, о чем нужно подумать заранее. И здесь снова, можно все-также не париться и писать в статические переменные ровно до того момента, пока вы не вставите еще один сервер. С учетом одного но. Делайте все эти грязные вещи внутри своего IDataProvier или IProblemResolver. Тогда придется менять только один класс, а не собирать изменения по всему коду.
ДевОпс
А как мы это будем разворачивать? Не ну у меня же все развернуто, я же не буду менять комп, переустанавливать ОС и заниматься прочими глупостями. А новые разработчики? Ну так они же программисты, это их работа, должны разораться. Ничего этого не надо документировать, а уже тем более не надо прилагать каких-то дополнительных усилий, чтобы это деплоилось проще.
Как-то раз мы разворачивали систему заказчика два дня на наших серверах. В ход пошло все: бубуен, тувинское народное горловое пение и самое главное Config Tool™. Без того самого кофиг тула вообще никто не мог заставить это работать. И я был бы счастлив, если бы это был инсталлятор. К сожалению, это было консольное приложение, которое надо было запускать в строго определенных условиях, после чего выкладывать архивы и разворачивать все руками на сервере. Просто без этого тула сконфигурировать всю пачку приложений никто не мог. Приложение многозначительно валилось с ошибками, совершенно не отражающими суть проблемы: например ругалось на сертификат, хотя проблема была в аторизации.
Ruby on Rails и ASP.NET давно уже предлагают и даже навязывают (и это правильно) простые и крутые способы разворачивания приложений. Пользуйтесь теми фишками, которые предлагает ваша среда. А если не предлагает, всегда можно сделать процесс разворачивания чуточку проще. Это касается не только уровня приложения. Полезно держать это в голове еще до того, как будет написана первая строчка кода. Если вы хотите поместить конфиг в базу данных, добавьте миграцию, чтобы в 2:00 AM не редактировать базу данных на продакшне, чтобы там был правильный конфиг. Другие разработчики в вашей команде тоже будут благодарны, если после очередного апдейта и VCS у них ничего не свалится от того, что теперь наше приложение работает с мега-супер новой штукой, которую нужно предварительно настроить с помощью бубна, тувинского народного горлового пения и духов.
Многопоточное программирование
Вы точно уверены, что вы умеете писать многопоточный код? Вы точно уверены, что оно вам надо вообще? Везде, где можно не писать многопоточного кода, пожалуйста, не пишите его. Интересно, клево да. И даже, возможно, на некоторых наборах данных на вашей машине он работает правильно. Многопоточное программирование — совершенно отдельная область знаний и писать его в разы сложнее однопоточного. Ровно как и отлаживать. Поберегите нервы себе и ваши коллегами.
Казалось бы вещи простые. Про все это говорили. Однако это то, что доставляет мне больше всего проблем на протяжении всего моего опыта работы в разработке программного обеспечения.
Автор: marshinov