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文件,就像一些项目中所见的那样(打破了声明性工具的目的)
  • 外部依赖已被锁定;例如,所有需要外部库的模块都使用相同的版本,并通过为该库使用专用别名来避免重复
  • 非常容易构建所需的精确类路径;只需连接别名即可
  • 不存在递归本地依赖没有更新的情况
  • 没有使用../../local-lib/src等不道德的做法

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

clj -M:module-1/dev:module-1:main:module-2/main:ext/lib-1:ext/lib-2:ext/lib-3...
当然,您可以为需要无数别名的脚本编写脚本来调用,但这无疑是复杂和容易出错的。如果别名能够要求一系列别名,就可以解决这个问题,案例被解决了。

另一个好处是它非常适合 continuous integration (CI) 和 operations (ops),因为它可以防止在添加别名时需要更新无数脚本(例如,您可以在每个地方始终使用相同的 "main" 别名,并添加/删除它所要求的别名,机会在 `deps.edn` 之外是看不到的)。
我们有一个单一代码库(monorepo),这确实是一个痛点之一,直到我们找到了一个更适合 deps.edn 的结构——见我在 corfield.org 上关于这段历程的一系列博客文章——现在我们正在迁移到 Polylith,而这只需要 handful of 别名。话虽如此,我自己的开发环境依赖于这样的调用:

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学习中了解到,应避免这些方法,而使用组合,这提供了更大的灵活性。

使用工具.build来简化处理monorepo中的这个问题的方法可能更简单吗?

在原文中的例子中,将会有一种机制来防止:dev/project1包含:dev/all-projects或其他包含别名的别名?这种分组可以有多少层?

将有没有定义明确的优先级规则?
将有没有工具来诊断冲突所在 - 或许-Stree就足够,但我并不确定

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

也许避免这种情况的方法是有一条类似:meta-aliases的机制,它只能包含别名而不能包含其他:meta-aliases,但这样似乎还是在增加复杂性。

我希望特定于monoreps的问题可以在不向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 投票
by
0 投票
by

这对于进行代码格式检查非常有用。

clj -M:eastwood:kibit:antq

可以是

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

你需要一些其他的过程来依次运行三个代码格式检查工具的 -main 函数。
by
是的,这是一个已知问题,但仍然可以通过在 :lint 别名本身中提供一个手工调制的 :main-opts 来克服这个问题,将所有工具的主要 fn 调用组合成一个。例如,根据 Cam Saul 的 Lein-alike 语法示例。这样它将是最后的一个,并覆盖其他的。
by
马克,你的意思是有一个包含 "-e" 的 :main-opts 表达式,并程序化地调用三个 -main 函数中的每个?就像 "(do (eastwood/-main) (kibit/-main) (antq/-main))" 一样。
(无论主命名空间是什么)。

鉴于很多工具在最后都会调用 (shutdown-agents),你很可能之后无法再运行 -main 函数...
...