• Почему Service Locator это зло и что использовать вместо?

    FanatPHP
    @FanatPHP
    Чебуратор тега РНР
    Все эти страшные слова - они на самом деле всегда про одно и то же - про связность. Когда ты хардкодишь внутри класса вызов какого-то конкретного сервиса - ты намертво к нему привязываешься. И чтобы поменять сервис на другой, ты будешь вынужден поменять код класса. Окей, поменял. И тут же в другом месте, где этот же класс использовался, что-то сломалось! И что теперь? Делать два класса, которые различаются одной строчкой? Нет конечно. А как тогда использовать один и тот же класс для обработки разных входящих данных (или одних и тех же данных, но разными способами)? Сделать его поведение изменяемым. То есть сделать изменяемыми те инструменты, которыми он пользуется - т.е. его зависимости.

    Поэтому все зависимости обычно передаются через конструктор (и поэтому и называются инъекция зависимостей.)

    Таким образом мы можем менять поведение класса, не меняя его код

    Но тут надо понимать, что всё это работает только при правильном применении ООП. А точнее просто при применении ООП. Потому что 98% "ООП" кода, который пишется на РНР - это голимая процедурщина, даже если она обёрнута в классы и методы. Если у тебя метод класса представляет из себя стену кода, которую ты тупо перенёс из файла, инклюдившегося в любимое похапешное спагетти - то это не ООП. Это та же процедурщина, вид сбоку. И смысл использования dependency injection ты с ним не почуствуешь. Будешь конечно применять, но в качестве карго культа - потому что тебе это на тостере написали.
    А вот когда твой код начнет становиться действительно объектным - тогда стразу станет понятнее.


    Похожим на сервис локатор является сервис- или DI-контейнер. Используемый вручную, он является тем же самым сервис локатором. Поэтому вручную его никогда не надо вызывать - что и запрещается в симфоневских конроллерах - а только для автоматического создания классов. В МВЦ у тебя ведь очень многие объекты создаются автоматом - сущности, контроллеры. И вот для того, чтобы при автоматическом создании экземпляра класса у тебя были на руках все требуемые сервисы - и нужен контейнер.

    Соотвтственно, ответ на вопрос "что использовать?" очень простой:
    - при ручном создании экземпляра объекта, все зависимости передавать в него через конструктор, а не получать "из воздуха" в коде.
    - при автоматическом создании экземпляра объекта, использовать dependency injection container

    В этим смысле очень полезно освоить Симфони - строгий фрейворк, в котором нет сервис локатора и в котором запрещено пользоваться контейнером напрямую.
    Ответ написан
    4 комментария
  • Какой сервис выбрать для расчета маршрута и как создать собственный сервис с интерактивными картами?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    По требованиям все кроме третьего пункта (про стоимости) умеет osrm. К нему же идёт опенсорсный фронтенд, который можно допиливать.

    В обоих ваших вариантах вы написали какую-то чушь.
    Тайловый рендер разворачивается в докер-контейнере за 5 минут. Как и osrm. Сложно будет настроить все это под ваши хотелки, но можно.
    Бд - postgis. Есть тулза, которая импортит снапшот osm данных: https://wiki.openstreetmap.org/wiki/Osm2pgsql
    Можете придумать или поискать тег для указания стоимости проезда по дороге и везде проставить. По построенному osrm маршруту потом дополнительным запросом к бд можно вытащить дороги с ценами
    Ответ написан
    Комментировать
  • Как правильно написать функционал подписки на события как addEventListener или .on в jQuery?

    RAX7
    @RAX7
    class EventsBus {
      constructor() {
        this._callbacks = {};
        this._id = 1;
      }
    
      emmit(eventType, data) {
        if (!this._callbacks[eventType]) {
          return;
        }
        this._callbacks[eventType].forEach(item => item.cb(data));
      }
    
      on(type, callback) {
        if (!this._callbacks[type]) {
          this._callbacks[type] = [];
        }
    
        const id = this._id++;
        this._callbacks[type].push({
          id: id,
          cb: callback,
        });
        return { id, type: type };
      }
    
      revoke(prop) {
        const { type, id } = prop;
    
        if (!this._callbacks[type]) return;
    
        const index = this._callbacks[type].findIndex(item => item.id === id);
        if (index !== -1) {
          this._callbacks[type].splice(index, 1);
        }
      }
    }
    
    const bus = new EventsBus();
    
    bus.on('hello', (data) => console.log('hello', data));
    
    const evt1 = bus.on('boom', (data) => console.log('boom1', data));
    const evt2 = bus.on('boom', (data) => console.log('boom2', data));
    const evt3 = bus.on('boom', (data) => console.log('boom3', data));
    
    bus.revoke(evt1);
    
    bus.emmit('boom', 42);
    bus.emmit('hello', '!!!');
    Ответ написан
    Комментировать
  • Как правильно написать функционал подписки на события как addEventListener или .on в jQuery?

    @StockholmSyndrome
    class SomeClass {
      callbacks = []; 
    
      
      on(eventType, cb) {
        this.callbacks.push({
          type: eventType, 
          callback: cb
        });
      }
    
    
      emit(type, ...args) {
        this.callbacks
          .filter((n) => n.type === type)
          .forEach((n) => n.callback.call(this, ...args));
      }
    }
    Ответ написан
    Комментировать
  • Как реализовать прием команд приложению на node js на сервере?

    Xuxicheta
    @Xuxicheta
    инженер
    Да как угодно, в данном случае проще всего вебсокет открыть. Только авторизацию сделать простейшую, jwt как раз подойдет.
    Ответ написан
    2 комментария
  • Как открыть порт в ubuntu?

    it_monk
    @it_monk
    Разработчик в oncloud.ru
    Ещё есть такая хорошая штука как ufw (ubuntu firewall), порт с помощью неё включается так:

    ufw allow 32348
    Ответ написан
    Комментировать
  • Как в symfony 3.4 вывести логин (или какие-либо данные) в базовый шаблон?

    BoShurik
    @BoShurik Куратор тега Symfony
    Symfony developer
    1. Рендер контроллера внутри шаблона
    https://symfony.com/doc/3.4/templating/embedding_c...
    {{ render(controller(
        AppBundle:Article:recentArticles',
        { 'max': 3 }
    )) }}

    2. Кастомный Twig Extension, который добавляет функцию, реализующую нужную логику
    https://symfony.com/doc/3.4/templating/twig_extens...
    {{ articles(3) }}
    3. Если надо выводить что-то простое, к примеру, версию приложения, то можно использовать глобальные переменные
    https://symfony.com/doc/3.4/templating/global_vari...
    {{ app_version }}
    4. Какие-то вещи доступны в глобальной переменнойapp, к примеру, тот же инстанс залогиненого пользователя
    {{ app.user.username }}

    Это справедливо для всех версий Symfony
    Ответ написан
    Комментировать
  • Как в symfony 3.4 вывести и отправить форму для сущности в списке сущностей?

    BoShurik
    @BoShurik Куратор тега Symfony
    Symfony developer
    $form = $this->container->get('form.factory')
        ->createNamed(
            'account_'. $account->getId(), 
            AccountType::class, 
            $account
        )
    ;


    По поводу кода
    public function indexAction(Request $request)
    {
        $accounts = $this
            ->getDoctrine()
            ->getRepository('AppBundle:Account')
            ->findActive();
    
        $forms = [];
        foreach ($accounts as $key => $account){
    
            $form = $this->container->get('form.factory')->createNamed('account_'. $account->getId(), AccountType::class, $account);
    
            // Не надо добавлять кнопки сабмита, их рекомендуется добавлять непосредственно в шаблоне обычным html
            // $form->add('submit', SubmitType::class);
    
            $form->handleRequest($request);
    
            // Не надо инжектить форму в сущность, легче просто передать формы в шаблон
            // $account->setForm($form);
            // $account->setFormView($formView);
    
            if($form->isSubmitted() && $form->isValid()){
    
                // Объекты передаются по ссылке, нет смысла в получение $account повторно
                // $data = $form->getData();
    
                $this->addFlash('success', 'Saved');
    
                $em = $this->getDoctrine()->getManager();
                // Это актуально только для создания сущности, при редактировании - это не нужно
                // $em->persist($data);
                $em->flush();
    
                return $this->redirectToRoute('account_list');
            } else {
                $forms[$account->getId()] = $form->createView();
            }
        }
    
        return [
            'forms' => $forms,
            'accounts' => $accounts,
        ];
    }


    {# {{ form_row(account.formView) }} #}
    {{ form_start(forms[account.id]) }}
        {{ form_widget(forms[account.id]) }}
        <button>Submit</button>
    {{ form_end(forms[account.id]) }}


    P.S. В идеале бы разделить обновление и список сущностей по разным экшенам
    Ответ написан
    2 комментария
  • Какие сервисы/хостинг могут запустить программу на nodejs, electron и puppeteer на удаленном сервере?

    Jump
    @Jump Куратор тега Системное администрирование
    Системный администратор со стажем.
    Вам нужен виртуальный сервер.
    Для начала нужно определится с ресурсами - сколько ресурсов (памяти, процессора, диска, и.т.п) нужно вашему сервису, насколько важна стабильная работа, насколько важна поддержка, и выбирать из кучи предложений сервер который вас устроит.
    Многие предоставляют площадки размещения VPS на выбор - например можно выбрать площадку в Германии, России, США, или где-то еще.
    В общем запрос в поисковике "VPS сша" выведет вам кучу вариантов, вам только надо выбрать подходящий вам по цене, стабильности. Проверить тот же пинг с сервера до нужного вам ресурса. Многие дают тестовый период чтобы попробовать, оценить.
    Ответ написан
    Комментировать
  • Какие сервисы/хостинг могут запустить программу на nodejs, electron и puppeteer на удаленном сервере?

    saboteur_kiev
    @saboteur_kiev Куратор тега Системное администрирование
    software engineer
    Все мои попытки поиска оканчивались обычным хостигном для сайта или виртуальным сервером для того же веба, сам я не очень разбираюсь в сис. администрировании.


    Ну так все верно - для работы с GUI вам нужна виртуальная машина (виртуальный сервер, VPS). Хостинг это обычно для бэкенда.
    Ответ написан
    Комментировать