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

    trevoga_su
    @trevoga_su
    Преподаватель по программированию говорит, что операторную скобку необходимо использовать только в том случае, когда внутри несколько операторов, а иначе записывать в такой форме
    скажи ему, что он теоретик.

    Когда нужно будет дописать второе условие, скобки обязательно понадобятся. Это раз.
    Второе - читабельность лучше.
    Третье - исключается возможность ошибок.

    Наличие скобок ни на что не влияет, минусов - нет. Только плюсы.
    Ответ написан
    Комментировать
  • Как разобраться с инверсией зависимостей?

    Fesor
    @Fesor
    Full-stack developer (Symfony, Angular)
    Что такое адаптер?


    Смотрите. Есть у вас например micro USB кабель. И есть дырка в новом макбуке - Usb type c. Друг в друга они, как вы понимаете, не втыкаются. И можно взять адаптер microUSB -> USB type-c.

    В этом суть адаптера. Конвертация интерфейсов. Мы сделал интерфейс штуки которая нам нужна, потом взяли готовую штуку которая вроде бы то что нам надо делает, и сделали адаптер, который закрывает нестыковки в интерфейсах.

    Таким образом если вдруг через месяц обнаружатся проблемы, вы сможете заменить "готовую штуку" на другую готовую, сделать другой адаптер, и все. Изменения с точки зрения кода, который использует нужный нам интерфейс, будут только в используемом адаптере.

    За счет этого достигается независимость.

    Что значит "принимает зависимость"?


    Предположим у нас есть метод для смены пароля юзера. Что бы это безопасно провернуть, нам надо пароль захэшировать и хранить в захэшированном виде. То есть нам нужна какая-то штука, которая будет эти пароли хэшировать. Мы о ней знать ничего не хотим, хотим что б нам ее давали:

    public function changePassword(string $password, PasswordEncoder $encoder)
    {
        $this->password = $encoder->encode($password);      
    }


    Это зависимость нашего метода. Он зависит от него. Диалог между объектами можно представить себе такой:

    - Слыш, поменяй пароль на этот
    - Оке, только хэшер паролей мне дай, мне очень надо
    - А какой тебе?
    - Да любой с этим типом
    - Ну ок. На вот пароль и хэшер. Делай дела.

    Что такое вообще эта зависимость?


    Зависимости - это все что мы используем чтобы сделать дела. Это не только библиотечки, но и просто классы, функци и т.д. Весь "сторонний" код с точки зрения нашего кода. И самое важное в том, что "нашим" кодом является тот, над которым мы работаем в данный момент времени, а не все что мы написали. Даже функции, которые есть в языке программирования из коробки являются зависимостями. Вот только от них вам не деться никуда особо, а потому с ними замарачиваться не стоит. Или если есть долговременная поддержка у библиотеки и она устаялась - тоже можно просто использовать. А вот если это поделка на гитхабе с 10-ю звездочками и там до сих пор нет ни одного релиза - но она вам вот очень нужна, возможные поломки в ней (а они рано или поздно будут) стоит "закрыть" адаптером что бы потом поменять на что-то получше или обновить без боли.
    Ответ написан
    Комментировать
  • Как правильно работать с MySQL в Java?

    Vamp
    @Vamp
    Первый вопрос: скажите пожалуйста правильно ли я построил схему работу с базой?

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

    Второй вопрос: у меня после каждого запроса в терминале висит куча Sleep соединений

    Сложно сказать в чём дело по тем данным что вы предоставили. Возможно con.close() выдал исключение и не закрыл соединение, а у вас это исключение тупо игнорируется.

    В однопоточных приложениях распространена практика открыть одно соединение и работать с ним всё время, пока приложение работает. То есть примерно так:

    package hello.world;
    
    import java.sql.*;
    
    public class Main {
    
        // один коннект на всё приложение
        private static Connection conn;
    
        // в данном случае так же можно использовать и единственный Statement
        private static Statement stmt;
    
        public static void main(String[] args) throws SQLException {
            conn = DriverManager.getConnection("jdbc:mysql://localhost/hello", "user", "password");
            stmt = conn.createStatement();
            doTheJob();
        }
    
        private static void doTheJob() throws SQLException {
    
            // здесь используется фишка Java7 под названием try-with-resources,
            // которая освобождает нас от необходимости закрывать ResultSet руками
            // он будет закрыт автоматически в конце try блока
            try ( ResultSet rs = stmt.executeQuery("SHOW TABLES") ) {
                while ( rs.next() ) {
                    System.out.println(rs.getString(1));
                }
            }
    
            // переиспользуем Statement для другого запроса - это допустимо
            try ( ResultSet rs = stmt.executeQuery("SELECT column FROM table") ) {
                while ( rs.next() ) {
                    System.out.println(rs.getString(1));
                }
            }
    
            // вариант без try-with-resources для Java6 и ниже
            ResultSet rs2 = null;
            try {
                rs2 = stmt.executeQuery("SELECT column2 FROM table2");
                // делаем что-то с rs2
            } finally {
                close(rs2);
            }
    
        }
    
        private static void close(ResultSet rs) {
            if ( rs != null ) {
                try {
                    rs.close();
                } catch ( SQLException e ) {
                    e.printStackTrace();
                }
            }
        }
    
    }


    То есть закрывать коннект к базе после каждого запроса совершенно необязательно. В некоторых случаях это даже вредно, потому что открытие нового коннекта занимает некоторое время и при большом количестве запросов этот оверхед становится заметным.

    Для многопоточных программ часто используется схожая техника, где у каждого потока есть свой объект Connection, с которым он работает (например, хранит свой экземпляр коннекта в ThreadLocal поле).

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

    Разумеется, описание в предыдущем абзаце довольно поверхностное и неполное, но обрисовывает общую для всех пулов концепцию.

    Если будете заниматься многопоточным программированием, а это маст хэв для backend (в особенности, highload), то без пула коннектов не обойтись. Хотя конечно можно и обойтись, но по мере развития проекта вы будете пилить собственную обёртку и в итоге реализуете самый простейший пул коннектов. Оно того не стоит - проще сразу взять готовый.

    Я не рекомендую сразу браться за изучение каких-либо пулов. Сначала попрактикуйтесь с голым JDBC в однопоточных приложениях. Пулы коннектов - это уже вторая ступень. К ним следует приступать только когда будете уверенно себя чувствовать в JDBC. На начальном этапе они будут только мешать.

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

    package hello.world;
    
    import com.zaxxer.hikari.HikariConfig;
    import com.zaxxer.hikari.HikariDataSource;
    
    import java.sql.*;
    import java.util.Properties;
    import java.util.concurrent.CountDownLatch;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class Main {
    
        // пул, в котором содержатся все соединения
        private static HikariDataSource dbPool;
    
        // в этом сервисе будем параллельно выполнять запросы
        private static ExecutorService executor = Executors.newFixedThreadPool(5);
    
        public static void main(String[] args) throws SQLException {
    
            // конфигурируем пул
            Properties props = new Properties();
            props.setProperty("dataSourceClassName", "com.mysql.jdbc.jdbc2.optional.MysqlDataSource");
            props.setProperty("dataSource.url", "jdbc:mysql://localhost/hello");
            props.setProperty("dataSource.user", "user");
            props.setProperty("dataSource.password", "password");
            props.setProperty("poolName", "MyFirstPool");
            props.setProperty("maximumPoolSize", "5"); // в этом пуле будет максимум 5 соединений
            props.setProperty("minimumIdle", "1"); // как минимум одно активное соединение там будет жить постоянно
            dbPool = new HikariDataSource(new HikariConfig(props));
            doTheJob();
        }
    
        private static void doTheJob() throws SQLException {
    
            // сколько запросов будем делать параллельно
            int selects = 5;
    
            // этот объект позволит нам дождаться выполнения всех запросов,
            // выполняющихся в параллельных потоках чтобы подсчитать общее время
            // выполнения всех запросов
            CountDownLatch waitLatch = new CountDownLatch(selects);
    
            long startTime = System.nanoTime();
            for ( int i = 0; i < selects; ++i ) {
                executor.submit(new ThreadPoolJob(dbPool, waitLatch));
            }
    
            try {
                // ждём когда все воркеры закончат
                waitLatch.await();
            } catch ( InterruptedException e ) {
                System.out.println("latch was broken by interruption request");
            }
            long timeElapsed = System.nanoTime() - startTime;
            System.out.println("All queries was executed in: " + (timeElapsed / 1000000000) + " sec");
    
        }
    
        // класс-воркер, который будет выполнять запрос
        private static class ThreadPoolJob implements Runnable {
    
            private final HikariDataSource dbPool;
    
            private final CountDownLatch waitLatch;
    
            ThreadPoolJob(HikariDataSource dbPool, CountDownLatch waitLatch) {
                this.dbPool = dbPool;
                this.waitLatch = waitLatch;
            }
    
            @Override
            public void run() {
                String tName = Thread.currentThread().getName();
                System.out.println(tName + ": Start query");
                try (
                    Connection conn = dbPool.getConnection();
                    Statement stmt = conn.createStatement();
                 ) {
                    // здесь мы не получаем и не работаем с ResultSet, поэтому не
                    // описываем его в try-with-resources
                    stmt.execute("SELECT SLEEP(5)");
                    System.out.println(tName + ": Query completed");
                } catch ( SQLException e ) {
                    e.printStackTrace();
                } finally {
                    waitLatch.countDown();
                }
            }
        }
    
    }
    Ответ написан
    Комментировать
  • PAINT как сделать принудительное сохранение в PNG?

    chupasaurus
    @chupasaurus
    Сею рефлекторное, злое, временное
    GNU Dia /thread
    А если конкретно, то ваши инженерЫ видимо зря носят такое название, потому что неправильное применение неправильного инструмента - очень далеко от инженерного подхода. И да, формат по умолчанию в mspaint неизменяем.
    Ответ написан
    Комментировать
  • Технический писатель или аналитик?

    По-моему, вопрос не в техническом писателе или аналитике, а в недостаточно эффективном управлении проектом.
    ...но нет этого связующего звена в компании пока...

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

    @Mercury13
    Программист на «си с крестами» и не только
    Циклы и условия — это для того, чтобы язык был полным по Тьюрингу (т.е. был — на бесконечной памяти, разумеется — эквивалентен машине Тьюринга). На языке процессора циклы и условия выглядят совсем не так (там, по сути, куча GOTO и IF GOTO), но машинный код тоже полон по Тьюрингу.

    Впрочем, есть вещи, которые поддерживаются языком именно потому, что процессор их поддерживает. Обычно хватает поддержки на уровне библиотек: атомарные операции, аппаратное шифрование… Но есть и вещи, вошедшие в собственно язык. Вот несколько штук.
    • Нуль-терминированные строки, насколько мне известно, включили в Си потому, что на том PDP это было быстро.
    • Большинство языков, деля с остатком отрицательные числа, говорят, что округление идёт к нулю (знак остатка = знаку делимого) — потому что так работает большинство процессоров.
    • Модель памяти Java говорит: нет невесть откуда взявшихся значений (другими словами, если мы считали 1234 — значит, до этого кто-то его туда записал), за исключением не-volatile long и double. На 16-битный процессор многопоточную Яву ставить бессмысленно, а 32-битный — это уже дело.

    Вызовы функций — с ними всё наоборот. Как только выяснилось, что это хорошая штука, для них сделали аппаратную поддержку. А так — для вызова функций (в удобоваримом для компилятора виде, с хорошо стандартизованными соглашениями вызова) хватает косвенной адресации и пары лишних регистров.
    Ответ написан
    Комментировать
  • Можно ли увеличить скорость вращения DC двигателя 9V?

    gbg
    @gbg Куратор тега Arduino
    Любые ответы на любые вопросы
    Какие батарейки были в машинке до того, как вы решили ее сломать? Дело в том, что крона не предназначена для отдачи большой мощности - нужны батарейки поосновательней.

    Я так думаю, что крону вы вперли потому, что от нее удобно запитывать ардуйню.
    Ответ написан
    3 комментария
  • Существует ли красивая конструкция для делегирования реализации интерфейса?

    Не совсем понятно, чего вы хотите. Вернее, чего хотите - понятно, непонятно - почему.

    Если вы хотите абсолютно все методы делегировать к инстансу IR - то почему бы вам просто не возвращать инстанс IR через интерфейс I из объекта A - зачем самому A реализовывать I?

    Если же посредничество A все-таки необходимо, то значит, что вы хотите дать этому какую-то смысловую нагрузку. Т.е. раз вам хочется, чтобы A сам реализовал I, то значит вам хочется, чтобы он скрывал факт того, что вызовы на самом деле делегируются к инстансу IR.

    Раз вы хотите, чтобы факт делегирования скрывался от клиента класса A, то вероятно, со временем, вы захотите поменять логику делегирования, и делегировать, например, не к IR, а к другой реализации интерфейса I (иначе зачем вам такое сокрытие факта делегирования к IR). А раз так, то вполне логично, что вы должны явно реализовать методы, делегирующие себя к методам IR.

    К чему я это всё? Конечно, можно себе представить, что код делегирования генерируется автоматически на основе конструкции вроде вашей (implements I by delegate), однако: а) это довольно частный случай, чтобы добавлять в язык синтаксический сахар для этого, плюс наверняка возникнет ряд вопросов реализации, на которые не будет однозначного ответа; б) я думаю такое реализуемо в языках с мощными макросами, но мне приходят в голову только те, которые вы врядли будете использовать, например Nemerle или Lisp. А, ну и на препроцессоре C++ такое можно сделать.
    Ответ написан
    2 комментария
  • Как можно фильтровать Entity без запроса в базу и без цикла?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Если нужно отфильтровать список записей, извлечённых из БД. то это можно сделать при помощи лямбд и StreamAPI. Что-то вроде:
    list.stream()
        .filter(entity -> "bar".equals(entity.getFoo()))
        .collect(Collectors.toList());


    А вообще фильтровать нужно в запросе к БД.
    Ответ написан
    Комментировать
  • Java. Как корректно организовать взаимодествие с сетью?

    leahch
    @leahch
    3Д специалист. Долго, Дорого, Дерьмово.
    Так или иначе, лучше использовать NIO, и проверять наличие данных через selector! Вот на почитать - www.javaportal.ru/java/articles/useselectfast.html... (ожидание входящих данных)
    И откажитесь вообще от sleep - это не очень красиво.
    Да, возможно, данные придется буферировать, так как они могут прийти в двух пакетах, например "BEG" и "IN"
    С файлами отдельная история - наверное поможет вот это! Механизм аналогичный - https://docs.oracle.com/javase/tutorial/essential/...
    Ответ написан
    2 комментария
  • Есть сообщение с полем типа string, могу ли я анализировать это поле?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    if(value.equals("OK"))  { ... }
    
    switch(value) {
        case "OK": ... break;
        case "Error": ... break;
    }

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

    enum Status {
        Ok,
        Error,
        Warning
    }
    
    class Foo {
        static void bar(Status status) {
            if (status == Status.Ok) {
                ... 
            }
            ...
        }
    }
    Ответ написан
    9 комментариев
  • Кто должен составлять документацию ( в компании) на программный продукт?

    eduardtibet
    @eduardtibet
    Technical Writer / Documentation Engineer
    В принципе, коллеги выше уже основную часть сказали. Добавлю от себя:
    1. Концепт системы и ТЗ - Аналитик.
    2. Планы работы и контроль их выполнения - ПМ
    3. Эксплутационная документация (руководства разного типа и вида, FAQ, HOWTO и т.п.) - технический писатель.
    4. API, SDK reference, архитектурные документы - либо технический писатель (если он высокого класса), либо разработчики.
    5. Постановка работ по документированию (типы документов, исполнители, docflow между членами команды и.т.п.) - в больших компаниях технический писатель уровня Lead. В маленьких стартапах - у кого больше опыта.
    6. Тест-планы, тест-кейсы - группы тестирования (либо лид, либо наиболее опытный)

    Для справки предыдущих участником треда: заказчики в 98% случаев НИЧЕГО не делают. Это правда жизни. Т.е. они скажут "хочу это и это", но построить из этих слов грамотную систему - см. п.1
    Ответ написан
    2 комментария
  • Что делают делегаты в C#?

    lexxpavlov
    @lexxpavlov
    Программист, преподаватель
    Вашу задачу можно сделать тремя способами:
    1) создать метод, который будет суммировать каждый элемент списка в переменную, точнее, в поле класса.
    long Result;
    long Sum(List<int> intList)
    {
        Result = 0;
        intList.ForEach(AddElement);
        return Result;
    }
    
    void AddElement(int i)
    {
        Result += i;
    }

    2) Чтобы не создавать "лишнюю" функцию, необходимую только для конкретной задачи, то можно взять анонимную функцию. Анонимные функции в C# используются с помощью делегатов. Дополнительно, анонимные функции могут использовать замыкания, и нет необходимости создавать внешнее поле.
    long Sum(List<int> intList)
    {
        long result = 0;
        intList.ForEach(delegate(int i) { result += i; });
        return result;
    }

    3) Можно взять лямбду - в данном случае, это "синтаксический сахар" - упрощение создания делегата.
    long Sum(List<int> intList)
    {
        long result = 0;
        intList.ForEach(i => result += i);
        return result;
    }
    Ответ написан
    2 комментария
  • Возможно ли декомпилировать windows приложение, написанное на C++?

    Можно. Но не бесплатно.
    IDA + Hex-Rays decompiler
    Ответ написан
    Комментировать
  • Какой есть алгоритм вывода средств с банкомата?

    dimonchik2013
    @dimonchik2013
    non progredi est regredi
    разбирайся

    в общем виде задача решения не имеет, кстати
    Ответ написан
    Комментировать
  • Как написать функцию join по любому строковому свойству?

    zagayevskiy
    @zagayevskiy Куратор тега Java
    Android developer at Yandex
    Тут проблема в том, что Predicate - это функциональный интерфейс, используемый для проверки условий. Т.е., у него один метод test(), который проверяет условие. Решение есть, оно довольно простое.
    1) Создаём свой функциональный интерфейс, который принимает объект и возвращает строку:
    interface Getter<T> {
        String getString(T from);
    }

    Формально такой функциональный интерфейс соответствует лямбде, которая принимает один аргумент типа  T. А такая лямбда, в свою очередь, соответствует ссылке на метод класса Т без аргументов.

    2) Создаём join (delimeter я опустил, добавьте его сами):
    public static <T> String join(Collection<T> collection, Getter<T> getter) {
        StringBuilder builder = new StringBuilder();
        for(T cursor: collection) {
            builder.append(getter.getString(cursor));
        }
        return builder.toString();
    }


    3) Использовать так:
    class User {
        ...
        public String getName() { ... }
    }
    List<User> users = ...;
    String joined1 = join(users, User::getName); //<-- так
    String joined2 = join(users, user -> user.getName()); //<-- или так
    Ответ написан
    3 комментария
  • Как обнаружить железный backdoor?

    SADKO
    @SADKO
    aka -=SADKO=-
    В закрытых частях тематических выставок видали мы эти "последние разработки" покрытые гос.тайной, я бы рассказал, да рассказывать особо и нечего, всё старо как мир, но теперь и с гуями с учётом UX\UI что бы было понятно даже полным дебилам, у которых есть свои, хорошо зарекомендовавшие себя методы :-)

    Любое подозрительное железо, например сетевая плата, при наличии дискретной, или любая другая плата без реальной потребности в оной, и\или наличия драйверов. В своё время были популярны "удлинители клавиатуры", сейчас наверное есть даже USB хабы, только это уже всё из другой оперы, и на хрен никому не нужно.
    Сейчас самая распространённая аппаратная закладка, набор интеловских причиндал для удалённого администрирования, но это с одной стороны лечится, а с другой обходится, но тоже лечится :-)
    Ответ написан
    8 комментариев
  • Есть ли какая - нибудь разница между процессорами x64 и x86-64, или это одно и то же, просто по разному называется?

    @evgeniy_lm
    Когда возникла необходимость появления на рынке 64 разрядных CPU мнения Intel и AMD по этому поводу кардинально разделились. Intel предложили технологию IA64 которая ни как не стыкуется со старой 32 разрядной х86 (которой 40 лет, однако). AMD вышли на рынок с технологией AMD64 которая в ущерб производительности сохранила совместимость с х86 что позволило на новых процессорах напрямую выполнять старый код. Ожидаемо, что замечательная идея от Intel не имела коммерческого успеха и весь ширпотреб Intel выпускает по стандарту AMD64, который адепты Intel стыдливо именуют х64 или х86-64
    Ответ написан
    2 комментария