• Почему inline функция не компилилируется?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему так происходит?

    Потому что стандарт С11 (9899:201x 6.7.4:7, черновик доступен тут) говорит следующее про спецификатор inline:

    Any function with internal linkage can be an inline function. For a function
    with external linkage, the following restrictions apply: If a function is declared
    with an inline function specifier, then it shall also be defined in the same translation
    unit. If all of the file scope declarations for a function in a translation unit include
    the inline function specifier without extern, then the definition in that translation
    unit is an inline definition. An inline definition does not provide an external
    definition for the function, and does not forbid an external definition in another
    translation unit. An inline definition provides an alternative to an external
    definition, which a translator may use to implement any call to the function
    in the same translation unit. It is unspecified whether a call to the function uses
    the inline definition or the external definition.

    Самое главное тут -- в середине: инлайн-реализация не предоставляет и не запрещает реализацию со внешней линковкой, и в последнем предложении: транслятор волен сам выбирать, какую реализацию функции использовать -- инлайновую или со внешней линковкой.
    Поскольку ты написал так:
    inline void some_inline_func(uint32_t num)
    {
        . . .
    }

    ты тем самым реализовал инлайн-версию этой функции, но не реализовал версию со внешней линковкой. А транслятор выбрал (вернее ты ему подсказал выбрать, опцией -O0) использовать реализацию функции со внешней линковкой, поэтому ты получил ошибку от линковщика.

    Вариантов решения этой проблемы примерно 3:
    - определить функцию следующим образом:
    extern inline void some_inline_func(uint32_t num)
    {
        . . .
    }

    Такая функция будет доступна из других единиц трансляции.

    - либо определить функцию следующим образом:
    static inline void some_inline_func(uint32_t num)
    {
        . . .
    }

    Такая функция будет доступна только для данной единицы трансляции.

    - оставить в этом исходнике всё как есть, а в каком-нибудь другом определить следующую функцию:
    void some_inline_func(uint32_t num)
    {
        . . .
    }

    Это самый дурацкий вариант, поскольку эти две реализации могут не совпадать и в зависимости от выбора транслятора ты можешь получить разное поведение.
    Ответ написан
    Комментировать
  • Как работает веб-сервер и node js в связке? Зачем нужен Nginx?

    alexey-m-ukolov
    @alexey-m-ukolov Куратор тега Веб-разработка
    Самое простое - nginx отдаёт статику. На больших объёмах делать это через Ноду неэффективно.
    Посложнее - nginx позволяет управлять ходом запроса. Например, редиректить на https.
    Ещё сложнее - можно настроить nginx, чтобы он умно балансировал запросы между несколькими бэкендами и автоматом блокировал слишком частые попытки подключения.

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

    saboteur_kiev
    @saboteur_kiev
    software engineer
    База - сама по себе, микросервис - сам по себе.
    У базы может быть свой кластер с репликацией базы по своим нодам. У микросервиса - свой кластер, со своими контейнерами. В результате и база и сервис можно горизонтально масштабировать, в зависимости от того, что работает недостаточно быстро.

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

    А непосредственно балансировщик - это вообще часть функционала кластера или сетевой подсистемы, а не непосредственно контейнера.
    Ответ написан
    Комментировать
  • Как создать поэтапный план разработки приложения?

    dmitriylanets
    @dmitriylanets
    веб-разработчик
    Если весь процесс разделить на этапы то можно выделить:
    1. Анализ и сбор требований
    2. Проектирование
    3. Разработка
    4. Тестирование и ввод в эксплуатацию

    Анализ и сбор требований
    попробуйте выделить три уровня вариантов использования твоего функционала:
    1 уровень - цели проекта, например: Продажа товаров через Интернет-магазин,...
    2 уровень - пути достижения целей: Оформление заказа, управление корзиной, Авторизация, Регистрации клиента
    3. Команды которые реализуют кейсы из пункта 2: заполнение формы заказа, подтверждение формы, добавление товара в корзину, очистка корзины, изменение товара в корзине.

    цели уровня 1 помогут сконцентрироваться на результате, предоставить клиенту ожидаемые результат
    цели уровня 2 помогут выделить Варианты использования , роли, это как правило задачи которые отражаются в ТЗ
    цели уровня 3 это задачи разработчиков которые могут отражаются в техническом ТЗ или могут формировать спринт
    Ответ написан
    Комментировать
  • Где можно отучиться на DevOps'а?

    saboteur_kiev
    @saboteur_kiev Куратор тега IT-образование
    software engineer
    DevOps это не отдельная вакансия. Это инфраструктурный инженер, который работает над задачами автоматизации сборки, настройки различных окружений и деплоймента.
    То есть это еще одно направление системных администраторов, со своим набором технологий.

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

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

    Следовательно, джуниор-девопс звучит странно.

    А значит - нужно начинать с админа, набираться опыта, потом уже подучить ci/cd инструменты и уже потом смотреть в девопс.
    Также в девопс можно прийти из разработчиков или тестировщиков (если занимался автоматизацией и настройкой тестовых окружений).
    Но в любом случае стадию джуниор нужно пройти до того, как начинаешь думать про ДевОпса.
    Ответ написан
    Комментировать
  • Где можно отучиться на DevOps'а?

    chupasaurus
    @chupasaurus
    Сею рефлекторное, злое, временное
    Сначала надо дорасти до бородатого сисадмина (цикл статей для начинающих, Яндекс выпилил вроде у себя записи лекций с КИТа, поэтому добро пожаловать на торренты), параллельно изучая цикл разработки ПО с инструментарием на всех шагах, тоже естественно на практике (тут помогут как open source проекты, так и зарабатываемые деньги, которые сгорят на лабы в облаках дабы покрутить игрушки), а в идеале ещё и поработать весломразработчиком от года и более.
    Ответ написан
    Комментировать
  • Как реализовать быстрый поиск в массиве объектов по значению свойства?

    SynCap
    @SynCap
    Делаю интернет с 1998 года
    Не сваливать все в объект, а сразу писать в IndexedDB, а необходимые для оперативной обработки данные, например выборку по городу, брать средствами работы с IndexedDB.

    Для браузеров не умеющих работать с IndexedDB есть библиотека PouchDB, менее шустрая, чем нативные встроенные в браузер реализации (UPD: если их нет, в противном случае - используются нативные), но даже на старых браузерах (IE7,8) будет выигрыш, как по удобству манипуляции данными, так и по скорости.

    UPD: обращение к IndexedDB НЕ блокирует интерфейс и может использоваться в воркерах (см. issues на странице).

    UPD: кстати, PouchDB :
    • сам использует IndexedDB, когда она доступна, в старых WebKit, в т.ч. на Android использует WebSQL, когда совсем плохо (старые IE) - тоже чего-нибудь придумывает, как минимум - localStorage;
    • дает возможность работать с серверными данными, как c локальными, когда они доступны, идеальное решение для снижения заморочек с созданием "оффлайн" приложения или одностраничника с "миллионом записей", проводя "репликацию";
    • все танцы с бубном вокруг индексов - фоновая, абсолютно прозрачная задача.
    • если поставить на сервере CouchDB или эмулировать ее Rest api - можно забирать всех "Вась из Омска" прямо с сервера одним вызовом
    UPD: И когда, наконец, народ научиться подбирать подходящий инструмент для работы, а не валить лес пилкой для ногтей и не вскапывать грядки карьерным самосвалом?
    Ответ написан
    1 комментарий
  • Верстать без фреймвороков это значит быть не професионалом?

    @RomkaChev
    Верстая на фреймворке вы рискуете написать поддерживаемый и понятный код.
    А самое главное - вы загрузите лишних 100-200kb данных - непозволительная роскошь.

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

    Верстку без фреймворка - заказчикам!

    P.S. - Заказчик, конечно, неправ.
    Ответ написан
    Комментировать
  • Как сделать валидацию данных?

    1. Подключить hibernate-validator
    2. В DAO-объектах натыкать аннотаций '@Min', '@NotNull', '@Size',...
    3. В методах контроллеров, принимающих DAO-объекты в качестве параметров, добавить аннотации '@Valid'
    Ответ написан
    1 комментарий
  • Как сделать валидацию данных?

    @Cr2ed
    Я вижу 2 способа:
    1. Подключите form validating
    2. У вас скорее всего есть класс для описания реквеста. добавте там метод validate и вызовите его в начале контроллера

    public class AuthenticateRequestBody {
    
        private String username;
    
        private String password;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(final String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(final String password) {
            this.password = password;
        }
    
        public void validate() {
            if (StringUtils.isBlank(username)) {
                throw new ValidationException("Username is absent!");
            } else if (StringUtils.isBlank(password)) {
                throw new ValidationException("Password is absent!");
            }
        }
    }


    @PostMapping("/authenticate")
        @ResponseStatus(HttpStatus.NO_CONTENT)
        void authenticate(@RequestBody final AuthenticateRequestBody request) {
            request.validate();
    
            authenticationService.authenticate(request.getUsername(), request.getPassword());
        }
    Ответ написан
    Комментировать
  • Как сделать валидацию данных?

    jaxtr
    @jaxtr
    JavaEE/Spring-разработчик
    Я на практике использую следующий подход: для каждой хранимой сущности, которую может создать/изменить пользователь, я создаю класс, описывающий форму (иногда бывает, что для редактирования и создания используются даже разные классы в виду разного набора полей).
    Это делается по двум причинам: во-первых - не все поля в хранимой сущности пользователи могут создавать/изменять (например, даты создания/редактирования и идентификаторы), во-вторых - вынесение аннотаций валидации из класса сущности.

    Теперь ближе к делу: для валидации существуют аннотации из пакета javax.validation.constraints, а также дополнительные, предоставляемые реализациями Bean Validation API (например @Email из Hibernate Validator).

    Допустим, у нас есть класс, представляющий собой форму регистрации:
    SignUpForm.java
    public class SignUpForm {
        @Email
        private String email;
    
        @Size(min = 8)
        @Pattern(regexp = "какая-нибудь регулярка для проверки надёжности пароля")
        private String password;
    }


    В контроллере мы будем принимать форму таким образом:
    SignUpController.java
    public class SignUpController {
        public ResponseEntity signUp(@RequestBody @Valid SignUpForm form, BindingResult bindingResult) {
        }
    }



    В form будут содержаться данные, отправленные пользователем, а в bindingResult - результат валидации, который можно легко проверить, вызвав bindingResult.hasErrors(). Отмечу только то, что аргумент класса BindingResult должен быть сразу после аргумента, помеченного аннотациями @RequestBody и valid, в других случаях валидация работать не будет.

    Но дальше - больше. Допустим, нам нужно добавить поле для подтверждения пароля и проверять его соответствие паролю. В таком случае нам надо добавить свою аннотацию (в данном случае на класс) и валидатор.
    Новый класс формы:
    SignUpForm.java
    @PasswordMatch
    public class SignUpForm {
        @Email
        private String email;
    
        @Size(min = 8)
        @Pattern(regexp = "какая-нибудь регулярка для проверки надёжности пароля")
        private String password;
    
        private String passwordConfirmation;
    }


    Аннотация:
    PasswordMatch.java
    @Target({TYPE, ANNOTATION_TYPE})
    @Retention(RUNTIME)
    @Constraint(validatedBy = PasswordMatchValidator.class)
    @Documented
    public @interface PasswordMatch {
    
        String message() default "{constraints.passwordmatch}";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    
        @Target({TYPE, ANNOTATION_TYPE})
        @Retention(RUNTIME)
        @Documented
        @interface List {
    
            PasswordMatch[] value();
        }
    }


    Ну и валидатор:
    PasswordMatchValidator.java
    public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, SignUpForm> {
    
        @Override
        public void initialize(PasswordMatch constraintAnnotation) {
        }
    
        @Override
        public boolean isValid(SignUpForm value, ConstraintValidatorContext context) {
                return Objects.equals(value.getPassword(), value.getPasswordConfirmation());
        }
    }


    И ещё один способ валидации - при помощи спринговых валидаторов. Допустим, нам нужно проверить существование указанного email в нашей БД, что вполне вписывается в процесс валидации. В таком случае пишем валидатор:
    SignUpFormValidator.java
    public class SignUpFormValidator implements Validator {
        public boolean supports(Class<?> type) {
            return SignUpForm.class.isAssignableFrom(type);
        }
        public void validate(Object target, Errors errors) {
            SignUpForm form = (SignUpForm) target;
            // проверяем, что нужно и добавляем ошибки в errors, если они есть
        }
    }


    Регистрируем его в контроллере:
    SignUpController.java
    public class SignupController {
        @InitBinder
        public void initBinder(WebDataBinder binder) {
            binder.addValidators(new SignUpFormValidator());
        }
    }


    После этого Spring будет производить дополнительную валидацию при помощи этого валидатора.

    Более подробно с валидацией в Spring можно почитать в официальной документации.
    Ответ написан
    Комментировать
  • Какой шаблонизатор более востребован на рынке Spring?

    @ruslanys
    Смешной вопрос. Шаблонизатор - лишь инструмент представления. Не бойтесь учить новое.

    Что касается выбора - Thymeleaf неплох, но есть нюансы.
    Например, Thymeleaf дает "рабочую" верстку, над которой дизайнер и программист могут работать параллельно, но это, пожалуй, единственный плюс.
    Из минусов, которые лично я отметил:
    1. Если на клиенте используется, например, Angular.JS, то в атрибутах тегов у вас будет несусветная каша, условно:
    <td th:text="${user.name}" ng-show="shouldShowUsername()">Username</td>

    В реальном проекте, где количество атрибутов нужно умножить на X - это оказалось трудно поддерживаемым .
    2. Учитывая тот факт, что Thymeleaf директиво-ориентированный шаблонизатор, его scope - это тег. К сожалению, не все теги одинаково хороши. А иногда их вовсе нет!
    Скажем, вы хотите отправлять plain-text сообщения по e-mail. Вам не нужна верстка и вы генерируете вовсе не HTML. В таком случае, с Thymeleaf будут проблемы, т.к. исключительно теги определяют его SCOPE. По-моему как-то костыльно эту проблему можно решить типа th:removetag, но тоже не всегда. В одном из случаев мы пытались генерировать блок стилей в head страницы и у Thymeleaf, насколько я помню, были проблемы с этим (возможно, починили).

    В любом случае, мы очень любили Thymeleaf и были его ярыми последователями, пока не столкнулись с концептуальными ограничениями завязки на директивы. Весь проект переписали на Freemarker (благо не много было генерации HTML на бекенде) - счастливы.
    Ответ написан
    Комментировать
  • Почему не работает coffee-screept?

    @Sanitar88
    Студень
    может, всё дело в грамматике (coffee-script)
    Ответ написан
    Комментировать
  • Как правильно работать с JSON в JAVA?

    EugeneP2
    @EugeneP2
    Java Dev
    gson от google, проще не бывает )
    google-gson

    Gson gson = new GsonBuilder().create();
    
    String json = gson.toJson(someObject);
    
    SomeObject newso = gson.fromJson(json, SomeObject.class);
    Ответ написан
    3 комментария
  • Хочу научиться создавать плагины JQuery - с чего начать?

    dunmaksim
    @dunmaksim
    Технический писатель
    Чтобы создавать свои плагины, Вам нужно:
    - хорошо знать JS и его подводные камни;
    - знать, что такое шаблон "модуль" и уметь писать свои модули;
    - помнить, что jQuery.fn - всего лишь псевдоним для jQuery.prototype; добавляя свою функцию к этому свойству, Вы расширяете прототип функции jQuery, и важно ничего там не сломать;
    - следовать соглашению, по которому любой плагин jQuery на выходе должен вернуть исходный или модифицированный массив переданных на вход элементов (шаблон "цепочка", есть ещё антишаблон, следующий из этого, называемый "крушение поезда")

    Собственно, вот Вам заготовка модуля:
    (function ($){
        "use strict";
        function myFunction(items){
            return $(items).each(function(){
                $(this).text("Hello, jQuery!");
            });
        }
    
        $.fn.hellojQuery = myFunction;
    }(jQuery));
    Ответ написан
    1 комментарий