• Как должен выглядеть идеальный контроллер?

    Если хотите идеал, то он должен соответствовать следующим пунктам:

    1. Сериализация/десериализация - это дорогостоящее мероприятие, поэтому оно должно делаться только в двух местах: прямо на входе и прямо на выходе. Вход - это ваш контроллер, Выход - это другой сервис, куда вы передаёте данные, или база данных (тут тоже происходит сериализация, либо явно, либо в ORM). Во всех остальных слоях инфообмен должен совершаться уже при помощи объектов PHP либо нативных типов. Это экономит ресурсы. При передаче между слоями приложения объектов вместо значений либо ассоциативных массивов вы сразу будете видеть очепятки, IDE вам прекрасно поможет при помощи автодополнения, объекты могут иметь какие-то полезные методы.

    2. Очень желательно в каждом из слоёв иметь собственный класс, отвечающий за данные. Например, нам в слой API приходит JSON-чик с новым пользователем.
    - Сериализуем JSON в DTO UserInAPI, сразу валидируем всё то, что мы можем валидировать без слоя бизнес-логики, и либо отдаём клиенту ошибку, либо передаём сам объект UserInAPI в следующий слой: слой бизнес-логики
    - В слое бизнес логики, получаем DTO UserInAPI на входе, преобразуем его в свой бизнес-объект UserInBusiness, валидируем его уже с точки зрения бизнеса, и либо возвращаем ошибку в слой API, либо совершаем над ним действия, и передаём объект класса UserInBusiness в слой работы с базой
    - В слое работы с базой данных получаем на входе объект UserInBusiness, преобразуем его уже в сущность базы данных UserInDB, валидируем всё на предмет корректности данных для базы, и либо возвращаем ошибку в бизнес, либо сохраняем сущность класса UserInDB в базу.

    Зачем такие сложности, вы спросите? А просто обратите внимание на то, что скорость изменения кода в разных слоях разная.
    - API вообще должен меняться раз в сто лет, чтобы не злить клиентов. Поэтому DTO класс UserInAPI будет стабильным и редко будет меняться.
    - Бизнес-логика меняется очень часто. У класса UserInBusiness постоянно будут добавляться поля и методы, тут жизнь будет кипеть.
    - Слой базы данных будет меняться реже, чем слой бизнеса, но чаще, чем слой API, потому что нам нужны будут новые поля в базе, новые таблицы и связанные таблицы.
    - И если мы один тип сущности протащим во все слои, то эта сущность обрастёт таким количеством различной хрени, что нам плохо станет, когда будем на неё смотреть. Либо она обрастёт кучей декораторов в каждом из слоёв. Поэтому лучше всё разделить.

    3. Теперь внимание, казалось бы, что мы слишком сильно связываем наши слои, и нижестоящие слои знают что-то о вышестоящих, а это неправильно. Ведь мы передаём объект UserInAPI в слой бизнеса, т.е. слой бизнеса должен уметь работать с этим объектом. И так же слой базы должен уметь работать с объектом бизнеса UserInBusiness. Как же быть? А очень просто. На входе слоёв использовать интерфейсы. Т.е. в слое бизнеса мы будем принимать не сам класс UserInAPI, а объект, имплементирующий интерфейс UserIncoming, который объявим в бизнес слое, и заставим слой API сделать так, чтобы его класс UserInAPI имплементировал этот интерфейс. Таким образом слой бизнеса ничего не будет знать о слое API, а будет ждать на входе данные по контракту, описанному в интерфейсе. Бизнесу плевать на конкретную реализацию, ему нужны только методы getUsername, getEmail из интерфейса. А какой класс ему их предоставит - пофигу. Таким образом мы практически полностью разделяем слои и в два счёта сможем поменять слой API, где у нас HTTP контроллеры, на слой RabbitMQ, SOAP, Grpc и т.д.
    Ответ написан
    6 комментариев
  • Что выбрать: sqlite или redis?

    Вдруг будет слишком долго?
    Не будет. Забудьте вообще на данном этапе своего обучения про существование такого понятия как "скорость", пока не столкнётесь с тормозами в реальности.
    Хочется redis
    Его сложнее администрировать, чем sqlite. Но если хотите - развлекайтесь.
    Ответ написан
    1 комментарий
  • Существуют ли технологии блокировки записи с экрана в веб-технологиях?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Даже на закрытых плеерах с DRM эта защита не спасает. Ничто не помешает переткнуть кабель из монитора в карту видеозахвата. Или тупо поставить перед монитором камеру.
    Ответ написан
    Комментировать
  • Существуют ли технологии блокировки записи с экрана в веб-технологиях?

    @Drno
    Ну скорее всего никак. Кому надо тот всё равно запишет, так или иначе.
    Например я могу запустить ОС в вриртуалке, открыть сайт, а видео записывать средствами управления виртуализацией.. например в Vbox такое есть)
    Ответ написан
    Комментировать
  • Почему ошибка в передаче параметров в функцию в TypeScript?

    Alexandroppolus
    @Alexandroppolus
    кодир
    Property 'children' does not exist on type 'AuthProviderProps

    Да, поменялось. FC теперь из коробки не содержит children

    type AuthProviderProps = PropsWithChildren<{
        userManager: UserManager;
    }>;
    Ответ написан
    Комментировать
  • Почему имя параметра может совпадать с именем члена класса?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Как плюсы понимают, что с одной стороны параметр, а с другой - член класса?

    Это называется семантический разбор. На вход компилятору подается исходный текст, на выходе - дерево выражений (очень грубо говоря).
    Существуют правила, по которым эти деревья строятся. Например, БНФ.
    Вот в них и описывается что и где может находиться. В данном случае, в списке инициализации могут находиться только члены класса, но ты передаешь еще и параметры. В этот момент компилятор сходит с ума, т.к. нарушаются эти правила .
    P.S. чтобы подобных проблем не было, то для полей классов используй префикс подчеркивания
    Ответ написан
    7 комментариев
  • Банят аккаунты в телеграмме при использовании библиотеки telethon. Кто-то находил решение?

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

    Если тебе нужно что-то типа аккаунта для бизнеса, то тогда посмотри в сторону ботов для бизнеса
    Ответ написан
    Комментировать
  • Как извлечь информацию в JavaScript?

    @Everything_is_bad
    https://learn.javascript.ru/ а то ты начал сюда бегать на каждый чих про работу на стороне клиента
    Ответ написан
    1 комментарий
  • Как посмотреть массив до применения map?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    И что тут особенного? Объекты в JS копируются по ссылке.
    const a1 = [{ "id": "1" }, { "id": "2" }, { "id": "3" }];
    Здесь создаётся массив, в котором три ссылки на объекты.

    let a3 = [...a1];
    Здесь производится декомпозиция массива и из этих трёх ссылок формируется новый массив. Сами ссылки при этом остаются неизменными.

    let a4 = a1.slice();
    Опять таки, ссылки не меняются и ведут на те же самые объекты.

    const a2 = a1.map(i => {
        i["name"] = "Name" + i["id"];
        return i;
    });
    Здесь в объекты по ссылкам добавляется новое поле и как результат каллбэка возвращается ссылка на объект. Соответственно в a2 те же самые ссылки.

    В результате имеем четыре массива, в которых ссылки на одни и те же объекты.

    Чтобы не менять исходные объекты, надо из них строить новые:
    const a2 = a1.map((o) => ({ ...o, name: `Name${o['id']}` }));
    Ответ написан
    1 комментарий
  • Какой самый простой способ организовать SSO?

    AshBlade
    @AshBlade
    Просто хочу быть счастливым
    Самый популярный фреймворк для SSO - OAuth.
    Про него много где уже писали. Например, вот некоторые ссылки:
    - https://habr.com/ru/articles/77648/
    - https://habr.com/ru/companies/vk/articles/115163/
    - https://oauth.net/2/

    Также есть еще и OpenID Connect. Это фреймворк построенный вокруг OAuth:
    - https://habr.com/ru/companies/nixys/articles/566910/
    - https://openid.net/developers/how-connect-works/

    Поймешь как они решают эту проблему - поймешь как решить свою.
    На вопрос прямого ответа не дам - много букв
    Ответ написан
    Комментировать
  • Как защитить программу от копирования без интернета?

    wataru
    @wataru
    Разработчик на С++, экс-олимпиадник.
    Никак. Единствнный способ гарантированно защититься от нелицензионного копирования - это вынести ключевую часть функционала на сервер. Любая остальная защита - лишь усложнение реверс инжениринга и взлома. Всегда можно каленым железом вырезать любую проверку ключа из исполняемого кода.

    Активация ключа по телефону/интернету исключает лишь самый тривиальный способ "взлома" - просто копирование одной и той же лицензии по куче компьютеров без модификации исполняемых файлов.

    А так, берете какую-нибудь крипто библиотеку, выдаете сертификат, в котором подписываете своим приватным ключем "Лицензия выдана ООО рога и копыта". В программе зашит ваш публичный ключ. Программа проверяет файл лицензии, что он подписан вашим ключем. Но любой "хакер" умнее вас просто вырежет эту проверку из программы.
    Ответ написан
    4 комментария
  • Почему не срабатывает функция?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Дык onclick - это свойство. В нём одновременно может быть только одна функция.
    Используйте addEventListener.
    Ответ написан
    1 комментарий
  • Нужно ли писать суффиксы литералов?

    mayton2019
    @mayton2019
    Bigdata Engineer
    Во всех случаях мы описали тип слева. Тоесть задача типизации - выполнена.
    float a = 1.0f;
    unsigned int a = 10u;

    Я думаю что ничего дополнительно указывать не надо. В противном случае у code-reviewer
    это вызывает удивление и очередной WTF. Тоесть вам придется объяснять своему коллеге
    ДЛЯ ЧЕГО вы ввели в исходные код дополнительную информацию.

    Нужно писать так чтобы у коллег к вашему коду вообще не возникало вопросов.
    Ответ написан
    Комментировать
  • Почему startOfDay возвращает неравильное время для UTC зоны?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    RTFM
    startOfDay
    Return the start of a day for the given date. The result will be in the local timezone.
    Ответ написан
    Комментировать
  • На чем писать маленький портал для тестирования сотрудников?

    zkrvndm
    @zkrvndm
    Архитектор решений
    Используй Google формы: https://www.google.ru/forms/about/
    Ответ написан
    Комментировать
  • Что такое upstream в Git?

    sergey-kuznetsov
    @sergey-kuznetsov Куратор тега Git
    Автоматизатор
    Гит — это распределенная система. Мы можем иметь много равноправных репозиториев и обмениваться информацией между ними. Тот репозиторий, в который мы сейчас коммитим, будет локальным. А другие репозитории, в которые отправляем (push) или из которых получаем (fetch), они внешние (вышестоящие, upstream, remotely)
    Часто говорят удаленные, но это не очень уместный перевод слова remote в данном контексте. Потому что появляются странные формулировки типа «удалить удаленный»

    Именем upstream ещё принято обозначать исходный репозиторий, от которого мы сделали форк на GitHub, так как имя origin уже занято и указывает на форк. Поэтому адрес исходного репозитория, при необходимости, сохраняем в переменной upstream. В данном контексте это просто традиция, и назвать ссылки на внешние репозитории мы вольны как угодно. Команда git remote лишь создаёт переменные, в которых мы храним URL внешних репозиториев, чтобы затем использовать имя переменной в командах, вместо того, чтобы писать длинный URL.
    Ответ написан
    Комментировать
  • Ошибка при JSON.parse как исправить?

    ipatiev
    @ipatiev Куратор тега PHP
    Потомок старинного рода Ипатьевых-Колотитьевых
    А вы можете объяснить, зачем вам здесь вообще JSON.parse?
    И почему нельзя написать просто
    var dataJSONArray = <?= json_encode($u,JSON_UNESCAPED_UNICODE) ?>;
    Ответ написан
    1 комментарий
  • Как быть с кэшированием файлов (css, js, svg...) при их изменении?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Веб-разработка
    ведь его браузер новые стили не прочитает
    Бразуер кеширует конкретный файл. Соответственно, для сброса кэша просто меняют путь к файлу.
    Простой вариант: добавить get-параметр, в котором будет содержаться время последнего изменения. Но этот вариант требует чтения с диска на сервере, чтобы узнать mtime (не велика беда) и работает не со всеми reverse proxy (некоторые криво настроенные могут игнорировать get-параметры).
    Поэтому уже лет десять существуют системы сборки фронтенда, которые прямо в имя файла подставляю хэш от его содержимого. Сейчас это есть для абсолютно любой системы - gulp, webpack, что угодно.
    Называется это Cache Busting, вот вам первая попавшаяся статья: https://www.keycdn.com/support/what-is-cache-busting
    А ещё, кэш - это не только "не запрашивай файл 365 дней", там много различных функций: https://jakearchibald.com/2016/caching-best-practices/

    при их изменении на стороне клиента
    Такая формулировка подразумевает, что это клиент что-то меняет. Я уж обрадовался: "о, какой интересный вопрос, есть над чем подумать!"...
    Ответ написан
    2 комментария