Я создаю класс C ++ для выполнения команд SSH, используя libssh2.
Жизненный цикл SSH-сессии libssh2 проходит следующие этапы:
Перед шагом 1 мы должны открыть сокет, который мы передаем libssh2 на шаге 2. С этого момента нам больше не нужно передавать сокет, так как libssh2 будет хранить ссылку на него. После шага 4 мы можем закрыть сокет.
Я разоблачаю это через класс (SSHSession
) и я бы хотел настроить (шаги 1 и 2) произойти на ctor и срывать (шаги 3 и 4), которые должны выполняться в dtor (поскольку шаг 2 занимает много времени, это позволит мне сохранить пул сессий открытым и использовать его для выполнения команд).
Моя первая попытка сосредоточить весь код на SSHSession
и его ctor быстро превратился в беспорядок, с рутиной «если этот шаг не пройден, тогда мы должны увидеть, что уже сделано и отменить это»; Дтор был не так сложен, но я все же нашел его слишком «занятым».
Затем я разделил работу между несколькими классами, реализуя RAII для каждого шага получения / выпуска, а именно:
Я создал класс SessionConnection
который реализовал шаги 2 и 3, и имел член типа SessionHandle
которые реализовали шаги 1 и 4; он также имел сокет в качестве члена данных, создавая зависимость первого порядка от ctor / dtor — сокет не мог быть уничтожен до SessionHandle
член.
Рассматривая свой дизайн, я решил, что могу организовать шаги 2 и 3 следующим образом:
2.1. Handshake (устанавливает сеанс SSH на удаленном хосте)
2.2. Аутентификация
3. Отключение (завершает сеанс SSH на удаленном хосте)
Что означает, что я мог бы еще больше упростить мой SessionConnection
class, реализуя другой класс для выполнения RAII на шагах 2.1 и 3, и заканчивая чем-то вроде этого:
SSHSession
имеет SessionConnection
элемент данных.SessionConnection
реализует шаг 2.2.SessionConnection
имеет элемент данных сокета.SessionConnection
имеет SessionHandle
элемент данных, который реализует шаги 1 и 4. Это должно быть уничтожено перед сокетом.SessionConnection
имеет RemoteSessionHandle
элемент данных, который реализует шаги 2.1 и 3. Он должен быть создан после и уничтожен до SessionHandle
элемент данных.Это значительно упрощает мои ctors / dtors, любезно предоставленные RAII. И я нахожу концептуально звук; если, с одной стороны, мы можем рассматривать их как состояния, через которые проходит сеанс SSH, с другой стороны, мы также можем видеть их как ресурсы (локальные, удаленные), которыми мы управляем.
Однако теперь у меня строгий порядок строительства / уничтожения в SessionConnection
и хотя я считаю, что это улучшение (и я не нашел ничего в своем исследовании, в котором говорилось, что «это зло», только «это должно быть четко задокументировано»), мне интересны другие мнения, и я с радостью приму информацию / указатели о возможных альтернативах этой конструкции.
На что я смотрел, пока:
Спасибо за ваше время.
Кажется, в этом дизайне нет ничего принципиально неправильного.
Если вы хотите снять ограничение на порядок строительства / уничтожения членов SessionConnection
Вы могли бы сделать следующее:
SSHSession
SSHConnection
членSSHConnection
LocalSessionHandle
членLocalSessionHandle
Socket
членОпределенный порядок построения / уничтожения элементов и их содержащих классов обеспечивает выполнение шагов в правильном порядке.
Других решений пока нет …