Задать вопрос
  • Какие из бекенд фреймворков наиболее "самодостаточные"?

    Vamp
    @Vamp
    Ответ написан
    Комментировать
  • ООП: Правильно ли архитектурно так делать?

    Vamp
    @Vamp
    Возможно, это нормально, так и должно быть ? или как архитектурно правильно решать подобное?

    Это нормально. Безликие массивы становятся осмысленными сущностями. Такой код становится проще понимать и поддерживать.

    Используемый вами подход называется data transfer object (DTO). Широко распространенная практика. DTO отлично сочетается с иммутабельностью, которая присутствует в ваших классах.

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

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

    Называется ORM. Находится в ответственности ORM слоя/фреймворка.
    Ответ написан
    4 комментария
  • Как настроить xdebug для докера на vps?

    Vamp
    @Vamp
    У вас сложности с тем, что xdebug является инициатором коннекта на ваш домашний ip. И если домашний провайдер выдаёт вам не белый IP, то напрямую такой коннект сделать не удастся.

    Выходом может быть проброс порта через ssh.

    ssh -R 9003:172.17.0.2:9003 user@vpsaddr
    Данная команда установит ssh соединение с логином user на ваш vps по адресу vpsaddr и откроет на этом сервере порт 9003, который сквозь ssh соединение будет прозрачно проксироваться на 9003 порт уже на вашем локальном компьютере.

    Вам нужно будет только узнать какой локальный IP адрес у вашего контейнера и подставить его вместо 172.17.0.2, который я указал для примера.

    Узнать его можно командой
    docker inspect ваш-контейнер | grep IPAddress
    Этот ip адрес нужно прописать в xdebug.client_host и в опцию -R вместо 172.17.0.2.
    Ответ написан
    8 комментариев
  • Что за фигурные скобки в Java?

    Vamp
    @Vamp
    Эта конструкция называется блоком статической инициализации. Есть ещё точно такой же блок динамической инициализации, только без ключевого слова static.

    Блоки инициализации нужны для задания начальных значений полям класса.
    class Initable2 {
        static int staticNonFinal;
    
        public static void main(String[] args) {
            System.out.println(staticNonFinal);
        }
    }

    Данный пример выведет ноль, хотя переменной staticNonFinal не присваивалось никакое значение. Java гарантирует, что любые поля класса будут проинициализированы "нулевым" значением. То есть компилятор неявно вставляет в класс блок статической инициализации, в котором переменной staticNonFinal присваивается ноль.

    class Initable2 {
        static int staticNonFinal;
    
        // Вот этот блок будет добавлен к
        // вашему классу во время компиляции.
        static {
            staticNonFinal = 0;
        }
    
        public static void main(String[] args) {
            System.out.println(staticNonFinal);
        }
    }


    Разумеется, вы можете инициализировать переменные своими значениями:
    class Initable2 {
        static int staticNonFinal = 42;
    
        static String a = "hello";
    
        static Cache<String, Integer> b = CacheBuilder.newBuilder()
            .maximumSize(100)
            .expireAfterWrite(10, TimeUnit.MINUTES)
            .build();
    }

    И тогда компилятор в блоке инициализации будет подставлять ваши значения вместо нулей:
    class Initable2 {
        static int staticNonFinal;
    
        static String a;
    
        static Cache<String, Integer> b;
    
        static {
            staticNonFinal = 42;
            a = "hello";
            b = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build();
        }
    }

    А если вашей переменной требуется какая-то сложная инициализация, которую одной строкой не представить (как в примере с Cache), то тогда вам придется написать блок инициализации явным образом вручную:
    class Initable2 {
        static int staticNonFinal = 42;
    
        static Map<Integer, String> statusCodes = new HashMap<>();
    
        static {
            statusCodes.put(200, "OK");
            statusCodes.put(404, "Not Found");
            statusCodes.put(418, "I'm a teapot");
        }
    }

    И тогда компилятор сгенерирует вам такой код:
    class Initable2 {
        static int staticNonFinal;
    
        static Map<Integer, String> statusCodes;
    
        static {
            staticNonFinal = 42;
            statusCodes = new HashMap<>()
            statusCodes.put(200, "OK");
            statusCodes.put(404, "Not Found");
            statusCodes.put(418, "I'm a teapot");
        }
    }


    Точно таким же способом инициализируются и нестатические поля при помощи блока динамической инициализации (перед таким блоком отсутствует ключевое слово static и выглядит как просто фигурные скобки в теле класса). Каждый раз при создании объекта класса сначала выполняется блок динамической инициализации, а затем конструктор. Именно в таком порядке. Блок статической инициализации выполняется один раз при загрузке класса в память.

    Блоки динамической инициализации редко используются программистами, так как проще всего сделать "инициализацию" в конструкторе (в кавычках, потому что формальная инициализация уже была выполнена перед запуском конструктора и конструктор просто переписывает уже инициализированное значение своим, поэтому более точным термином здесь будет переприсваивание). Но блоки статической инициализации используются довольно часто, так как статических конструкторов не существует.

    Вот эти все блоки инициализации были придуманы создателями языка java чтобы исключить целый класс лютых ошибок, связанных с доступом к неинициализированным переменным, характерный для языков си и си++.
    Ответ написан
    Комментировать
  • Как сделать свою mvn dependency?

    Vamp
    @Vamp
    Для этого нужно создать maven project. В pom.xml этого проекта прописать group, artifact и version. Затем собрать проект командой mvn install

    Maven скомпилирует код вашего проекта, упакует в jar и скопирует этот jar вместе с pom.xml в ваш локальный maven репозиторий.

    Далее в другом проекте подключаете свою зависимость как любую другую зависимость, указывая group, artifact и version, которые прописали ранее.
    Ответ написан
    Комментировать
  • Как мониторить работу скрипта PHP?

    Vamp
    @Vamp
    Начните с настройки директив slowlog в конфиге fpm.

    request_slowlog_timeout mixed
    The timeout for serving a single request after which a PHP backtrace will be dumped to the 'slowlog' file. A value of '0' means 'Off'. Available units: s(econds)(default), m(inutes), h(ours), or d(ays). Default value: 0.

    slowlog string
    The log file for slow requests. Default value: #INSTALL_PREFIX#/log/php-fpm.log.slow.

    Как только какой-либо скрипт работает дольше request_slowlog_timeout, снимается стек трейс данного скрипта и записывается в текстовый файл по пути, указанному в slowlog. Если тормозит какое-то конкретное место, то в стек трейсе будет видно какое. Например, если тормозит база, то в slow логе в топе стек трейса будет, например, вызов PDOStatement::execute.
    Ответ написан
    Комментировать
  • Всегда ли выполняется выполняется блок finally?

    Vamp
    @Vamp
    Автор правильно пишет. Если исключение выбросится на строке lnputFile in = new InputFile("Cleanup.java")j, то оно попадёт сразу в catch(Exception e) { System.out.println("Ошибка при конструировании InputFile"); }. Здесь finally не выполняется, так как исполнение кода не заходит в try блок, к которому прикреплён тот finally.

    Но если исключение стрельнет где-то внутри цикла while((s = in.getLine()) != null), то сработает внутренний catch блок и finally блок. Внешний catch не будет выполнен.

    А если в блоке try либо catch выполнить System.exit() ?

    В таком случае finally блок не будет выполнен, так как javadoc System.exit() чётко пишет: "This method never returns normally." А раз метод не возвращает управление, то try блок не выполняется до конца, соответственно finally не запускается.
    Ответ написан
    Комментировать
  • Когда использовать Collection, а когда Iterator?

    Vamp
    @Vamp
    В каких случаях следует идти через Collection, а в каких через Iterator? (особенно если надо просто пробежаться всем элементам).

    Зависит от объекта, по которому вы хотите просто пробежаться. Если он имплементирует интерфейс Iterable (или унаследованный от него Collection), то for(Pet p:pets) - ваш вариант.

    Через Iterator следует идти, если вы хотите пробежаться по элементам и в процессе пробежки удалить какие-то элементы из итерируемой коллекции. Сделать это безопасно можно только через Iterator.

    Решение с Iterator выглядит привлекательно при написании класса, в котором реали­зация интерфейса Collection затруднена или непрактична.

    Здесь автор имеет ввиду, если вы сами пишете класс, по которому можно "пробежаться". В этом случае проще всего сделать это через итератор, так как в нем меньше методов, которые необходимо реализовать, по сравнению с интерфейсом Collection.
    Ответ написан
    Комментировать
  • Почему так работают битовые сдвиги в Java?

    Vamp
    @Vamp
    Битовый сдвиг для типа long не может превышать 63. Поэтому сдвиг 1L << 64 будет преобразован jvm в 1L << (64 & 0x3f), в результате чего получается 1L << 0 и поэтому у вас значение не изменяется.

    Вашу задачу решает сдвиг 1L << 63. Единица изначально находится на 1 позиции (позиции нумеруются справа налево) и сдвигается влево на 63 позиции. Вы получаете желаемую единицу на 64 позиции с 63 нулями позади.

    Что касается 128L << 56, то здесь всё корректно и логично. Единица находится на 8 позции и имеет 7 нулей сзади. Сдвигая её на 56 позиций, у вас получается желаемый результат - единица на 64 позиции (8 + 56) и 63 нуля позади (7 нулей + 56).
    Ответ написан
    Комментировать
  • Каковы шансы сгенерировать одинаковые onion домены?

    Vamp
    @Vamp
    И по какому принципу они вообще генерируются(v3)?

    Генерируется ключевая пара размером 256 бит по алгоритму ed25519. Публичный ключ затем кодируется в base32 вместе с некоторыми служебными данными - номером версии (3) и контрольной суммой. Получившаяся строка и является доменом в зоне onion.

    Если делать полный перебор (а других вариантов я не вижу), то нужно сгенерировать до 2256 ключевых пар. Если взять миллиард компьютеров, которые будут одновременно и без пересечений друг с другом генерировать ключевую пару каждую наносекунду, то все пары можно перебрать примерно за 36*1041 млрд лет, что кажется мне достаточно малым шансом, учитывая, что возраст вселенной всего чуть менее 14 млрд лет.

    Надо отметить, что не все варианты из 256-битового пространства удовлетворяют ed25519. Но даже если отбросить 99% вариантов как невалидные и не тратить время на их генерацию, то перебор оставшихся 1% все равно будет невообразимо дольше возраста вселенной.
    Ответ написан
    Комментировать
  • Почему не работает dependency NametagEdit?

    Vamp
    @Vamp
    Вероятнее всего неправильно указан repository

    Попробуйте вместо
    <repository>
        <id>upstream</id>
        <url>https://ci.nametagedit.com/plugin/repository/everything/com/nametagedit/nametagedit/</url>
    </repository>


    прописать это
    <repository>
        <id>upstream</id>
        <url>https://ci.nametagedit.com/plugin/repository/everything/</url>
    </repository>
    Ответ написан
    4 комментария
  • Получения энтропии для генератора случайных чисел в PHP - как можно сделать случайность по настоящему случайной?

    Vamp
    @Vamp
    Если вам не нужна криптографическая стойкость, то заморочки с генератором истинно случайных чисел абсолютно неоправданы. ГСЧ на вихре мерсенна отлично подходит для любых задач, не связанных с криптографией.
    Ответ написан
    Комментировать
  • Имеет ли смысл размещать медиа на .onion-сайте в даркнэте, либо можно ссылаться и на лайтвеб?

    Vamp
    @Vamp
    Вы же зачем-то решили переместить основной сайт в onion? Вот те же самые причины применимы и к поддомену.

    А так, если вы оставите media в интернете, то для доступа к нему будет требоваться использование tor exit ноды, которых мало и они часто бывают перегружены. Поэтому может случиться так, что ваш сайт загрузится быстро, а вот медиа контент медленно и печально. Перенести media в tor стоит хотя бы для избавления от необходимости пересекать границу tor-интернет, тем самым ускорив загрузку.
    Ответ написан
    1 комментарий
  • Как запустить 5000 потоков параллельно с GET запросами?

    Vamp
    @Vamp
    Распараллелить выполнение в самом воркере с помощью ReactPHP или лучше GuzzleAsync. В таком случае не придется держать 5000 воркеров именно

    Вариант с GuzzleAsync - самый лучший. Под капотом он использует возможности curl_multi_exec, которые позволяют асинхронно отправлять несколько запросов, не плодя при этом лишние процессы. Не уверен конечно, что осилит 5000 параллельных запросов, но даже если и не сможет, то можно разделить 5000 между несколькими воркерами.

    2. "Правильно ли" это вообще делать с помощью PHP или это все таки задача уже других языков которые умеют в параллельное выполнение, корутины? Go, NodeJs?

    У вас нагрузка в основном IO bound, так что не имет значения какой язык выбрать. Главное чтобы он поддерживал IO multiplexing (который поддерживается в PHP через вышеупомянутый curl_multi_exec).

    3. Может уже есть готовые решения в виде библиотек на PHP? Искал, но не нашел

    Guzzle
    Ответ написан
    3 комментария
  • Как проверить хэш PHP функции crypt на Python?

    Vamp
    @Vamp
    Есть встроенная библиотека crypt

    from crypt import crypt
    
    print(crypt("hello world", "ab"))
    Ответ написан
    Комментировать
  • Java. Сокеты. Как заставить сервер постоянно слушать до нажатия кнопки?

    Vamp
    @Vamp
    Нужно тело try блока, где открывается серверный сокет, обернуть в бесконечный цикл. Чтобы сервер не завершался после обработки первого клиента.
    Ответ написан
    5 комментариев
  • Как получить последний использованный прокси в Guzzle?

    Vamp
    @Vamp
    В guzzle есть другой способ передачи заданий - через promise.
    $requests = function () use ($data, $client) {
        foreach ($data as $item) {
            yield function () use ($client, $item) {
                return $client->sendAsync($item['request'])
                    ->then(function (Response $response) use ($item) {
                        echo $item['proxy'] . ' -> ' . $response->getStatusCode() . PHP_EOL;
                    });
            };
        }
    };
    Ответ написан
    1 комментарий
  • В чем практический смысл импорта функций из стандартной библиотеки?

    Vamp
    @Vamp
    Практический смысл видится мне только один - избежание проблем в случае появления в будущем в неймспейсе Foo\Bar функции, совпадающей по имени со стандартной.

    Но вероятнее всего это просто принятый в проекте стиль написания кода.
    Ответ написан
  • Безопасен ли удаленный доступ?

    Vamp
    @Vamp
    В вашем случае небезопасно. У Cisco AnyConnect есть функция, позволяющая работодателю загрузить на ваш компьютер и выполнить с правами администратора любой бинарник.

    Две ос на двух дисках - это хороший вариант, но только при условии, что домашний диск вы будете физически отключать от компьютера каждый раз перед загрузкой в рабочую ОС.

    Вариант получше - установить рабочую ОС в виртуальную машину hyper-v или virtualbox и работать в ней.
    Ответ написан
    4 комментария
  • Можно ли сделать динамическое добавление WebAPI?

    Vamp
    @Vamp
    1. Blue-green deployment. Запускаете два инстанса своего приложения. Один из них условно называется green, другой blue. Ставите перед ними nginx/haproxy и настраиваете проксирование всех запросов на green инстанс. Когда приходит время изменений, делаете их на blue инстансе, рестартите его и перенастраиваете проксирование всего трафика с green инстанса на blue. В следующий раз делаете то же самое, но с green инстансом.

    Этот вариант не требует ни строчки изменений в коде.

    2. В бесконечном цикле с паузой в 1 сек между итерациями читаете файлы с конфигурацией из нужной папки. Затем останавливаете сервисы, для которых не нашлось определения в конфиге, запускаете сервисы, для которых определение есть и перезапускате сервисы, у которых конфиг изменился. Это уже реализовано в spring boot externalized configuration, но ничто не мешает вам реализовать это руками.
    Ответ написан
    1 комментарий