Ответы пользователя по тегу Проектирование программного обеспечения
  • Выбор средств для разработки высоконагруженного веб приложения?

    Главная фишка высоконагруженных приложений не в выборе технологий, а в архитектуре. Зачастую, узким местом приложения является база данных. Первое, что нужно сделать - это научиться масштабировать данные. Ищем по ключевым словам "шардирование", "репликация".
    После того, как данные масштабируются, можно думать о включении кэширующего слоя. Ищем "memcached", "redis".
    Если начинает не справляться фронтенд (фронтенд бэкэнда), подключаем балансировщик нагрузки. Как на уровне DNS, так и на уровне отдельных инстансов фронтенда.
    Раздаете много статики? CDN вам в помощь.
    Много сложных и ресурсоемких вычислений, результат выполнения которых не требует моментального отображения клиенту? Разворачиваем очереди задач и считаем это в фоне.
    А уж какую технологию выбрать java или php это Вам виднее. То, что лучше знаете и сможете поддерживать.

    Советую почитать ruhighload.com/scale
    Ответ написан
    1 комментарий
  • Как правильно спроектировать приложение?

    Почитайте про паттерны. Мне очень помогла книга "Чистый код" (www.ozon.ru/context/detail/id/21916535/).

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

    Разбиваем программу на сущности: User, News, Page.
    У каждой сущности есть свое хранилище: UserStorage, NewsStorage, PageStorage. Хранилище занимается только тем, что управляет сущностью в БД: save, load, delete, etc.
    При создании, хранилище прнимает соединение с БД и сохраняет его "в себе".
    Код при этом получается примерно такой:
    $Connection = ConnectionPool::getConnection('users');
    $UsersStorage = new UserStorage($Connection);
    
    $User = $UsersStorage->loadById(1);
    $User->set('name', 'Yakob');
    $User->get('name');
    $UserStorage->save($User);
    $UserStorage->delete($User);


    Аналогично другими сущностями.
    Сразу же прослеживается связь между сущностями и хранилящами между собой. Выделяем абстракцию, например AbstractStorage. Выносим в нее общие части хранилищ.
    Приведенный код создания хранилища можно скрыть, например за фасадом примерно так:
    class UserFacade {
        protected static $UserStorage = null;
    
        public static function getById($id) {
            return self::getUserStorage()->getById($id);
        }
    
        public static function save(User $User) {
            return self::getUserStorage()->save($User);
        }
    
        protected static function getUserStorage() {
            if (is_null(self::$UserStorage)) {
                $Connection =  ConnectionPool::getConnection('users');
                self::$UserStorage = new UserStorage($Connection);
            }
    
            return self::$UserStorage;
        }
    }


    Все остальное - разные укровни бизнес логики. Нужно получить новости юзера? Создаем класс например UsersNewsStorage, который наследуется от NewsStorage. Есть метод getFeed
    Код примерно такой получается:
    ....
    $User = $UserStorage->getById(1);
    $UsersNewsStorage = new UsersNewsStorage($Connection);
    $Feeds = $UsersNewsStorage->getFeed($User);


    Нужна валидация новостей? Хранилище (NewsStorage) мы не трогаем, оно занимается только тем, чем занимается. Остальное бизнес логика.
    Добавляем валидацию в UsersNewsStorage.
    $User = $UsersStorage->loadById(1);
    $News = new News(['title'=>'AAA', 'body'=>'bbbbbb']);
    $UsersNewsStorage = new UsersNewsStorage($Connection);
    try {
      $UsersNewsStorage->saveNews($User, $News); // Внутри валидация
    } catch (ValidationNewsErrorException $Ex) {
      // Валидация не прошла
    }


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