• Как реализовывать структура скрипта с асинхронными запросами?

    @de1m
    Недавно что-то такое-же надо было. К примеру - у меня есть массив с серверами и на каждом сервере у меня есть несколько папок, которые надо проверить.
    self.startVerifyBackup(listOfServer).then(function (outArr) {
            return callback(null, outArr);
          }).catch(function (err) {
            return callback(err, null);
          });

    Здесть я передаю массив с серверам.
    Вот сама функция
    verifyBackup.prototype.startVerifyBackup = function (folderList) {
      var self = this;
    
      return Promise.all(folderList.map(function (folder) {
        return self.checkFolder(folder);
      }));
    };

    И функция которая проверяет все папки на каждом сервере
    verifyBackup.prototype.checkFolder = function (folder) {
      var self = this;
      return new Promise(function (resolve, reject) {
        if (self.config.backupserver[self.bserver].passphrase !== undefined && self.config.backupserver[self.bserver].passphrase !== null) {
          var passphrase = "PASSPHRASE=" + self.config.backupserver[self.bserver].passphrase;
        } else {
          var passphrase = "";
        }
        if (self.config.backupserver[self.bserver].tmpdir !== undefined && self.config.backupserver[self.bserver].tmpdir !== null) {
          var btemp = self.config.backupserver[self.bserver].tmpdir;
        } else {
          var btemp = "";
        }
    
        var command = "sudo " + passphrase + " duplicity verify file://" + folder + " " + btemp;
        self.runSSH(command, self.sshkeypath, self.eserver, self.bserver, function (err, data) {
          if (err) {
            return reject(err);
          } else {
    
            var output = data.toString().split("\n");
            output.splice(0, 2);
            var objReturn = {
              name: folder,
              output: output
            };
            return resolve(objReturn);
          }
        });
      });
    };


    Примерно так это должно выглядить, хотя я думаю, что у меня ошибки немного не верно обрабатываются.
    Ещё вместо promis'ов можно использовать библиотеку async. Но адепты promis'ов против, хотя там больше возможностей.
    Ответ написан
    Комментировать
  • Как правильно реализовать метод потомка для вызова метода предка?

    Kr0nic
    @Kr0nic
    Пишу код за еду
    public _Bar ToType()
    {
    	return new _Bar
    	{
    		FooField = FooField,
    		BarField = BarField
    	};
    }
    Ответ написан
    5 комментариев
  • Как сделать функцию-обёртку для игнорирования исключений?

    @rare
    Рекомендую вам использовать монады. Там есть примерно то, что вы пытаетесь сделать (монада try) + многое другое. Вот первое попавшееся из гугла: https://github.com/louthy/csharp-monad#try-monad
    Оно же в виде nuget-пакета: https://www.nuget.org/packages/csharp-monad/
    Ответ написан
    1 комментарий
  • Как сделать функцию-обёртку для игнорирования исключений?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    void IgnoreException(Action funcName)
    {
        try{ funcName();  }
        catch(Exception){}
    }
    
    void Func()
    {
        // код
    }
    
    void MyMethod()
    {
        IgnoreException(() =>
        {
            Func();
        });
    
        // Если запустить просто метод без параметров и возвращаемого значения, то можно так:
        IgnoreException(Func);
    }


    Но согласен с Free_ze. Вместо catch(Exception) лучше делать нужный конкретный тип исключения. Потому как может возникнуть другое исключение, и об этом вы не узнаете.
    Ответ написан
    1 комментарий
  • Как сделать функцию-обёртку для игнорирования исключений?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    interface ILogger {
        void LogException(Exception ex);
    }
    
    ...
    
    void IgnoreExceptions<ExType>(Action func, ILogger logger) where ExType : Exception {
        try { 
            func(); 
        }
        catch(ExType ex) {
            logger.LogException(ex);
        }
    }
    Ответ написан
  • Можно ли настроить nginx как smtp прокси с авторизацией по заданным парам login-password?

    Для решение вашей задачи подходят либо доверенные сервисы типа mailchimp, либо коррентно сконфигурированного почтового сервера, наличие у него dkim.
    Ответ написан
    3 комментария
  • Как правильно организовать классы?

    Я использую такой подход:
    Есть три интерфейса EntityInterface, RepositoryInterface, RepositoryDriverInterface
    interface EntityInterface extends Serializable {
        public function getId();
    }
    
    interface RepositoryInterface {
        public function getDriver();
        public function findById($id, EntityInterface $Entity);
        public function save(EntityInterface $Entity);
    }
    
    interface RepositoryDriverInterface {
        public function set($id, $data);
        public function get($id);
    }

    Драйвер репозитория работает с базой данных. Сам репозиторий занимается сериализацией/десериализацией сущностей. Примеры драйверов:

    Драйвер, работающий с массивами:
    class RepositoryDriverArray implements RepositoryDriverInterface {
        private $data = [];
    
        public function set($id, $data) {
            $this->data[$id] = $data;
        }
    
        public function get($id) {
            return $this->data[$id];
        }
    }

    Драйвер работающий с Redis'ом:
    class RepositoryDriverRedis implements RepositoryDriverInterface {
        protected $Redis = null;
    
        public function __construct(Client $Redis) {
            $this->Redis = $Redis;
        }
    
        public function set($id, $data) {
            $jsonData = json_encode($data);
            $this->Redis->hset($this->getContainerName(), $id, $jsonData);
        }
    
        public function get($id) {
            $jsonData = $this->Redis->hget($this->getContainerName(), $id);
            $data = json_decode($jsonData, true);
    
            return $data;
        }
    
        public function getContainerName() {
            return 'myContainer';
        }
    }

    Пример реализации самих репозиториев:
    abstract class AbstractRepository implements RepositoryInterface {
        protected $RepositoryDriver = null;
    
        public function __construct(RepositoryDriverInterface $RepositoryDriver) {
            $this->RepositoryDriver = $RepositoryDriver;
        }
    
        public function save(EntityInterface $Entity) {
            $this->getDriver()->set($Entity->getId(), $Entity->serialize());
        }
    
        public function findById($id, EntityInterface $Entity) {
            $data = $this->getDriver()->get($id);
            $Entity->unserialize($data);
    
            return $Entity;
        }
    
        public function getDriver() {
            return $this->RepositoryDriver;
        }
    }

    Далее, пишем бизнес-логику:
    class User implements EntityInterface {
        // TODO: Implement methods
    }
    class UserRepository extends AbstractRepository {}

    И вот так работаем со всей этой системой:
    $Redis = new Client([/* connection params */]);
    $RedisDriver = new RepositoryDriverRedis($Redis);
    $UserRepository = new UserRepository($RedisDriver);
    
    $User = new User();
    $UserRepository->save($User);
    
    $User = new User();
    $UserRepository->findById(1, $User);

    Пишем юнит тесты? Подменяем драйвер репозитория:
    $ArrayDriver = new RepositoryDriverArray();
    $UserRepository = new UserRepository($ArrayDriver);
    
    $User = new User();
    $UserRepository->save($User);
    
    $User = new User();
    $UserRepository->findById(1, $User);


    Такую систему очень просто тестировать. Всю "рутину" можно обернуть в различные фасады, "конфигураторы", провайдеры.
    Я написал лишь примеры, конечно, в реальной системе больше возможностей драйвера, репозиториев.
    Кэширование стоит делать на уровне репозитория. Драйвер занимается только сохранением/загрузкой данных.
    Ответ написан
    1 комментарий
  • Как правильно организовать классы?

    nazarpc
    @nazarpc
    Open Source enthusiast
    Вы никогда не работаете "через интерфейс", хотя бы потому что он не имеет реализации.
    Но вы можете сделать следующее:
    ...
    public function setRepository (RepositoryInterface $repository) {
        $this->repository = $repository;
    }
    ...


    Таким образом передать в качестве аргумента можно любой объект, класс которого реализует RepositoryInterface, и только такой объект. Так же можно передавать его в конструкторе при создании объекта, если он обязательно нужен.

    А вообще рекомендую почитать про Inversion of Control (IoC) и Dependency Injection (DI) - это вещи, которые вы захотите использовать с таким подходом.
    Ответ написан
    1 комментарий