请在2024年Clojure状态调查中分享您的想法!

欢迎!请查看关于页面以获取更多关于如何使用本站的信息。

+46
tools.deps
重新标记

有一个包含其他别名的别名会很有用。

一个用例是有时候仅针对一个项目进行开发,而其他时候则针对一组项目进行开发。

以下是一个例子

{: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单体库中组织内容。当然,有相当多的方法来处理Clojure单体库的问题,但一种简单的方法是

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

这给了我们

  • 一个清晰的deps.edn文件,其中包含所有内容
  • 无需像一些项目中看到的那样动态构建deps.edn文件,这样可以实现声明性工具的目的。
  • 外部依赖被锁定;例如,所有需要外部库的模块都使用相同的版本,而不进行重复使用该库的专用别名
  • 非常容易构建所需的精确classpath;只需简单拼接别名
  • 不存在像传递性本地依赖未更新之类的状况
  • 没有使用像../../local-lib/src之类的邪恶实践

这是一种非常精确的方法,只要这样做就有效。唯一的缺点是现在必须与许多别名周旋,而且并不总是显而易见什么真正需要或不需要

clj -M:module-1/dev:module-1:main:module-2/main:ext/lib-1:ext/lib-2:ext/lib-3...
当然可以编写需要无数别名的脚本调用,但这过于复杂且易于出错。如果别名能够要求一系列别名,就可以解决这个案例。

另一个好处是它很适用于CI和操作,因为它可以避免在添加别名时更新无数脚本(即您可以在任何地方始终使用同一“主”别名,并添加/删除它所要求的别名,对外部 `deps.edn` 的可见性没有影响)。
我们有一个MonoRepo,这绝对是我们遇到的一个痛点,直到我们找到了一个更适合deps.edn的结构——参见我在corfield.org上关于这一历程的一系列博客文章——现在我们正在迁移到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指出从多个别名继承时可能存在冲突的潜在风险。因此,可能更倾向于引用别名向量而不是集合。由此产生的其他设计挑战可能需要解决,但我仍然认为这是一个有用的功能。

是的,顺序肯定很重要
+1

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

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

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

是否有明确的优先级规则?
是否有工具可以诊断冲突所在 - 可能-Stree足够,但我并不确定

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

可能的一个避免方式是有一种类似于:meta-aliases的东西,它只能包括别名而不是其他:meta-aliases,但这样做仍然似乎增加了复杂性。

我希望单仓(mono-reps)特有的问题能够在不增加deps.edn配置复杂性的情况下得到解决(特别是避免继承或多重继承)。

+1

我认为可能的语法会类似于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 投票
by

这会在代码审查中非常有用。

clj -M:eastwood:kibit:antq

可以是

clj -M:lint
当你组合所有包含 :main-opts 的别名时,只有最后一个被使用(因为 main 选项是按位置传递的,传递给 clojure.main 的 -main 函数),因此你不能通过单独的命令行运行多个代码审查工具,即使是有多个别名。

你需要某些其他进程一个接一个地运行三个代码审查工具的 -main 函数。
by
是的,这是一个已知的问题,但是仍然应该可以通过提供手工制作的 U:lint别名,在其中一个合并所有工具的主要功能调用进一个来实现,例如按照 Cam Saul 的 Lein-alike 语法示例进行。这样,它将是最后一个,并覆盖其他所有内容。
Mark,你的意思是要不要让 :main-opts 包含 "-e" 以及一个程序自动调用三个 -main 函数的表达式?比如 "(do (eastwood/-main) (kibit/-main) (antq/-main))"。
(无论主命名空间是什么)。

由于许多工具在末尾都会调用 (shutdown-agents),你可能在那之后无法再运行 -main 函数...
...