Смешной баг

Written by elwood

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

b0e42e7832f67135e55aaf8e51afcb2b

Gradle и maven enforcer

Written by elwood

Те, кто плотно пользуются мавном, наверняка знают и активно используют плагин maven enforcer. Если включить проверку DependencyConvergence, то плагин будет проверять проект на отсутствие конфликтов между версиями используемых артефактов:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>enforce</id>
            <configuration>
                <rules>
                    <DependencyConvergence />
                </rules>
            </configuration>
            <goals>
                <goal>enforce</goal>
            </goals>
        </execution>
    </executions>
</plugin>

У него есть ещё проверки, но самая важная именно эта. Например, в проекте используется log4j версии 1.2, а какая-то библиотека в одной из транзитивных зависимостей ссылается на log4j 1.1, то enforcer ругнётся во время сборки. После этого программист увидит проблему и пойдёт чинить. Как правило, для решения траблы достаточно замаскировать часть транзитивных зависимостей с помощью exclude. Если же этого не сделать, а отключить enforcer, то в билд попадут обе зависимости: и log4j:1.2, и log4j:1.1, что не очень хорошо, так как то, какая версия будет реально использована, зависит лишь от порядка его нахождения в classpath.

В gradle же по умолчанию работает следующая схема. Если есть конфликт, то будет использована крайняя версия артефакта, и дублей в результирующем билде не будет. И — черт возьми — в 99% случаев это именно то, что надо ! Но душа взывает к возможности полного контроля за ситуацией. Хочется, чтобы при появлении конфликтующей зависимости программист сразу об этом узнал и на всякий случай проверил ещё раз руками. Если у вас такая же параноя — вы можете установить другой режим разрешения конфликтов (благо грейдл это позволяет):

configurations.all {
   resolutionStrategy {
      // Fail eagerly on version conflict (includes transitive dependencies)
      // e.g. multiple different versions of the same dependency (group and name are equal)
      failOnVersionConflict()
   }
}

Всё, теперь сборка будет фейлиться при появлении конфликтов. Разрешать эти конфликты вам придётся самостоятельно, опять же с помощью exclude’ов, либо пользуясь force-установкой версий артефактов (см. документацию).

Единственный минус этой схемы по сравнению с maven enforcer в том, что enforcer вываливает все конфликты сразу, а gradle будет фейлиться на каждом конфликте по одному 🙂 В общем, занятие чистить руками конфликты это минимум на полчаса ковыряний с gradle :dependencies.

А вообще, режим градла по умолчанию очень разумный, в принципе, можно ничего и не трогать, всё будет работать (почти всегда).

Пробуем .NET Core в Linux

Written by elwood

Прочитал статью про новый .NET Core. Очень впечатлило то, что можно будет создавать нативные приложуньки так, как это делается в Go. То есть командуешь тупа

dotnet build --native

и на выходе – микроскопический (ну, может, не совсем микроскопический) бинарник, не требующий толстого .NET-рантайма. И это – со всеми плюшками языка C# и развитого туллинга (хотя бы отладчик есть, в отличие от того же Go) ! В общем, я загорелся попробовать на нём собрать свою любимую поделку.

Но не срослось. На крайней команде из гайда хелло-ворлд отказался приветствовать мир:

$ dotnet run
Compiling dotnet for DNXCore,Version=v5.0

Compilation succeeded.
    0 Warning(s)
    0 Error(s)

Time elapsed 00:00:01.4364181
 

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime,
Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies.
The system cannot find the file specified.

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