2024 Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面获取更多有关此操作的信息。

+46
工具依赖库
被重新标记

有一个启用其他别名的别名的功能将很有用。

一个用例是有时针对单个项目进行开发,但有时针对一系列项目进行开发。

这里是一个示例

{:aliases 
  {:dev/project1 {:override-deps {:local/root "/some/path/project1"}}
   :dev/project2 {:override-deps {:local/root "/some/path/project2"}}
   :dev/project3 {:override-deps {:local/root "/some/path/project3"}}
   ;; something like the following:
   :dev/all-projects {:aliases #{:dev/project1 :dev/project2 :dev/project3}}}

6 个答案

+2

(随后在Slack上关于https://clojure.atlassian.net/browse/CLJ-2638状态的讨论中)

一开始,一个别名要求其他别名可能看起来并不是那么有用,但我相信它是组织Clojure单仓库(monorepos)的一个非常强大的简单构造。当然,对于解决Clojure单仓库的问题有很多方法,但一种直接的方法是

  • 在仓库根目录中维护一个单份deps.edn文件
  • 每个外部依赖一份别名
  • 每个内部“模块”和关注点(如:foo/main:foo/test:bar/main:bar/test等)一份别名

这样我们就有

  • 一个清晰的deps.edn文件拥有所有内容
  • 无需动态构建 deps.edn 文件,就像某些项目中看到的那样(违背了声明性工具的目的)
  • 外部依赖被锁定;例如,所有需要外部库的模块都使用同一个版本,而不是通过为该库使用专用别名来重复使用
  • 非常容易构建您需要的精确类路径;只需简单地连接别名即可
  • 不存在传递性本地依赖没有更新的情况
  • 没有使用 ../../local-lib/src 路径等不神圣的做法

这是一种非常精确的方法,效果很好。唯一的缺点是,您现在必须处理许多别名,而且并不总是明显需要哪些,哪些不需要

clj -M:module-1/dev:module-1:main:module-2/main:ext/lib-1:ext/lib-2:ext/lib-3...
当然,您可以编写脚本调用,需要无数别名,但这既复杂又容易出错。如果别名能够要求一个别名向量,那么这个问题就可以解决了。

另一个好处是,它与 CI 和 ops 合作得很好,因为它防止了在添加别名时需要更新无数脚本(即您可以在任何地方始终使用相同的“main”别名,并添加/删除它所需的别名,外部 `deps.edn` 之外看不到变化)。
我们有一个 monorepo,这绝对是一个痛点之一,直到我们在 corfield.org 上的关于这个过程的博客帖子中提出了一个更适合 deps.edn 的结构为止 —— 现在我们正在迁移到 Polylith,它只需要几个别名。话虽如此,我的个人开发环境依赖于这样的调用:

SOCKET_REPL_PORT=5000 clojure -J-Dlog4j2.configurationFile=log4j2-sean.properties -M:rebel:portal:everything:dev:test:runner:build:add-libs:dev/repl

当然,将所有这些都归为一个单一的:dev/sean 别名会很棒(而且我经常为某些任务添加几个额外的别名)。
+1

感谢 John Stevenson 指出,从多个别名继承时存在潜在冲突。因此,可能更倾向于引用别名向量而非集合。由于这个担忧,这里可能存在其他设计挑战需要解决,但我仍然认为这是一个有用的特性。

by
是的,排序确实是重要的
+1
by

我的担忧在于将继承(甚至多重继承)的复杂性引入到本应简单的配置中。多年来我从 Java 中学到的关键是要避免这些方法,并使用组合,它提供了更大的灵活性。

使用 tools.build 来解决 mono-repos 中这个问题的方法是否更简单?

在原始问题中提出的例子中,是否有机制来防止或至少警告出现:dev/project1 包含 :dev/all-projects 或其他包含别名的别名?这种分组可以深入多少层?

是否有明确优先级规则?
是否有诊断冲突的工具——也许 -Stree 够用,但我不确定

别名分组是否会限制在项目中定义的别名,还是也包括用户级别的 deps.edn(我假设排除用户级别的配置会增加更多复杂性)

或许一种避免这种情况的方法是拥有类似于 :meta-aliases 的东西,它只能包括别名,而不能包括其他 :meta-aliases,但这似乎还是在增加复杂性。

我希望能够解决 mono-repls 的特定问题,而不增加 deps.edn 配置的复杂性(特别是避免继承或甚至多重继承)。

+1
by

我认为一种可能有效的方法是类似于 Leiningen 所做的语法

{:aliases
 {:with-tests {:extra-paths ["test"]}
  :with-dev-deps {:extra-deps [...]}
  :dev [:with-test :with-dev-deps {:exec-fn some/fn}]}}

:aliases 中定义的别名可以是已经支持的正常映射,也可以是有名称的别名向量,后面可以跟一个映射。别名向量可以是包含那些别名的等价物,例如上面的示例中的 dev 别名基本等同于 with-tests:with-dev-deps:dev(使用 dev 的映射部分)

共 0 票赞成
共 0 票赞成

这对于代码审查来说非常有用。

clj -M:eastwood:kibit:antq

可能是这样的

clj -M:lint
当将所有包含 :main-opts 的别名组合在一起时,只有最后一个会被使用(因为主选项是位置性的,传递给 clojure.main 的 -main 函数),所以无法通过单行命令运行多个代码审查工具,即使有多个别名也是如此。

需要其他过程来依次运行三个代码审查工具的 -main 函数。
是的,这是一个众所周知的问题,但仍然可以通过在 :lint 别名内部提供一个手工制作的 :main-opts 来克服这个问题,将所有工具的主函数调用组合成一个。例如,根据 Cam Saul 的 Lein-alike 语法示例。这样它将是最后一个,并且应该会覆盖其余部分。
马克,你是想说有 :main-opts 该选项包含一个 "-e" 和一个表达式,程序调用每个三个 -main 函数?就像 "(do (eastwood/-main) (kibit/-main) (antq/-main))"
(无论主命名空间是什么)。

考虑到许多工具在最后都调用了 (shutdown-agents),你可能无法在之后运行 -main 函数...
...