Community Over Code(北美)2023

作者: Paul King

发布时间:2023-10-26 下午 05:00


今年的北美版 ASF 会议 Community Over Code 在哈利法克斯会议中心举行了四天的现场会议(10 月 7 日至 10 日)。

注意
演示文稿幻灯片和音频/视频(如有)仍在添加到会议网站。如果提供更多资料,此帖子将更新链接到额外内容。

这篇帖子提供了会议的最新情况。它主要关注 Groovy 专题,但也有关于其他专题和会议许多其他方面的内容。特别是,希望这篇帖子能让您对参加会议,特别是 ASF 会议,为何会是一次有益的体验有所了解。我希望在未来的会议中见到您。

抵达

在进入正式的会议报告之前,对于那些从几个时区之外旅行参加会议的人来说,一个小贴士是:如果您只是通过社交媒体来了解情况,那么经常在会议上发言可能看起来是一种迷人的生活,但如果没有一点计划,您可能看到的只是飞机、酒店和会议室的内部。花一些时间去看看主办城市/国家是值得的。如果您在抵达的第一天(如果晚上抵达,则在抵达后的第一个完整天)也能晒到太阳,这似乎有助于克服时差。就我而言,我借此机会在哈利法克斯东部骑了一段自行车,大部分路程都是沿着适合骑行者的自行车道。

HalifaxRideMap

这条路线 90% 都在废弃的铁轨上修建的小径上,这些小径是 Trans Canada Trail 的一部分。它进一步细分为更小的部分,包括 Shearwater Flyer TrailSalt Marsh TrailAtlantic View TrailDartmouth Waterfront Trail。我租自行车的地方建议骑到 Lawrencetown Beach,但我又稍微往前骑了一点点,以防万一。景色非常壮观。我特别喜欢一些秋天的色彩景象,这在我居住的地方很少见到。

HalifaxRideCollage

Groovy 专题

stickers

Groovy 专题分布在会议的前两天,共有十场会议以及第一天之后的“群英荟萃”环节。会议通常有迷你主题:Groovy 更新、面向 Java 开发人员、Kubernetes 和 Groovy、Groovy 和数据科学(今年重点是 Apache Ignite)等等。在这里,我们只介绍每场讲座的一些亮点。如果您想了解更多细节,建议您仔细阅读幻灯片和其他内容。

Groovy 更新

前两场讲座涵盖了 Groovy 项目的现状以及更广泛的 Groovy 生态系统的一些更新。

Paul King 第一场讲座是 Groovy 和 Groovy 生态系统更新。这场讲座讨论了 Groovy 项目本身的状况以及更广泛的 Groovy 生态系统中的一些重要项目。

一些亮点

  • Groovy 下载量最近突破了 30 亿次,目前平均每天下载量略高于 300 万次。

  • Groovy 已经支持类和脚本,但随着 JEP 445 脚本在 Java 中即将推出(JDK21 中的预览版),Groovy 5 支持额外的形式,以便 JEP 445 代码示例可以直接在 Groovy 中运行(适用于 JDK11+)。

    def main() {
        println 'Hello world!'
    }

    有一些变体严格保持与 JEP 445 兼容(以获得相同的字节码简化),还有一些变体保留了 Groovy 的额外功能,例如访问脚本绑定和上下文。使用 `run` 方法而不是 `main` 方法来获得传统的 Groovy 脚本功能。一个额外的好处是,在类似 JEP 445 的脚本中,不需要 Groovy 的 `@Field` 注解来指定字段。这是另一个例子,这个例子使用 Jackson 数据绑定将自身序列化为 JSON 文件

    @JsonIgnoreProperties(["binding"])
    def run() {
        var mapper = new ObjectMapper()
        assert mapper.writeValueAsString(this) == '{"pets":["cat","dog"]}'
    }
    
    public pets = ['cat', 'dog']
  • Groovy 添加了对“下划线作为占位符”功能的支持。这类似于 JEP 443(JDK21 中的预览版),但 Groovy 还为闭包和多重赋值表达式添加了此功能。

    var (_, y, m, _, _, d) = Calendar.instance
    println "Today is $y-${m+1}-$d" // Today is 2023-8-23
  • 现在提供了一个额外的 `@OperatorRename` AST 转换,它使得使用 Groovy 的运算符重载更容易使用大量库。这在处理可能操作复数、矩阵或分数的库时非常方便(如下面的示例,它使用 Apache Commons Numbers Fraction 库)。以前,您可能放弃使用运算符重载快捷方式,或者您(或其他人)可能会编写一些 Groovy 特定的扩展方法,以提供特定感兴趣库的更好运算符重载语法糖。现在,这些库现在可以轻松地直接开箱即用地与运算符重载功能一起使用。

    @OperatorRename(plus='add')
    def testAddOfTwoFractions() {
        var half = Fraction.of(1, 2)
        var third = Fraction.of(1, 3)
        assert half.add(third) == Fraction.of(5, 6)  // old style still works
        assert half + third == Fraction.of(5, 6)     // fraction '+' operator!
    }
  • Grails 6 最近发布,支持 Groovy 3 的最新版本。

  • Micronaut 4 最近发布,支持 Groovy 4 的最新版本。

  • Geb 7 和 Spock 测试框架的几个版本也支持 Groovy 4。

  • Deep Netts 深度学习库的最新版本在使用 Groovy 5 和 GraalVM 时运行良好。

  • 最新版本的 Apache Ignite 与 Groovy 5 配合使用时,在扩展分布式数据、分布式计算和分布式数据科学应用程序方面效果良好。

第二场讲座是 为什么在 2023 年使用 Groovy?这讨论了使 Groovy 成为一个引人注目的语言选择的功能,即使考虑到 JDK 生态系统中其他语言正在取得的巨大进步。

一些亮点

  • 如果您需要其动态特性,例如运行时元编程、生命周期钩子和动态构建器,那么 Groovy 是一个引人注目的选择。

  • Groovy 还提供了范围、默认参数、命名参数、命令链、运算符重载、可扩展工具(包括可扩展类型检查器)等功能。

  • 除了它自己的原生特性之外,Groovy 5 为大约 150 个 Java 类提供了大约 2000 个扩展方法。

  • 特质(Traits)提供与接口中的默认方法类似的功能,但特质不仅仅解决 API 演进问题,它们是更具雄心和强大的面向对象特性。Groovy 提供有状态特质、更强大的方法选择选项、支持运行时特质应用(动态特质),并支持像 Scala 那样的可堆叠特质模式。

  • Groovy 的闭包(Closure)抽象提供了比 lambda 表达式更强大的机制,包括记忆化和尾调用递归处理。您可以以更自然的递归形式编写阶乘(避免显式命令式算法),并且不会出现栈溢出问题。您可以编写递归斐波那契算法,这些算法只需几毫秒即可执行,而不是朴素递归算法所需的数万亿年。

  • AST 转换(基于注解)和宏方法(类似但看起来像方法调用)允许声明式编程风格,其中几行代码可以替换数百或数千行等效代码。生成的代码遵循最佳实践,并且错误率大大降低。Groovy 5 有 80 多个 AST 转换。

  • 语言集成查询允许以类似 SQL 的风格查询数据。

    GQ {
        from fruit in ['Apple', 'Apricot', 'Banana', 'Cantaloupe']
        groupby fruit[0] as firstChar
        select firstChar, list(fruit.toUpperCase()) as fruit_list
    }

    其结果是

    +-----------+------------------+
    | firstChar | fruit_list       |
    +-----------+------------------+
    | A         | [APPLE, APRICOT] |
    | B         | [BANANA]         |
    | C         | [CANTALOUPE]     |
    +-----------+------------------+
  • 虽然我们喜欢 Java 最新版本中开关表达式的许多激动人心的变化,但 Groovy 仍然提供了许多额外的选项(适用于 JDK8+):Groovy switch expressions

  • Groovy 为 JDK8+ 提供模拟记录,为 JDK16+ 提供原生记录,并有许多记录增强功能:Groovy 记录 除了内置增强功能之外,Groovy 的 AST 转换也使得记录开发变得更容易。幻灯片中提供了将记录与以下 AST 转换结合使用的示例:`@PropertyOptions`、`@ToString`、`@Memoized`、`@Builder`、`@Requires`、`@Sortable`、`@Newify` 和 `@OperatorRename`。当然,您不仅限于此列表。

面向 Java 开发人员的 Groovy

接下来的两场讲座面向 Java 开发人员,旨在帮助他们了解如何将 Groovy 用于开发或测试需求。

Jeff Scott Brown

下一场讲座由 Jeff Scott Brown 主讲,主题是《面向 Java 开发者的 Groovy》。Jeff 涵盖了以下一系列主题:

  • Groovy 可选类型

  • Groovy 属性

  • Groovy 脚本语法

  • 将 Java 源码演进为 Groovy

  • Groovy 的特殊功能

  • Groovy 和 Java 类的 Groovy 扩展方法

下一场讲座是 使用 Groovy、Spock、JUnit5、Jacoco、Jqwik 和 Pitest 测试 Java。本次讲座涵盖了使用 Groovy 测试与 Java 生产代码的常见场景,尽管大部分内容也适用于其他 JVM 语言(包括 Groovy!)的生产代码。它还展示了几个您可能希望在测试工具包中考虑的高级工具的示例。

讲座的核心示例基于一个最初看起来非常简单的数学计算,最初使用以下 Java 代码实现

Buggy code

我们使用 Spock 测试框架编写了一个 Groovy 测试,乍一看,它似乎表明我们的初始实现是正确的,因为所有测试都通过了,并且我们有 100% 的测试覆盖率。

Code coverage

但这只是 100% 的行和分支覆盖率,并没有反映 100% 的状态覆盖率。我们可以通过添加一个额外的测试用例来说明这一点,现在它失败了

Add fault revealing test case

结果发现,最初的实现没有考虑到一个边缘情况,但修复起来很简单。

Corrected algorithm

现在我们所有的测试用例都通过了,并且仍然保持 100% 的覆盖率。

这个故事的寓意是,100% 的行覆盖率和分支覆盖率不足以确保正确的实现。您应该尝试添加测试用例,直到您认为问题领域得到了充分测试。讲座的其余部分探讨了两个高级工具,它们可以帮助您发现测试用例的不足之处。

Pitest 工具是一个变异测试工具。了解它的工作原理以及它如何提供帮助,最初可能会有点烧脑。Pitest 会修改您的生产代码,然后重新运行您的测试套件。如果测试套件仍然通过,即变异体存活下来,这可能表明存在代码异味。

通常这意味着您的测试套件不够完整,无法杀死变异体,您应该添加更多的测试用例。但变异测试并非一门精确的科学,如果一个变异体存活下来,可能意味着缺少测试用例,可能意味着现有测试用例存在缺陷,可能意味着实现代码中存在 bug,也可能是误报。

当我们有 3 个测试用例时,对有缺陷的实现运行该工具,确实发现了一些存活的变异,分析表明这些变异确实与有缺陷的边缘情况相对应。

Pitest result

这应该引导我们添加额外的测试用例,就像我们之前手动做的那样,这有望迫使我们发现这个错误。

在修复后的实现上运行该工具显示有所改进,但仍然存在潜在的代码异味。这一发现反映出对于我们修复后的实现,`c > Math.min(a, b)` 和 `c >= Math.min(a, b)` 是等价的,尽管在一般情况下,这可能意味着某个边缘情况没有被测试到。因此,变异测试无疑是有用的,但通常需要人工分析来排除任何误报。

另一个被审查的工具是 Jqwik,一个基于属性的测试工具。此类工具在用随机数据测试实现时,会检查某些属性是否成立。事实上,此类测试也揭示了原始代码中的缺陷,而在修复后的代码中没有发现缺陷。

Jqwik result

Kubernetes 和 Groovy

Groovy 专题的下一个迷你主题是 Kubernetes 和 Groovy。Jorge Aguilera

第一场讲座由 Jorge Aguilera 主讲:它在我的集群上运行。将 Groovy Kubernetes 应用程序部署到 Okteto。幻灯片

在本次讲座中,Jorge 展示了一个部署在云中的 Groovy Micronaut Kubernetes (k8s) 应用程序。它部署到 Okteto 平台,因此实际上大部分 k8s 细节都由平台处理。

这个示例应用程序是 Collatz 猜想的一个简单解决方案。我记得在大学时代学习过这个,但已经忘记了细节。基本上,给定一个起始数字,根据当前数字是偶数还是奇数,执行两种计算之一。奇数乘以 3 然后加 1,偶数除以 2。如果结果变为数字 1,则停止,否则继续。这个猜想是,最终计算会终止,即它总是最终等于 1。

有趣的是到达 1 所需的循环次数。这是一个返回循环次数的算法。

class Collatz {
  static long getAt(BigInteger n) {
    var result = n
    var count = 0L
    while (result != 1G) {
      if (result % 2G == 0G) {
        result /= 2G
      } else {
        result *= 3G
        result++
      }
      count++
    }
    count
  }
}

我们使用静态 `getAt` 方法为我们提供了一个简洁的速记来获取结果。我们可以测试 维基百科页面 中提到的一些示例序列。

assert Collatz[12] == 9
assert Collatz[19] == 20
assert Collatz[27] == 111

现在,围绕这个算法创建我们的微服务。我们可以通过多种方式为 Micronaut 创建一个完全工作(但只是骨架)的项目。这里,是从命令行所需的:

mn create-app \
    --features kubernetes \
    --features postgres \
    --features jdbc-data \
    --lang groovy collatz

我们已经展示了一些您可能想要使用的示例功能。您可以根据应用程序的需求添加更多功能。

我们可以更改骨架控制器以实现我们所需的功能

@Controller
  ...
  @Get('{n}')
  Map index(BigInteger n) {
    [n: n, count: Collatz[n]]
  }
...

Jorge 接着解释了 k8s 的配置细节,并演示了应用程序的部署。

Jorge 还发表了下一场演讲:让 Groovy 运行您的 k8s 集群。本次演讲深入探讨了更多 k8s 细节。他展示了如何用 Groovy 编写一个 swagger-operator,从而消除了部署 k8s 应用程序时繁琐的手动步骤。该 operator 监控我们的服务,并在需要时重写 configmap 并重新启动 pod。

操作器本身是用 Micronaut 编写的

@Operator(
    informer = @Informer(
        apiType = V1Swagger,
        apiListType = V1SwaggerList,
        apiGroup = V1SwaggerWrapper.GROUP,
        resourcePlural = V1SwaggerWrapper.PLURAL,
        resyncCheckPeriod = 10000L)
)
class SwaggerOperator implements ResourceReconciler<V1Swagger>{
}

Apache Groovy 和 Apache Ignite

下一个迷你主题是 Groovy 和数据科学。Groovy 被描述为 JVM 的 Python 等效物,Groovy 与许多 ASF 框架和技术(通常与数据科学和大数据相关)配合良好。

今年 Groovy 专题的数据科学内容特别关注使用 Apache Ignite 扩展您的数据科学应用程序,以及您的数据和计算应用程序。

第一场讲座是 使用 Apache Groovy 和 Apache Ignite 进行威士忌聚类。这是一个案例研究,探讨了如何对 86 种单一麦芽苏格兰威士忌进行聚类。

Whiskey flavour profiles

可以使用不同的算法进行聚类。这里使用了 K 均值聚类。

The k-means algorithm

对于这个特定的数据集,数据点的数量相对较少,扩展不是关键。但较大的数据集也会以相同的方式进行分割,所以我们来看看如何扩展它。首先我们读取数据

Whiskey flavour profiles

Apache Ignite 具有在集群环境中读取数据的特殊功能,但对于我们的示例,我们可以使用 Apache Commons CSV 来完成。

如果您了解 K-Means 算法,乍一看它似乎不适合分布式。要对点进行聚类,您需要计算**所有**点到质心的距离。幸运的是,该算法的各种分布式版本已经被设计出来,这就是 `ignite-ml` 库中包含的内容。我们只需像使用非分布式版本一样使用该库,Ignite 会为您完成繁重的工作。这是结果:

Whiskey flavour profiles

我们有各种选项来调整算法和可视化结果的不同方式。

Whiskey flavour profiles

顺便说一句,据说额外的关于这个主题的深入研究可能(也可能不)与会议一起进行。这无疑是因为会议在(新斯科舍)!Citadel

在这次演讲中,杰里米提出了一个问题:

如果我们利用 Groovy 的动态、易于编写和原型化的特性……
……结合 Apache Ignite 计算网格卓越的可伸缩计算能力和巧妙的对等类加载呢?

对于了解 Ignite 的人来说,它可以通过多种方式使用

Ignite

在这种情况下,它将用于分布式计算,手头的任务是解决魔方。具体来说,是一个 3x3x2 魔方不破坏性的角块移动。

Numbers

首先是创建一个小的领域模型来表示立方体

Model

然后将不同技能的计算机集群组合成计算网格。

Team

或者如果您不是《银河护卫队》的粉丝,可以选择机器的不同可视化效果。

Machines

然后编写角交换算法

Algorithm

最后得到结果

Results

我不会抢 Jeremy 的风头。请查看链接获取详细信息。但一个经验是,天真地将工作分配给能力不同的机器有时会产生令人惊讶的结果。幸运的是,有多种方法可以使计算网格作业分配考虑这些差异。

杂项

Jeff 做了另一个演讲,这次是关于《GORM 数据服务》。首先涵盖了传统的 GORM 功能,包括动态查找器、Criteria API、Where 查询和 HQL。

1

然后他介绍了 GORM 数据服务

2

Jeff Scott Brown Jeff 还为该专题做了最后一场演讲:《开源软件与你》。在这次演讲中,Jeff 分享了他自己的开源之旅。他涵盖了他在开源领域工作 30 多年的一些见解。讨论了为什么您可能想为开源做贡献,以及如何做贡献。他的旅程为所有开始或继续自己开源之旅的人提供了灵感。

Jeff 介绍了他的早期项目。他接着讨论了 Grails,这是 Groovy 早期发展中的一个关键驱动力。他还重申了 Unity Foundation 对 Grails 基金会和 Micronaut 基金会的持续投资——这两个技术是许多 Groovy 用户非常熟悉的。他还讨论了 Unity Foundation 最近的一些项目,这些项目旨在应用开源来帮助服务不足的社区。

其他专题

除了 Groovy 专题,会议还充满了其他引人入胜的内容,分为以下几个专题:

  • API/微服务专题

  • 大数据:计算专题

  • 大数据:存储专题

  • 云和运行时专题

  • 社区专题

  • 内容整理专题

  • 数据工程专题

  • 金融科技专题

  • 框架专题

  • 地理空间专题

  • 亮点专题

  • 孵化器专题

  • 物联网专题

  • 性能工程专题

  • 搜索专题

  • 与 ASF Infra 的服务器端聊天

  • 流媒体专题

  • 可持续性专题

  • Tomcat 和 httpd 专题

我确实看了不少来自其他专题的讲座,但与其尝试总结我看到的一切,不如直接将您指向会议 日程 中的在线内容。

在城堡的夜晚

会议的与会者活动是在哈利法克斯城堡国家历史遗址的夜晚。城堡是一座为保护城市而建造(并多次重建)的防御工事。它高高地矗立在俯瞰港口的山顶上,有时也是重要的通讯枢纽。

如果您在哈利法克斯,城堡是值得一游的地方。他们提供历史游览、幽灵游览、每日炮火表演以及偶尔的行军和乐队演练。我只想指出导游中提到的一个特点。在电子通信出现之前,旗杆兼具军事和商业信号的双重目的。即使在电报发明之后,旗帜仍然作为一种传统被使用,以纪念早期的时代。

商业信号桅杆曾被英军用来向公众通报港口内的海上交通情况。不同的旗帜会指示进港船只的数量和国籍(以及其他信息)。军事信号桅杆使用基于旗帜和圆盘的代码。信息可以传递到其他信号站,从而使信息能够快速远距离发送。通过信号桅杆和代码,原本可能需要半天才能通过骑马传递的信息可以在 30 分钟内完成。

Citadel

但等等,还有更多……

当然,ASF 会议远不止我所能表达的那些。这里有很棒的人,很棒的食物,大厅里的对话,还有机会与出色的 Infra 同事们聊天。我有没有说很棒的人和很棒的食物?

conference

希望在未来的 ASF 会议中见到您。

回家

旅行归来后,务必与家人朋友叙旧。就我而言,这包括在海滩度过一个周末。

Mermaid Beach

如果您访问澳大利亚,请务必过来看看。

其他信息

2023 年哈利法克斯社区代码大会其他旅行报告

另请参阅