• Можно ли найти работу Linux-админом с небольшим опытом?

    Robur
    @Robur
    Знаю больше чем это необходимо
    Можно ли найти работу Linux-админом с небольшим опытом?


    Кому-то можно. Кому-то нет. В каких-то условиях можно. В других нет.
    Лично для вас - есть только один способ выяснить. Вы его конечно же уже знаете.

    А на тостер вы пришли за моральной поддержкой. Хоть это и вне тематики ресурса, но давайте я вас поддержу:

    Дерзай мужик! ты сможешь! ничего не бойся!

    Все, удачи.
    Ответ написан
    Комментировать
  • Как восстановить математическое мышление?

    @CHolfield
    Есть только одна рабочая методика.
    Мысль на физическом уровне есть результат прохождения электрических сигналов между нейронами по цепочкам. Чтобы сигнал перешел от одного нейрона к другому, в промежуток между ними (синапс) выделяется определенное количество нейромедиатора (серотонин и пр). Если сигналы раз за разом идут одними и теми же путями (при однородной умственной нагрузке), то необходимое для обеспечения проводимости количество нейромедиатора уменьшается, нарабатываются устойчивые связи. В конце концов однотипные задачи решаются в фоновом режиме. Если вы водите авто, обратите внимание, насколько часто взгляд перемещается по зеркалам, приборам, просто оцените объем информации, которая обрабатывается отдельным потоком и позволяет разговаривать с пассажиром при маневрировании. Решай задачи и все.
    Ответ написан
    4 комментария
  • Как сделать правильный выбор между C# и Java?

    Sputterspark
    @Sputterspark
    В далеком прошлом, я занимался пустой тратой времени. А именно - выбором языков программирования.

    И продолжаешь этим заниматься.
    Ответ написан
    Комментировать
  • Существует ли лаконичное описание математики?

    myjcom
    @myjcom
    Математика за 30 секунд
    Год: 2014
    Автор: под ред. Ричарда Брауна
    Переводчик: Карнаушко И.
    Издательство: Рипол Классик
    ISBN: 978-5-386-07012-0
    Серия: Узнать за 30 секунд
    Язык: Русский

    Математика. 50 идей, о которых нужно знать
    Год издания: 2014
    Автор: Крилли Т.
    Переводчик: Ш. Мартынова (с англ.)
    Издательство: Фантом Пресс
    ISBN: 978-5-86471-670-0
    Язык: Русский

    Магия математики: Как найти x и зачем это нужно
    Год издания: 2016
    Автор: Бенджамин А.
    Переводчик: Д. Глебов
    Издательство: Альпина Диджитал
    ISBN: 978-5-9614-4466-7
    Язык: Русский

    Удовольствие от x
    Год: 2014
    Автор: Строгац С.
    Издательство: Манн, Иванов и Фербер
    ISBN: 978-500057-008-1
    Язык: Русский

    Математика без формул
    Год выпуска: 1995
    Автор: Пухначев Ю., Попов Ю.

    Беседы о математике. Книга 1. Дискретные объекты
    Год выпуска: 2002
    Автор: Болтянский В.Г., Савин А.П.
    Жанр: Математика
    Издательство: МЦНМО
    ISBN: 5-94057-040-2
    Язык: Русский

    Мало ли...
    Логарифмическая линейка
    Год издания: 1958
    Автор: Кущенко В.С.
    Жанр или тематика: Математика
    Издательство: Судпромгиз
    Язык: Русский

    Счётная линейка
    Год выпуска: 1967
    Автор: Румшиский Лев Зимонович
    Издательство: "Наука"
    УДК: 681.143:518.5
    Язык: Русский
    Ответ написан
    Комментировать
  • Знания, которые не устаревают. С чего начать?

    Stalker_RED
    @Stalker_RED
    Прям совсем с нуля, или вы за эти 12 лет какие-то успешные шаги сделали?

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

    Самое важное: начните писать код прямо сейчас. Пусть это будет простенький hello world, или тупые и неэффективные решения задачки про 99 бутылок, пусть хоть самый ужасный говнокод, но это бесконечно лучше, чем вообще никакого.

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

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

    Пусть это будет как "фоновое" чтение, может даже получится читать эти книги для развлечения. Никаких мгновенных преимуществ в программировании они не дадут, но однажды вы можете заметить, что понимаете ПОЧЕМУ одни алгоритмы работают быстрее других.

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

    Потом можно переключиться на codewars, делать по одной задачке в день, например. Сравнивать свое решение с решениями других людей.

    Вот вам еще один список: Карта развития веб-разработчика
    Здесь уже не только неустаревающие знания, но неплохо бы потратить на каждую из этих тем хоть по 10 минут, чтоб понимать о чем речь. Конечно, для нормальной работы на многие из этих тем придется потратит намного больше времени.
    Ответ написан
    2 комментария
  • Как запустить 10000 классов в java?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Прежде всего нужно заметить, что запустить класс нельзя, его можно только объявить, а запускать можно методы экземпляров этого класса. Почему я и подумал, что вопрос неправильно сформулирован.

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

    Генерировать можно как java-код, так и байткод. Первый способ использует популярная библиотека Lombok. Для него понадобиться механизм работы с AST и механизм взаимодействия с компилятором. Oracle JDK и Open JDK предоставляют Compiler API, реализующий оба механизма. Кроме того, есть и другие инструменты для работы с AST, например Eclipse JDT. Я покажу применение пакета com.sun.tools.javac из Compiler API.
    Сноска
    До Java 9 пакет com.sun.tools.javac был упакован в tools.jar, поставляемый вместе с JDK. Начиная с 9-ки API компилятора вынесли в модуль jdk.compiler, не экспортирующие свои пакеты. Теперь можно не указывать путь до tools.jar в classpath, но нужно добавлять экспорты. В остальном ничего не изменилось.
    import java.lang.reflect.Method;
    import java.net.URI;
    import java.util.ArrayList;
     
    import javax.tools.JavaCompiler;
    import javax.tools.JavaCompiler.CompilationTask;
    import javax.tools.JavaFileObject;
    import javax.tools.SimpleJavaFileObject;
    import javax.tools.ToolProvider;
    
    import com.sun.tools.javac.code.Flags;
    import com.sun.tools.javac.code.Type;
    import com.sun.tools.javac.file.JavacFileManager;
    import com.sun.tools.javac.model.JavacElements;
    import com.sun.tools.javac.processing.JavacProcessingEnvironment;
    import com.sun.tools.javac.tree.JCTree;
    import com.sun.tools.javac.tree.TreeMaker;
    import com.sun.tools.javac.util.Context;
    import com.sun.tools.javac.util.List;
    import com.sun.tools.javac.util.Name;
    
    
    /**
     * Класс эмулирующий для компилятора файлы исходного кода
     * и позволяющий компилировать код прямо из памяти
     */
    class JavaSourceFromString extends SimpleJavaFileObject {
        private final String code;
    
        public JavaSourceFromString(String name, String code) {
            super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
            this.code = code;
        }
    
        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
            return code;
        }
    }
     
    public class CompilerDemo {
        private static final String BASE_NAME = "DynamicHello";
        private static final ClassLoader classLoader = ToolProvider.getSystemToolClassLoader();
        private static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
    
        /**
         * Метод формирующий абстрактное синтаксическое дерево
         * и преобразующий его в исходный код
         */
        private static String generateSource(String className) {
            Context ctx = new Context();
            JavacFileManager.preRegister(ctx);
            TreeMaker treeMaker = TreeMaker.instance(ctx);
            JavacElements elements = JavacElements.instance(ctx);
    
            JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);
    
            // Тело генерируемого метода
            // выводящее имя класса
            JCTree.JCBlock methodBody = treeMaker.Block(0, List.of(
                treeMaker.Exec(
                    treeMaker.Apply(
                        List.<JCTree.JCExpression>nil(),
                        treeMaker.Select(
                            treeMaker.Select(
                                treeMaker.Ident(
                                    elements.getName("System")
                                ),
                                elements.getName("out")
                            ),
                            elements.getName("println")
                        ),
                        List.<JCTree.JCExpression>of(
                            treeMaker.Binary(
                                JCTree.Tag.PLUS,
                                treeMaker.Literal("I am "),
                                treeMaker.Apply(
                                    List.<JCTree.JCExpression>nil(),
                                    treeMaker.Select(
                                        treeMaker.Apply(
                                            List.<JCTree.JCExpression>nil(),
                                            treeMaker.Select(
                                                treeMaker.Ident(
                                                    elements.getName("this")
                                                ),
                                                elements.getName("getClass")
                                            ),
                                            List.<JCTree.JCExpression>nil()
                                        ),
                                        elements.getName("getName")
                                    ),
                                    List.<JCTree.JCExpression>nil()
                                )
                            )
                        )
                    )
                )
            ));
    
            // Определение генерируемого метода
            JCTree.JCMethodDecl method = treeMaker.MethodDef(
                modifiers,
                elements.getName("introduceYourself"),
                treeMaker.Type(new Type.JCVoidType()),
                List.<JCTree.JCTypeParameter>nil(),
                List.<JCTree.JCVariableDecl>nil(),
                List.<JCTree.JCExpression>nil(),
                methodBody,
                null
            );
    
            // Определение генерируемого класса
            JCTree.JCClassDecl tree = treeMaker.ClassDef(
                modifiers,
                elements.getName(className),
                List.<JCTree.JCTypeParameter>nil(),
                null,
                List.<JCTree.JCExpression>nil(),
                List.of(method)
            );
    
            return tree.toString();
        }
    
        /**
         * Метод компилирующий исходный код
         */
        public static void compile(Iterable<? extends JavaFileObject> compilationUnits) {
            CompilationTask task = compiler.getTask(null, null, null, null, null, compilationUnits);
            task.call();    
        }
    
    
        /**
         * Метод запускающий сгенерированные классы с помощью рефлексии
         */    
        public static void loadAndRun(String className) throws ReflectiveOperationException {
            Class<?> cls = classLoader.loadClass(className);
            
            Method method = cls.getDeclaredMethod("introduceYourself");
            method.invoke(cls.newInstance());    
        }
    
        public static void main(String[] args) throws Exception {
            java.util.List<JavaFileObject> sources = new ArrayList<>();
    
            // Генерируем исходный код десятка классов
            for (int x = 0; x < 10; x++) {
                String className = BASE_NAME + x;
                sources.add(new JavaSourceFromString(className, generateSource(className)));
            }
    
            // Компилируем сгенерированный код
            compile(sources);
            
            // Запускаем скомпилированные классы
            for (int x = 0; x < 10; x++) {
                loadAndRun(BASE_NAME + x);
            }
        }
    }

    Конечно, можно было не заморачиваться с AST, просто засунуть код в строковый литерал, подставлять в этот литерал разные имена и подсовывать компилятору. Но это не так интересно!

    Продолжение в первом комментарии, а то я в лимит символов не укладываюсь.
    Ответ написан
    3 комментария
  • Как защититься от парсельщиков?

    zoonman
    @zoonman
    ⋆⋆⋆⋆⋆
    Существует несколько способов борьбы.

    Вектор усложнения доступа к информации

    Информация отдается с сервера с постоянной меняющейся структурой. Например блоки меняются местами и CSS генерируется налету, причем классы собираются рандомной цепочкой и имеют абсолютно рандомные названия. Это может повлиять на SEO.
    Если этого мало, то контент рендерится с помощью JS аналогичными алгоритмами. Сам JS тоже генерируется и обфусцируется. Доставка контента происходит через сложные технологии, например через WebRTC DataChannel или WebSockets. Про SEO не может быть и речи, плохо работает через мобильник.
    С подобным подходом прийдется писать парсер под ваш сайт. Скорее всего он будет делать скриншот и скармливать его распознавалке.

    Вектор контроля доступа к информации

    Доступ к информации предоставляется определенному кругу лиц. Например клиентам. Объемы доступа регламентированы и превышение карается расторжением договора или штрафом.

    Вектор ограничения доступа к информации с помощью каптчи

    Для идентификации клиентов используются evercookie+fingerprinting. Используется рейтинг адресов и подсетей.
    Для недоверенных подсетей (ip принадлежат в основном разного рода хостинг-провайдерам) captcha отображается сразу. Аналогично при появлении трафика из необычного места, например внезапный трафик из Индии или Китая.

    Вектор "медленный сервер"

    Анализируются поведенческие характеристики с помощью машинного обучения. Строится эталонная модель.
    Все, кто не попадает под модель, упираются в медленный сервер. Сайт начинает отдавать контент сразу, но очень медленно, например страница может открываться секунд 30. Причем попытка параллельного запроса приводит к ошибке. Если сайт велик, то подобные штуки останавливают парсильщиков на ура. Вдобавок дополнительно контролируются определенные вещи, вроде "пользователь загрузил js и css", провел мышкой там и там.

    Вектор для реального отваживания воришек

    Кроме выше перечисленных способов, есть очень простые, но действенные способы. При обнаружении парсинга, парсильщику отдается неверная/искаженная определенным образом информация. Например, если есть подозрение на конкурента ворующего цены, можно отдать цены чуть выше настоящих и немного подменить название товара, например заменить определенным образом букву "а" на "a". Затем такая штука ищется поисковиком и находится сайт конкурента.
    Далее вопрос решается так, как это удобно бизнесу. Обычно жалуются на нарушение копирайта. Ну или у конкурента внезапно сгорает склад. Тут уж кто на что горазд.

    А это специально для любителей парсить чужие сайты: cломанные пальцы очень сильно мешают набирать на клавиатуре будьте осторожны, в большинстве случаев воровство контента того не стоит.

    Подытожим. В большинстве случаев защита от парсинга вредит SEO.
    Если у вас воруют контент, значит он хороший. Защищайте его с умом. Простые средства вроде копирайта и успешные дела за воровство контента отвадят воришек от вашего сайта. Просто придайте делам огласку. Отслеживайте воровство и жалуйтесь в поисковые системы.
    Используйте технические средства для отслеживания воровства, например непечатаемые символы и стеганографию в картинках.
    Используйте внутренние ссылки и привязки к контенту и его автору. Например логические отсылки на свои предыдущие работы или другие товары, которые можно купить только у вас.

    Если у вас воруют статьи, просто требуйте обратную ссылку.
    Если воруют описание товаров, предложите продать его, а на вырученные деньги улучшите свое или увеличите оборот или потратьте их на рекламу.
    Еще одна рекомендация - сделайте все, чтобы поисковики узнавали о вашем контенте раньше, чем у воришек.
    Ответ написан
    6 комментариев
  • Какой выбрать таскменеджер для одного человека?

    zamboga
    @zamboga
    Бизнес-аналитика, фин. моделирование, дашборды
    контролировать время, которое я трачу на те или иные задачи


    С описанием — те, которые опробованы мною.

    • https://Toggl.com — отдельный софт в трее, расширение под хром, приложение на андроид. Интеграция с кучей сервисов (трело, асана и т.д.). Хоткеи тоже есть. Бесплатного тарифа вполне достаточно. автотрекинг
    • https://RescueTime.com - только в автоматическом режиме логирует, в каких приложениях/сайтах проводите время, и выводит подробную статистику. Бесплатного аккаунта хвататет за глаза.
    • https://TimeDoctor.com — платный. Есть отдельный софт в трее, хоткеи. Интеграция с кучей сервисов.
    • https://pomelloapp.com — простой помидоро-трекер, интеграция с трелло. Хоткеи есть, в трее не сидит, простенький бар поверх всех окон
    • https://PomoDoneApp.com — простой помидоро-трекер, интеграция с трелло. Хоткеи есть, в трее показывает таймер с обратным отсчетом времени.
    • https://tmetric.com — простой трекер, интеграция с трелло, есть десктопное приложение, помидорок нет. Хоткеи есть, сидит в трее
    • https://www.timecamp.com — есть куча интеграций, расширение хром, приложение в трее, автотрекинг
    • https://ManicTime.com - мощный стэндалон тайм-трекер. Очень гибкий в настройках, сидит в трее, есть хоткеи, разные типы таймеров. Платный. Статья danila.org.ua/otrabotannyie-chasyi-moy-podhod
    • https://toptal.com/tracker/
    • ○ Grindstone https://www.epiforge.com/grindstone/
    • https://www.primaerp.com
    • https://tahometer.com
    • https://aTimeLogger
    • https://myhours.com
    • https://wakatime.com
    • savemytime.co

    Статьи
    Ответ написан
    1 комментарий
  • Верстка с нуля: какие основные этапы работы?

    Vlad_IT
    @Vlad_IT Куратор тега Вёрстка
    Front-end разработчик
    Использую vscode+webpack+pug+scss+бэм. Из физических инструментов, основной моник: lg ultrawide 29um69g, рядом прикручен моник от ноутбука повешенный вертикально, подключенный через универсальный скаллер.

    0) Запускаю Spotify :-)

    1) Произвожу установку всех необходимых модулей для сборки. В моем случае у меня набор конфигураций для webpack (отдельные файлы для pug, scss, static и.т.д., выбираю что нужно).

    2) Запускаю avocode, загружаю в него макет. Определяю в нем переменные (в то же время записываю их, чтобы сразу кинуть в scss файл) для цветов, размеров шрифтов и.т.д. чтобы при получении кусочков кода из него, он сразу расставлял переменные.

    3) Запускаю VS Code, открываю нужную папку.

    4) Пишу размету на Pug. Пишу с БЭМ, если встречаю повторяющийся блок, то открываю файл _mixins.pug, в который пишу миксины для повторяющихся блоков, например товаров, пунктов меню, каких-то блоков и.т.д. Pug умеет делать циклы, это ускоряет сильно.

    5) Когда HTML готов, начинаю делать каркас. Если дизайн сделан по сетке, определяю контейнеры, колонки, строки в свои классы (не пишу в html тучи классов аля col-md-6, а пишу в SCSS инклуды в нужные мне блоки, типа @include make-col(2) и.т.д.).

    6) Экспортирую картинки из Avocode. Очень делается просто, указываю папку и просто кликаю экспорт и ввожу название файла и расширения. Преимущественно для иконок использую svg, если нет svg, то ищу эту иконку в интернете (дизайнеры редко рисуют иконки сами, но зато любят вставлять их не в векторе). Если иконка простая, могу сам ее в inkscape обвести, ну и если нет, то экспортирую png в размере (благо авокод это позволяет, если конечно дизайнер не вставил в исходном маленьком размере). Когда есть контакт с дизайнером, трясу его, ибо растр это плохо для иконок.

    7) Пишу стили блоков из страницы. На этом этапе можно на втором монике параллельно смотреть футураму или
    Арчера :-) Но чаще на широком монике слева браузер, справа VS Code, а на втором монике Avocode (может меняться местами с браузером). Мысленно нарезаю страницу на блоки. Для каждого блока (БЭМ) создаю отдельный scss файл (кто-то даже для элемента создает, но мне лень), из него сразу выписываю все селекторы. Иногда могу сначала выписать все селекторы со страницы (но так лучше не делать, т.к. во время работы может потребоваться изменить что-то в разметке), но чаще для одного блока выполняю этот пункт и за ним сразу выполняю пункт 8, потом для нового блока опять 7 и 8 и.т.д.

    8) Пишу css код вместе с Avocode, у него беру нужные мне параметры (а он уже подставил в них переменные), и вставляю в мой код. И параллельно сверяю со скрином макета используя вот это расширение https://chrome.google.com/webstore/detail/perfectp...

    9) Пишу адаптив. Я не могу привыкнуть к методологии mobile-first, поэтому пишу всегда сначала полную версию сайта. Я понимаю, что это чревато всякими проблемами и это типа не модно, но мне норм.

    10) Медиа-запросы пишу прямо в блоках, для каждого блока/элемента/модификатора может быть отдельный медиа-запрос. Но для начала определяю breakpoint'ы для разных экранов (чтобы их не было сотни разных), если использую Bootstrap, то беру его breakpoint'ы.

    11) Добавляю анимашки. Даже если заказчик не просил отдельно (и если не указал отдельно, что нельзя), он все равно будет доволен, а с animate.css+onscreen.js это вообще работа 10 минут. Сложные анимации обговариваю отдельно, чтобы не сделать ненужную работу.

    11) Все снова сверяю, пишу скрипты где надо. Для слайдеров в 99% случаев подходит slick (с доработками конечно, но там хорошее API), для других случаев могу написать свой.

    12) Сдаю заказчику и жду ответа сидя на тостере/пикабу.

    Это чисто мой опыт, опыт фрилансера, не знаю, как делают другие и не могу на 100% утверждать что это 100% правильный способ. Я так и не смог заставить свой конфиг webpack правильно вставлять спрайты svg.
    Надеюсь чем-то поможет мой ответ.
    Ответ написан
    7 комментариев
  • Как сделать такое приложение?

    alsolovyev
    @alsolovyev
    А в чем проблема? Как Вы пытались решить эту проблему(написать в интернете "Решите мне задача" не считается)?

    Разделите конечную цель на маленькие:
    1. Создаете/рисуете точки
    2. Добавляете обработчик движения мыши
    3. Определяете дистанцию от мышки до точки ( теорема Пифагора )
    4. Увеличиваете/уменьшаете значение радиуса точки в зависимости от положения мыши

    Все! Самое сложное это теорема Пифагора(5-6 класс).
    Остается все разбросать по методам....

    Вот "наговнокодил" пример на коленках(использовал class поэтому поддержку браузера смотрите сами): https://codepen.io/janeRivas/full/NMGBvG/ (если лагает у Вас, то удалите функцию на строке 116 и 120 или поменяйте кол. точек на строке 18 )

    Если нужно уместить все точки в какой-то фигуре(букве), то поменяйте функцию Rand, добавив в нее новые условия.

    ps если как-то по-другому надо соединить линии между собой, то у нас на каждом кадре есть координаты точек this.pos.x и this.pos.y. Ну и меняй метод lineTo как тебе надо...

    psps наверно начинать надо с простого, но если делать нормально, то я бы делал на three.js или pixi.js. Логика точно такая же, только перфоманс будет в разы лучше + сможем избежать кучу проблем с картинками и тп...
    Ответ написан
    1 комментарий
  • Чат на Java (Интерфейс клиента на JavaFX), как сделать?

    jamakasi666
    @jamakasi666 Куратор тега Java
    Просто IT'шник.
    Вот уже второй вопрос задаете и все такойже бестолковый.
    Во первых причем тут javafx вообще? Это вообще ui и никаким боком и уж темболее сложностей просто по определению быть не может ну вообще никак и никаким боком.
    Во вторых, абсолютно, подчеркиваю АБСОЛЮТНО, все что должно волновать на данный момент это архитектура. И начать НУЖНО именно с нее, сядьте, возьмите просто клочок бумаги и напишите пунктами в столбик что необходимо от чата, вот прям все что вы от него хотите, отчертите линию и справа также столбиком сгрупируйте хотелки по их смыслу, дальше уже для полученных групп справа написать псевдокод , что будет использоваться для этой фичи и какие типы данных будут ходить. Подобное я приводил уже в предудщем вашем вопросе но так и быть накидаю еще и тут пример.
    В третих, на тостер приходить надо уже с конкретной проблемой да еще и с которой нагуглить ничего не удалось, что то типа вот у меня сериализация, вот метод сериализация, вот десериализации, а вот ошибка и немогу понять почему.

    По второму пункту пример
    Хочу | Объединение схожего | Как сделать
    ----------------------------------------------------------------------------------------------------------------
    1 чат с другом | 1 | Формат (кому, откого, сообщение)
    2 история | 2 | Хранить в sql бд форматом сообщений
    3 чат со всеми | 1 | Формат (от кого, сообщение)
    4 чат со всеми но в комнате | 1 | Формат (от кого, комната, сообщение)
    5 авторизация | 3 | хранить в sql базе, передавать Форматом(логин, пароль)
    6 общение клиент сервер | | Текстовый вид, Json
    7 регистрация | 3 | хранить в sql , передавать Форматом(логин, пароль)
    n

    По результату берешь и систематизируешь уже конкретнее типа такого:
    1) Нарисовалось много разных форматов сообщений и надо их както отличать а значит сделаю класс родителя с полем int которое будет хранить тип сообщения. Проблема обмена информацией между клиентом и сервером решена полностью с обеих сторон.
    abstract class AMessage{
    int messType;
    }

    2) Необходим универсальный метод сериализации и десериализации объектов из\в json. Возьму библиотеку gson, почитав ее доки получился вот такой простой способ без колхоза. Проблема полностью решена.
    public <T> T fromJson(String json, Class<T> classOfT){
            Gson gson = new GsonBuilder().create();
            try{
                return gson.fromJson(json, classOfT);
            }catch(JsonSyntaxException jse){
                return null;
            }
        }
        public String toJson(Object obj){
            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            try{
                return gson.toJson(obj);
            }catch(JsonSyntaxException jse){
                return null;
            }
        }

    3) Надо назначить и написать классы для каждого сообщения
    Для сообщения в комнату будет так
    //от кого, комната, сообщение
    class RoomMessage extends AMessage{
    String from;
    String roomName;
    String message;
    RoomMessage(String from, String roomName, String message){
     this.messType = 10;
     this.from = from;
     this.roomName = roomName;
     this.message = message;
    }
    }

    n - такой будет класс регистрации и т.д.

    Шаг n.

    Вот только теперь начинаешь писать код. Причем при написании идешь по всем шагам и только так как описал это ранее, даже если в процессе реализации это оказалось сложно\криво\глупо\неправильно.

    Программирование на самом деле состоит процентов на 90 из вот такой волокиты с написанием на бумаге всего и вся и только из 10% реализации. Кроме того таким способом все получится сделать очень быстро, логично и понятно, будет очень легко искать ошибки в программе и дебажить ее. Кроме того еще и получишь сразу почти готовую документацию которую останется только причесать и можно будет показать другому кодеру и он сразу въедет что тут и как работает. А вот заниматься написанием кода "эмпирическим" путем всегда тупиковое дело в котором будешь буксовать на месте, постоянно забывать что тут и как а главное зачем и почему неработает.

    ps еслибы я был преподавателем, а Вы студентом, надавал бы по заднице и вообще заставил вместо такой работы при мне писать от и до всю логику програмки на бумаге а затем рассказывать зачем и почему так сделал.
    Ответ написан
    Комментировать
  • Для чего используется Java в современном вебе?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Java
    Седой и строгий
    Видимо, не очень глубоко вы погрузились. Для маленьких и средних, простых сайтов Python лучше Java, так как позволяет клепать их быстрее и проще. Здесь можно почитать объяснение этому. Но для крупных ресурсов, предъявляющих высокие требования к надёжности и низкой стоимости многолетнего сопровождения, таких как ebay.com, ничего лучше Java ещё не придумали.

    А уход android-разработчиков на Kotlin - это миф и хайп.

    Kysrj.png
    Ответ написан
    19 комментариев
  • По каким книгам изучать устройство компьютера?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Таненбаум - Архитектура компьютера
    Ответ написан
    Комментировать
  • Передача через Socket объекта?

    jamakasi666
    @jamakasi666 Куратор тега Java
    Просто IT'шник.
    1) Если хочется своего колхоза то имплементируйте в нужный класс интерфейс Serializable, на стороне передачи будет нечто
    ObjectOutputStream out ...;
    out.writeObject(object);

    на стороне приема нечто такое
    ObjectInputStream in ...;
    YouClass object = (YouClass)in.readObject();

    2) Если хочется взять готовенькое то смотри в сторону kryonet, все быстро и просто.
    3) Если все же хочется своего но не особо хочется морочиться с сериализацией то смотри protobuf.
    4) Еще можно пойти классическим путем. В классе который хотите передавать создаете конструктор с нужными полями, дальше этот класс перегоняете в json\xml\обычным массивом текста с разделителями и передаете строкой, на принимающей строке разбираете эту строку и создаете объект через конструктор. Для автоматизации можно взять к примеру Gson в котором все сведется к такому виду
    public static class Entity {
        int id;
        String name;
       //другие типы и данные, если класс то аналогичным образом описываете
    
        public Entity(int id, String name) {
            this.id = id;
            this.name = name;
        }
    }String json = gson.toJson(entity); // {"id":100,"name":"name"}
    Entity read = gson.fromJson(json, Entity.class);
    Ответ написан
    Комментировать
  • Как грамотно написать интерпретатор?

    Rsa97
    @Rsa97
    Для правильного вопроса надо знать половину ответа
    Собственно классика - Книга красного дракона
    Ответ написан
    Комментировать
  • Как правильно организовать регистрацию и авторизацию пользователей сайта (Java)?

    AlexXYZ
    @AlexXYZ
    O Keep Clear O
    В основном всё верно. Я бы немного подправил следующие моменты:
    >> Пользователь отправляет, это "что-то", полученное при регистрации и в ответ получает страницу
    Не пользователь, а клиент (пользователь сидит за компом). Но клиент - не ваша программа, а в основном браузер (curl - тоже клиент) и ваша программа максимум может иметь доступ к некоторым кукам, да и то не ко всем (как настроит куку сервер, см. cookie httponly). Сервер проверяет токен и сопоставляет контекст приложения (php/java) с параметрами пользователя (_GET/_POST/_SESSION), поэтому код backend как правило никак не может влиять на контекст пользователя, только если в нём нет ошибок на выполнение критичных операций. (Естественно, что нужно разбираться в архитектуре сервера, т.к. на уровне фильтров, а в tomcat/IIS они есть, можно сделать много чего нехорошего ещё до обработки запроса под пользователем).

    >> Что представляет из себя токен? (случайную строку, которая является по сути идентификатором? Если да - то какой она должна быть длины, нужно ли ее шифровать и где хранить на стороне клиента?
    Токен - это уникальный идентификатор сессии в формате именно строки. Можно в него вставить JSON.stringify(), но браузер всё равно будет идентифицировать его как строку. Символы ему без разницы. Выдаётся на сессию на одном клиенте. Т.е. если вы подключитесь/логинитесь разными браузерами под одним логином пользователя, то у них будут разные токены. Однако, если вы технически сможете своровать токен из одного браузера и воткнуть его в другой, то фактически будете работать под одной сессией в разных браузерах и проходить аутентификацию во втором браузере не придётся (Иногда этим можно пользоваться для тестов). Именно по этом причине токены надо зарывать по максимуму, т.е. отправлять их в заголовках и в протоколе HTTPS. Только это не касается протокола Kerberos, там аутентификация производится другим механизмом и завладевание кукой не даст результата (весьма сложный механизм, используется в корпоративных сетях, не в интернете).
    где хранить на стороне клиента - Для кук браузер сам их хранит и сам же дописывает в заголовки при выполнении запросов, так что это делается прозрачно. Поставьте fiddler, там всё видно.
    нужно ли ее шифровать - Обычно нет.

    >> Слышал про OAuth и долго и коротко живущие токены
    OAuth используется, когда вы хотите привлечь большое количество пользователей, предполагая, что у них есть аккаунты в соцсетях, т.е. этот протокол упрощает и регистрацию и аутентификацию, но сложнее в настройках, чем form-based. тут есть одна тонкость - аккаунт пользователя в вашей программе надо будет всё равно создавать и связывать его с аккаунтом профиля в соцсети (сейчас подробнее не скажу, давно занимался)
    Теперь какая связь между токеном и OAuth - Делаем выход из контекста рассуждения "на уровень выше" и вспоминаем, что OAuth - протокол аутентификации, а после аутентификации нужно (барабанная дробь ...) тадам - установить токен сессии!!! Т.е. с помощью OAuth вы только проверяете валидность пользователя, затем ваша программа выясняет с каким аккаунтом на вашем сайте он связан и устанавливает токен/куку, чтобы не проходить аутентификацию каждого запроса от пользователя аккаунтов с соцсети. Ну, представьте, что даже на CSS и IMG надо будет требовать подтверждение? (если только не настроен NGINX для отдачи статики, как вы указали выше).

    >> Если да - то какой она должна быть длины
    Посмотрите на форматы и размеры токенов, которые выдают соцсети? Да, взять этот же toster.ru, вот прям сейчас:

    719fc6c4999547af95b58b252dd5255d.png

    Токен сессии придумываете самостоятельно. Хоть sid. Формат строки токена ничем не определён. Главное, чтобы при идентификации пользователя случайно не выдать аналогичный токен другому пользователю, а то получится, что два пользователя идентифицируются сервером как один, кто первый залогинился. Так что одна из проблем сервера - обеспечить уникальность токенов сессий, а это важный раздел безопасности. Вполне можно поискать способы компрометации выдачи "нужных" токенов и тогда безопасность сайта под большой угрозой.

    >> Достаточен ли уровень безопасности OAuth или стоит искать что то другое? jwt?
    Поскольку OAuth тоже начинается с "вешалки", т.е. с form-based аутентификации в соцсети, то главное обеспечить достаточный уровень секретности - HTTPS и всё будет норм.
    Ответ написан
    Комментировать
  • Использование this c return?

    @aol-nnov
    окей гугл, что такое fluent interface?
    Ответ написан
    1 комментарий
  • Есть ли обучающие материалы по ООП?

    sanek_os9
    @sanek_os9
    Работаю с Laravel, Vue, Vuetify, AWS Amazon, Linux
    Вот вам стог сена stog.jpg
    Вот вам тюк сена 617.jpg
    Какая между ними разница? И то, и то сено.
    Но, тюк он компактный, его удобно складывать, его легко переносить, вы из него хоть домик постройте. Стог это такая...просто куча, с этой кучей не удобно работать, сыпется, раздувает ветром, переносить сложно, и домик не построишь. Кто знаком с сельской жизнью тот поймет)
    Так вот, процедурный стиль, это стог сена, ООП это тюк сена. Процедурный стиль громоздкий, имеет огромную кучу каких то функции с длинными именами, его трудно поддерживать, вообще трудно вносить какие либо изменения, и если таковы понадобится, а сайт большой, то одно и то же изменение придется одинаково менять во многих местах, если вдруг вы где то забыли внести изменение то в лучшем случае это вызовет ошибку и вы её исправите, в худшем все продолжит работать но именно в том месте не так как надо, попробуйте потом найти это место...Что дает нам ООП...много чего, краткость кода, его ясность, его легко поддерживать, там нет повторяющегося кода, если вы что то захотите изменить, это нужно будет изменить единожды и ничего у вас не сломается после этого.
    Что касается примеров, этот пример должен быть большим что бы увидеть преимущества ООП подхода, это во первых, а во вторых преимущество особенно сильно проявляется когда вы работаете над этим проектом а не когда он уже написан и работает а вы смотрите на это со стороны.
    Еще раз напомню что
    Да, кто-то скажет что это не имеет смысла, но всё же любопытно было бы сравнить.

    вы что хотите сравнить? что красивше выглядит? кстати код написанный на ООП выглядит красивее и уже именно поэтому стоит его использовать)
    Напомнить я хотел что не сравнивать его нужно, а работать с ним.
    -----------------------------
    Вот пример, который не покажет всех преимуществ, это лишь пример одного из многих преимуществ ООП. Задача такая, получить данные пользователя и вывести их на экран.
    Процедурный стиль:
    $q = $pdo->prepare("SELECT * FROM `users` WHERE `id` = ? LIMIT 1");
    $q->execute([$id_user]);
    $user = $q->fetch();
    echo 'Имя: ' . $user['name'] . '<br />';
    echo 'Фамилия: ' . $user['surname'] . '<br />';
    echo 'Город: ' . $user['city'] . '<br />';

    ООП:
    class User{
        public $id;
        public $data;
        
        public function __construct(int $id)
        {
            $this->id = $id;
            $this->data = $this->getData();
            
        }
        private function getData(): array
        {
            $q = $pdo->prepare("SELECT * FROM `users` WHERE `id` = ? LIMIT 1");
            $q->execute([$this->id]);
            return $q->fetch();
        }
        public function __get($name)
        {
            if (isset($this->data[$name])) {
                return $this->data[$name];
            }
            return;
        }
    }
    $user = new User(1);
    echo 'Имя: ' . $user->name . '<br />';
    echo 'Фамилия: ' . $user->surname . '<br />';
    echo 'Город: ' . $user->city . '<br />';

    Казалось бы в чем тут преимущество если в ООП из данного примера больше кода, а выше я говорил о его краткости) краткость возникнет со временем при увеличении нашего приложения, еще я говорил что на ООП не любоваться нужно а работать с ним, так давайте же выполним следующие, сделаем так что если какие то данные не заполнены то выводилось сообщение "(данные не заполнены)"
    Процедурный стиль:
    $q = $pdo->prepare("SELECT * FROM `users` WHERE `id` = ? LIMIT 1");
    $q->execute([$id_user]);
    $user = $q->fetch();
    echo 'Имя: ' . ($user['name'] ?? '(данные не заполнены)') . '<br />';
    echo 'Фамилия: ' . ($user['surname'] ?? '(данные не заполнены)') . '<br />';
    echo 'Город: ' . ($user['city'] ?? '(данные не заполнены)') . '<br />';

    ООП:
    class User{
        public $id;
        public $data;
        
        public function __construct(int $id)
        {
            $this->id = $id;
            $this->data = $this->getData();
            
        }
        private function getData(): array
        {
            $q = $pdo->prepare("SELECT * FROM `users` WHERE `id` = ? LIMIT 1");
            $q->execute([$this->id]);
            return $q->fetch();
        }
        public function __get($name)
        {
            if (isset($this->data[$name])) {
                return $this->data[$name];
            }
            return '(данные не заполнены)';
        }
    }
    $user = new User(1);
    echo 'Имя: ' . $user->name . '<br />';
    echo 'Фамилия: ' . $user->surname . '<br />';
    echo 'Город: ' . $user->city . '<br />';

    Вы заметили как изменился процедурный стиль? Нам пришлось изменять каждое поле, нам пришлось повторятся, и хорошо что у нас только три поля а не десятки, и хорошо что у нас то проект из одного файла а не из....многих. И еще очень хорошо что вышла PHP7, иначе пришлось городить еще кучу условий.
    Вы заметили как изменился код ООП?
    В одном месте изменился кусочек кода, было:
    return;
    Стало:
    return '(данные не заполнены)';
    Такие случаи будут появляться сплошь и рядом, поэтому выбор ООП подхода очевиден.
    Еще более наглядно покажет преимущество ООП если мы добавим редактирование анкеты, в процедурном стиле нужно будет создавать три запроса (потому что в нашем примере три поля, в настоящем проекте их может быть десятки), в ООП придется один раз немного повозится (совсем чуть-чуть) и сделать универсальное обновление данных, что в результате, именно в том месте когда где потребуется обновление получится так:
    Процедурный стиль:
    $q = $pdo->prepare("запрос");
    $q->execute([/*переменная*/])

    И так три раза (в нашем примере, а в реальном проекте больше)
    ООП:
    нужно будет всего лишь написать так (например имя изменить)
    $user->name = 'новое имя';
    Мы не просто свойство изменим, данные изменятся и в базе данных, всего лишь одной такой строкой, но как это сделать пусть будет домашним заданием, ибо уже три часа ночи и я пойду спать, всем добра)
    Ответ написан
    5 комментариев