介绍Konsist:尖端的Kotlin linter
#kotlin #spring #android #androiddev

Image description

衬里是软件开发中的重要工具,有助于在整个代码基础上执行代码标准和最佳实践。通过分析错误和不一致的代码,Linters改善了协作,代码质量和遵守编码标准,尤其是在复杂项目中。

几个衬里已经可用于Kotlin编程语言。某些衬里的规则可能重叠,例如ktlintdetekt都有一个“格式化规则集”,但是,每个林格都以不同的重点创建:

  • ktlintâ-执行Kotlin编码约定。它的rules主要集中于代码命名和代码格式(间距,括号,空块,行长等)。
  • detekt-发现各种代码的气味。它的rules主要集中于代码气味,复杂性,性能和潜在错误。

现在您可能想知道为什么我们需要另一个衬里?为什么我们需要Konsist

好吧,让我告诉你一个简短的故事

认识Kotlin开发人员Jill

Image description

吉尔一直对编码充满热情,作为Kotlin开发人员工作的机会是梦想成真。她刚刚加入了一家蓬勃发展的科技公司,渴望贡献自己的技能并向她的才华横溢的同事学习。

几天后,吉尔(Jill)被分配了她的第一个重要任务:向项目添加新的用例。兴奋在她体内冒出来。这是一个证明自己,产生有意义影响的机会。这项任务似乎很简单,但她想确保自己与代码库的既定模式保持一致。

因此,吉尔开始探索现有用例,在文件后打开文件,然后挖掘结构和逻辑。她希望找到一种一致的模式,这将指导她制作新用例。但是她发现有点不知所措 - 每种用例都不同。

我们都来到这里 - 我们加入了一个新项目,我们需要一些时间来弄清楚发生了什么。项目通常很复杂,而且这种复杂性通常是不一致,纠结和混乱的代码基础的直接结果。

在项目的生命周期中,随着缩放和成熟的成熟,并且随着开发人员的到来,集成新功能,解决错误和应用修补程序通常会损害代码一致性。

团队可以就代码库标准达成共识,但是执行它们是另一个故事。开发人员并不完美,因此在审查Pr。

时很容易错过一两件事。

某些标准很难使用现有的衬里,因此通常不会自动化许多警卫。如果没有自动防护,代码库质量会随着时间的流逝而降低。

ktlint和detekt在文件级别上工作 - 他们正在一个一个核对文件,隔离检查每个文件。

认识Konsist

Konsist是一种新的尖端衬里。 Konsist着重于捕获类似类型的代码声明中的项目特定编码标准。让我们探索一些高级用法:

  • 每个子类扩展ViewModel都必须具有“ ViewModel”后缀
  • @Repository注释的课程应位于repository软件包中
  • 演示层(由presentation软件包定义)只能从域层访问类(由domain软件包定义)
  • 每个用例构造函数都有字母顺序排序的参数
  • 每个存储库构造函数参数都有一个源自类名称的名称

Konsist提供了两种类型的警卫来保护代码库 - 宣言警卫和建筑守卫。

Konsist宣告后卫

让我们看一些实际应用。让我们回顾一些证明Konsist API的代码示例,以及如何使用它来提高Kotlin代码的质量。

考虑包含三个声明的代码段 - com.myapp.logger软件包,logLevel属性和FileLogger类:
包com.myapp.logger

internal const val logLevel = "debug"

@LoggerEntity
internal class FileLogger(val level: String) : BaseLogger {
   fun log(message: String) {

   } 
}

我们可以在上面的片段中检查一些东西。让我们从获取声明名称开始。 Konsist Linter的入口点是Konsist类。开始,请查询可用的声明(所有类型),然后简单地映射其名称:

Konsist
    .scopeFromProject() // create scope from all project files
    .declarations() // get declarations
    .map { it.name } // "com.myapp.logger", "loglevel", "FileLogger"
    ...

可以将Konsist API与已知的Kotlin Collection Processing API(上述映射功能)混合,以提供其他处理和过滤功能。

映射名称将帮助我们了解如何检索各种声明和调试现有警卫,但是要定义实际的警卫,我们还必须验证这些声明是否使用ASSERT功能符合某个标准。

在高级Konsist声明检查中包含3个步骤:

  1. 决定要检查什么 - 例如课程
  2. 查询所需的声明 -
  3. 定义执行检查的断言 - 例如,必须具有内部修饰符。

让我们从检查是否扩展Baselogger类(如上filelogger)的所有类都有一个名称结尾,withlogger:

Konsist
    .scopeFromProject()
    .classes()
    .withParentClassOf(BaseLogger::class)
    .assert { it.name.endsWith("Logger") }

我们还可以验证是否对Logger软件包中的所有类进行注释,请注释:

Konsist
    .scopeFromProject()
    .classes()
    .resideInPackage("..logger..")
    .assert { it.hasAnnotations("LoggerEntity") }

要使Konsist Guard工作我们需要在单位测试中包装在代码上方 - 我们将这种守卫称为Konstst test

@Test
fun `classes present in logger package are annotated withLoggerEntity`() {
  Konsist
      .scopeFromProject()
      .classes()
      .resideInPackage("..logger..")
      .assert { it.hasAnnotations("LoggerEntity") }
}

@Test注释是JUnit框架的一部分。

测试名称为给定的警卫提供了描述,而自我解释的Konsist API允许轻松确定特定检查的范围。

Konsist建筑卫队

上面的示例证明了声明守卫的使用。 Konsist还提供了专用的API进行依赖性验证,可以帮助您保护应用程序层。这些守卫确保给定类(属于概念层的一部分)只能使用其他软件包(另一个概念层)中定义的类。考虑以下测试,该测试可以守护着位于com.myapp软件包中的清洁架构层:

fun `clean architecture layers have correct dependencies`() {
      Konsist
          .scopeFromProduction()
          .assertArchitecture {
              // Define layers
              val domain = Layer("Domain", "com.myapp.domain..")
              val presentation = Layer("Presentation", "com.myapp.presentation..")
              val data = Layer("Data", "com.myapp.data..")

              // Define architecture assertions
              domain.dependsOnNothing()
              presentation.dependsOn(domain)
              data.dependsOn(domain)
          }
  }

当建筑层存储在包装而不是模块中时,此防护罩很有帮助。

阅读广泛的Konsist documentation并查看snippets部分以获取更多示例。

划界很高兴幸福

Konsist API使开发人员可以轻松定义自定义,简洁和表达的后卫,以检查项目代码的正确性。 Konsist可以断言代码中存在的所有声明 - 命名惯例,注释,顺序和类型的参数,软件包结构,继承,修饰符,依赖项,架构层等等。

大多数衬里都可以在提供建筑规则的开箱即用,但是,它们通常不会很好地扩展 - 编写自定义规则通常是一项复杂的任务。它通常需要学习(不是那么明显的)内部衬里扩展API,并且简单条件可能会导致详细的代码。 Konsist API反映了Konsist API在Kotlin代码中可见的声明,因此API对开发人员来说更直观。 Konsist API模拟了Kotlin代码的结构,允许其快速查询Kotlin声明,例如文件,类,接口,功能,属性等。

Konsist项目状态

Konsist库已在各种春季和Android项目上进行了广泛的测试,其中包括Gradle和Maven Build Systems。此外,Konsist具有强大的测试套件(超过1300次测试和20张独特的CI检查),以防止回归错误。
Konsist可以安全使用,因为它不是生产代码基础的一部分,而是仅用于验证代码库(类似于Junit和其他测试框架)。

Konsist API经历了多次迭代,以使其更易于使用和更通用。在此阶段,Konsist API应该允许您表达您想到的大多数代码库后卫。

Konsist项目已达到第二个里程碑(项目状态页面),并正在积极寻求社区反馈以帮助其成熟:

Image description

社区参与

Konsist项目现在处于关键阶段,社区投入对于抛光它至关重要。当前,该项目需要外部输入和现场测试,以确保已准备好广泛使用。请与Konsist一起玩,尝试一下,让我们知道什么有效,您希望看到的功能以及可以改进的功能。在此阶段,您的反馈至关重要,因为它将帮助Konsist成熟。

如果您发现这个项目很有希望,可以通过在Github上主演,发推文或撰写博客文章来表达支持。这将有助于提高对项目的认识,吸引更多贡献者并更快地成熟。

感谢您的支持! ð

概括

Konsist是一种新的灵活的林格,它允许编写自定义,特定于项目的规则以捍卫项目代码一致性。它完成了其他衬里,提供了模仿Kotlin代码声明的更熟悉的API。 Konsist符合连续的集成管道和开发工作流程。有关更多信息,请查看Konsist documentation

Twitter(X)上关注我。