请在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 monorepos。当然,有相当多的方法可以对付 Clojure monorepos 的问题,但一个简单的方法是

  • 在仓库根目录中维护单个 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` 之外是无形的)。
我们有一个单体存储库,这绝对是我们面临的一个痛点,直到我们在 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 提出从多个别名继承时的潜在冲突问题。鉴于此,将别名引用为向量而不是集合可能更佳。由于这一担忧,可能还会有其他设计挑战需要解决,但我仍然认为这是一个有用的功能。

是的,排序确实很重要
+1 投票

我担心的是,在原本简单的配置中引入继承(甚至多重继承)的复杂性。我从多年的Java学习中总结到,要避免这些方法,而使用组合,这提供了更大的灵活性。

使用 tools.build 是否是解决单仓库(mono-repos)问题的更简单方法?

在原始问题中提到的例子中,是否有机制来防范或至少警告类似于:dev/project1包含在:dev/all-projects或另一个分组别名的:dev/all-projects或其他别名的情况?这个分组可以有多少层级?

是否有定义明确的优先级规则?
是否会有工具来诊断冲突所在之处——也许Stree就足够了,但我并不确定。

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

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

我希望针对单仓库(mono-repls)的问题可以通过不增加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
头像 by
当你结合所有包含 :main-opts 的别名时,仅使用最后一个(因为主选项是位置参数,传递给 clojure.main 的 -main 函数),因此即使有多个别名,也无法通过单个命令行来运行多个代码检查工具。

需要通过其他进程依次运行这三个代码检查工具的 -main 函数。
头像 by
是的,这是一个众所周知的问题,但人们仍然可以通过在 :lint 别名内部提供一个自定义的 :main-opts 来克服这个问题,该 :main-opts 将所有工具的主函数调用组合成一个,例如按照 Cam Saul 的 Lein-alike 语法示例。这样,它将是最新的一个,并将覆盖其他工具。
头像 by
马克,你的意思是有一个包含"-e"和一个程序调用每个三个主函数的表达式的:main-opts 么?比如 "(do (eastwood/-main) (kibit/-main) (antq/-main))"。
不管主命名空间是什么。

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