Обновить
40
0

Пользователь

Отправить сообщение
Много плюсов за статью, но ни одного комментария о самом инструменте формального анализа! Ведь это отличная вещь с великолепными потенциалом — один раз описываем контракт для метода и не беспокоимся о его содержимом — всё и так будет проверяться :)
А вообще кто-нибудь пользовался подобными вещами? Я так понял, это подобие контрактного программирования. Только более мощное. В IDEA есть аннотация Contract, которая позволяет выполнить простые проверки входных и выходных данных — описываем с помощью этой аннотации контракт для метода (что будет при подаче тех или иных значений), а дальше IDE сама проверят, что метод соответствует этому контракту.
Я хоть и плюсик за статью поставил, но она практически ни о чём — что за changeset (по статье можно догадаться, что это такое, но не плохо было бы объяснить, это явно), как похожие функции реализованы в других СУБД, как у вас на проекте используется этот функционал — ничего такого нет. Только краткое описание.
Ну, собственно, вопросы: Вы на других СУБД видели похожие вещи? И как Вы используете у себя changeset на проекте? Так сказать, практическое применение.
У нас, например, для Oracle просто пишем скрипты на изменения — один файл содержит набор изменений в пределах одного коммита — потом при накате на прод эти скрипты группируются и накатываются скопом. Rollback практически не используется.
А кстати, хороший вопрос! Что вы понимаете под тестированием пользовательского интерфейса? Полную имитацию нажатия на кнопочки, галочки, выбор из списка и т.п.? Или проверку логики работы UI? Я в работе использовал и использую два подхода для тестирования UI — и полная имитация пользователя (например, с помощью того же пресловутого Selenium'а) и тестирование логики UI (MVP в этом оооочень сильно помогает). Так вот, тестирование только логики, на мой взгляд вполне оправдано — при это покрывается очень большая часть функционала. А нетестируемая часть пишется насколько простой, чтобы в ней можно было совершать минимум ошибок. Я тут даже статью написал по этому поводу habrahabr.ru/post/246285/
P.S. Вообще это мысли не мои — в офф. доках GWT пишут про MVP и Мартин Фаулер это говорил.
Ну для меня математика проста — я пользуюсь IDEA, она покрывает процентов 70 моих потребностей на работе — тут и Java, Groovy, Python, Gradle, возможность подключаться к СУБД, редактирование xml, xslt. И при всём этом она обошлась мне в этом году долларов за 60 (случайно при продлении лицензии попал на скидку в 40%). В прошлом году она для меня стоила $200. И тут JRebel, который (конкретно в моём случае) может только чуть чуть ускорить деплой изменений при разработке. Это, в процентном соотношении, не более 2% всей моей работы. И при этом есть бесплатные альтернативы. Да, не такие мощные, как jRebel, но часть его функций могут покрыть. И при этом стоит он $365, а это в 6 раз дороже моего основного инструмента для работы. В общем, для меня нет ни малейшего повода его покупать.
P.S. Спасибо за коммент.
Отличная статья, интересно было почитать!
Для разработки я использовал DCEVM (вот статья habrahabr.ru/post/236075/ ) Для прода не подойдёт, т.к. там JVM подменяется, но для локального использования самое то — бесплатен и хорошо работает.
Про jRebel согласен — стоит очень дорого. Я даже не представлю такого use-case для себя, чтобы он окупился.
P.S. Спасибо за выкладывание classloader'а на GitHub!
Кстати, вопрос немного в сторону — я только что узнал про type annotations, которые упоминались в статье ( docs.oracle.com/javase/tutorial/java/annotations/type_annotations.html ) Судя по докам, эти аннотации позволяют проще писать nullable анализ. Правильно? Ну, в смысле, одно из возможностей их использования.
И вообще, кто нибудь работал с ними?
У нас тоже аннотации используются — отличная вещь, позволила найти/не допустить несколько ошибок. Плюс это такой зачаток программирования по контракту — когда определяешь метод сразу же аннотируешь возвращаемое значение и входные параметры. И потом проще его писать — не думаешь о том — будет тут null или нет, т.к. всё указано аннотациями плюс IDE проверяет. Ну и использовать этот метод проще — всё помечено аннотациями. Даже бывало укажешь аннотации для метода, а потом смотришь его использование, а там IDE показывает не нужный код — фактически метод возвращает не null, а в местах использования метода проверялось на null и этот код можно сразу удалить :)

Ещё пару замечаний по этим аннотациям и IDEA — у нас на разных проектах разные аннотации использовались в качестве NotNull И Nullable и получается, как только импортируешь проект, нужно не забыть указать эти аннотации в IDEA в качестве аннотаций NotNull и Nullable. Что хоть и не долго но не приятно и иногда забываешь. В общем, для проекта с gradle я сделал такую штуку:

/*
Установить настройки проекта для IDEA. Используется отдельная задача, т.к. задача idea в gradle не поддерживает настройки
проекта, который оформлен в виде директорий (так с 14 IDEA работает). Поэтому нужно править xml файл настроек проекта
отдельно. 
 */
task setupProject << {
    //xml файл настроек IDEA
    File miscXmlFile = new File("./.idea/misc.xml")
    // Если файла нет, то выходим. Нужно, чтобы не было ошибок в Jenkins, когда не создаются IDEA конфигурации.
    if (!miscXmlFile.exists()) {
        return;
    }
    XmlParser xmlParser = new XmlParser()
    Node miscXml = xmlParser.parse(miscXmlFile)
    // Указываем настройки NotNull и Nullable аннотаций для проекта.
    Node nullableNotNullManagerNode = miscXml.component.find { it.@name == "NullableNotNullManager" } as Node
    if (nullableNotNullManagerNode) {
        miscXml.remove(nullableNotNullManagerNode)
    }
    miscXml.append(xmlParser.parseText('''    
        <component name="NullableNotNullManager"> 
          <option name="myDefaultNullable" value="com.my_company.npe.Nullable"/>
          <option name="myDefaultNotNull" value="com.my_company.npe.NotNull"/>
          <option name="myNullables">
            <value>
              <list size="5">
                <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable"/>
                <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable"/>
                <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable"/>
                <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable"/>
                <item index="4" class="java.lang.String" itemvalue="com.my_company.npe.Nullable"/>
              </list>
            </value>
          </option>
          <option name="myNotNulls">
            <value>
              <list size="5">
                <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull"/>
                <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull"/>
                <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull"/>
                <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull"/>
                <item index="4" class="java.lang.String" itemvalue="com.my_company.npe.NotNull"/>
              </list>
            </value>
          </option>
        </component>'''

    ))
    XmlNodePrinter nodePrinter = new XmlNodePrinter(new PrintWriter(new FileWriter(miscXmlFile)));
    nodePrinter.preserveWhitespace = true
    nodePrinter.print(miscXml)
}


Эта задача позволяет автоматически указывать свои аннотации для проекта. Можно добавить её в задачу «idea», чтобы эти аннотации автоматически конфигурировались при загрузки проекта в IDEA. Пока так не стал делать, т.к. тестировал. При выполнении задачи переоткрывать проект не нужно — IDEA сама подхватит изменения. Плюс я тут вручную xml правлю, т.к. у меня не получить на таком низком уровне работать с конфигами IDEA в gradle.
А какое конкретно приложение App ops Вы использовали? А то в Google Play по запросу App ops штук десять приложений находит с этим названием.
Да, поведение разное. Ну это аргументированно тем, что если ошибка произошла (в Java это называется исключением) то и не нужно дальше продолжать работать — типа, это не нормальное поведение, поэтому дальше код выполнять не нужно. А в Go какая философия по этому поводу? Если метод выполнился с ошибкой, то дальше можно работать? Это я почему спрашиваю — часто в try/catch происходит работа с методами, которые могу вернуть ошибки и если каждый раз проверять возвращаемое значение, то будет долго. Например операции ввода/вывода — они практически все могут вернуть ошибку.
Интересно, а как в Go будет написан код, когда подряд идут несколько операций, которые могу вернуть ошибку?
Например:
file1, err := os.Open("test1.txt")
file2, err := os.Open("test2.txt")


Нужно каждый раз проверять что err не null?
С try/catch будет всего один catch блок.
Понятно. А Вы в support IDEA писали? А то странно — в IDEA есть поддержка Vaadin, но при этом с ним не работает GWT плагин.
На счёт своей сборки GWT не понял. А что будет, если в IDEA указать GWT SDK из Vaadin?
Был на прошлой Java конференции на выступлении Вашей компании — интересно рассказывали о единой платформе — и Web (с GWT и Vaadin) и Desktop (с Swing). :)

А теперь по статье — а Вы GWT какой версии используете? До 2.7 SuperDevMode не удобный — нужно перекомпиливать весь проект при малейшем изменении, а это долго. В 2.7 появилась инкрементальные компиляция, которая кардинально меняет дело. Но до 2.7, на мой взгляд удобнее пользоваться DevMode. Или Вам не часто нужно менять GWT Client код с перекомпиляцией всего?

И IDEA у Вас какой версии? В IDEA 14 (реклама!) отличная поддержка GWT — в GWT плагине используется github.com/branflake2267/superdevmode-launcher-legacy (насколько я понял) который позволяет запускать code server вместе с web сервером (как обычный DevMode) плюс не нужно явно перекомпилировать код с помощью закладок в браузере. Далее, IDEA поддерживает source map и, если запустить, браузер с IDEA плагином (я работал в Chrome) то можно отлаживать Java код в IDE (как в DevMode). Свои ограничения там конечно же есть (по сравнению в DevMode и Java), но, на мой взгляд, работает лучше чем в браузере.

Собственно, напишу, что узнал:
Альтернативный запуск SuperDevMode
По мимо использования стандартного DevMode можно использовать реализацию DevMode с поддержкой SuperDevMode без запуска отдельно code server и servlet container’а. Скачать её можно здесь:
github.com/branflake2267/superdevmode-launcher-legacy
Благодаря этой реализации так же ненужно явно вызывать компиляцию GWT через закладки в браузере – компиляция будет происходить автоматически (вроде как, перепроверить – проверено в IDEA, но возможно это преимущество GWT плагина IDEA).

Ремарка по поводу GWT 2.7
В GWT 2.7 добавили инкрементальную компиляцию, которая включена по умолчанию и позволяет не перекомпилировать весь проект. Т.ч. в идеале «горячий» старт в SuperDevMode будет таким-же или даже меньше чем в DevMode. Нужно только прописать –noprecompile и указать –workDir и –launcherDir (чтобы использовались конкретные папки, которые не сотрутся после перезапуска сервера) чтобы повторно не компилировать код при перезапуске сервера.
«Холодный» старт остаётся таким же долгим – происходит полная GWT компиляция.

Замечания о IDEA 14
В IDEA 14 доработали поддержку SuperDevMode – запуск SuperDevMode происходит также, как и просто DevMode, без необходимости запускать отдельно code server и servlet container и не нужно использовать закладки браузера для явного запуска компиляции – компиляция будет происходить при обновлении страницы.
Для того что бы компиляция не происходила каждый раз при перезапуске приложения, нужно в настройках запускаемой конфигурации явно указать папки workDir и war в поле Dev Mode parameters. Папка workDir – любая существующая папка, папка war – папка с web приложением, в которую будут компилироваться модули GWT. Пример:
-workDir D:\project\osbb_gradle\osbb_web\code_server_work_dir -war D:\project\osbb_gradle\osbb_web\src\main\webapp
Также нужно добавить памяти VM (VM options):
-Xmx1024m

Явно указывать папки workDir и war нужно потому что по умолчанию IDEA при каждом запуске копирует содержимое webapp папки в новую временную папку и запускает приложение уже там. Из-за чего скомпилированные в прошлый раз модули не используются и компиляция происходит заново. Но если указать явно папки, то при каждом запуске будут использоваться те же самые папки с уже скомпилированными модулями.

Что бы не компилировать модули в существующую папку приложения, можно при запуске приложения копировать её в другое место и использовать уже там, но при повторном запуске не очищать её. Т.о. существующая папка с приложением останется нетронута.
Интересный способ, должен работать из-за read barrier для volatile. Но судя по stackoverflow.com/questions/10620680/why-volatile-in-java-5-doesnt-synchronize-cached-copies-of-variables-with-main не всегда работает корректно :)
А что бы не было каждый раз обращения к volatile полю в цикле, можно его присвоить не volatile полю и обращаться.
Интересные примеры, спасибо! А то много раз слышал, как правильно делать, но практические примеры не правильного использования (и нюансы) не видел :)
Использовали MyBatis на несколько больших проектов. Только хорошие впечатления.

Из того что не указал автор — возможность создание TypeHandler'ов. Простой пример — в Java есть Enum со списком значений и нужно его замапить на значения из колонки. Создаётся TypeHandler — класс, который отвечает за преобразования этого объекта из Java в СУБД и наоборот, прописывается в маппинге запроса и всё. Дальше при выполнении запроса получает типизированные объекты. Мы использовали TypeHandler'ы для структур, списка структур, Enum'ов (шаблонный TypeHandler).

Также маппинги можно прописывать в интерфейсе (не скажу что это всегда удобно, но по крайней мере есть возможность не использовать xml).

Так же для IDEA есть отличный плагин по работе с MyBatis — plugins.jetbrains.com/plugin/7293. Я пробовал разные плагины для MyBatis, но этот оказался самый лучший. Из плюсов — подсветка синтаксиса в xml, autocomlite в xml, автопроверка соответствия интерфейса xml маппингу и наоборот, связывание методов интерфейса с маппингом (можно просто перейти в реализацию метода из интерфейса в xml — как к реализации метода интерфейса в классе). Также если настроить подключение к СУБД в IDEA, работает autocomplite по SQL запросам в xml (Например, если у нас в СУБД есть таблица students то если пишем в xml маппинге SELECT * FROM st и нажимаем Ctrl+Space IDEA подскажет, что можно выбрать таблицу students)

P.S. Работали с СУБД Oracle. В основном был вызов хранимых процедур и функций. Но были и select, и update.
Ну для Arduino проблема с дебагером — не проблема — там всё равно дебажить ни как нельзя :-D
Ребята из VisualMicro сделали свой костыль для дебага, но там у них не тру дебаг.
Да, Вы знаете, Open project тоже работает :) Import делал по аналогии с IDEA — если проект не IDEA проект (т.е. не содержит в себе папку .idea) то его нужно импортировать. Тут так же поступил — это CMake проект без папки .idea и по этому его импортировал.
Уточню — я говорю про методы в CMakeLists.txt файле. Честно говоря не знаю, как они правильно называются, т.к. я больше по Java :)
Я имею ввиду, когда в CMakeLists.txt есть строчка
print_board_list()

И в другом файле есть декларация этого метода:
function(PRINT_BOARD_LIST)
    foreach(PLATFORM ${ARDUINO_PLATFORMS})
        if(${PLATFORM}_BOARDS)
            message(STATUS "${PLATFORM} Boards:")
            print_list(${PLATFORM}_BOARDS)
            message(STATUS "")
        endif()
    endforeach()
endfunction()

То нельзя по Ctrl+click или Ctrl+B перейти на декларацию метода, пишет — «Cannot find declaration to go to».
Файлы входят в проект с точки зрения CLion, они не серые, в отличие от некоторых других файлов (т.е. есть с чем сравнить).
Если этого примера не достаточно, то можно скачать проект github.com/TimReset/arduino-cmake и посмотреть самим.

Информация

В рейтинге
4 817-й
Дата рождения
Зарегистрирован
Активность