请您在 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

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

一开始,别名要求其他别名的想法可能不是很实用,但我相信这是组织 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...
当然,您可以编写脚本调用以获得无数别名,但这既复杂又容易出错。如果别名能够要求一个别名向量,那么这个问题就可以解决了。

by
另一个好处是它与CI和运维兼容良好,因为它防止了添加别名时需要更新成千上万个脚本的麻烦(例如,您可以在任何地方都使用相同的“main”别名,并添加/删除它需要的别名,这样对`deps.edn`之外的人来说是无形的)。
by
我们有一个单体仓库,这绝对是我们遇到的一个痛点之一,直到我们找到了一个更适合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 投票
by

感谢John Stevenson指出,从多个别名继承时可能存在冲突的风险。因此,指代一个别名向量而不是集合可能更合适。因此出于这个担忧,可能还有其他设计挑战需要解决,但我仍然认为这是一个有用的功能。

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

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

使用 tools.build 作为解决 mono-repos 中此问题的更简单的方法是否可行?

在原始问题中提出的示例中,是否会有机制来防范或至少警告 :dev/project1 包含 :dev/all-projects 或另一个分组别名的情况?这种分组可以深入到多少层次?

是否有明确定义的优先级规则?
是否有工具可以诊断冲突的来源——也许 -Stree 已经足够了,但我并不确定

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

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

我希望可以通过不增加 deps.edn 配置的复杂性(特别是在避免继承或甚至多重继承的情况下)来解决特定于 mono-repls 的问题。

+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 投票

这将是非常有用的 linting。

clj -M:eastwood:kibit:antq

可能是

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

你需要某种其他进程来依次运行三个 lint 工具的 -main 函数。
这是众所周知的问题,但仍然可以通过提供自定义的 :main-opts 来克服这个问题,将所有工具的 main fns 调用组合成一个在 :lint 别名中,例如按照 Cam Saul 的 Lein-alike 语法示例。这样它将是最后一个,将覆盖其他的。
马克,你的意思是有一个包含“-e”和通过编程调用三个主函数的表达式的`:main-opts`?例如:"(do (eastwood/-main) (kibit/-main) (antq/-main))"
(无论主命名空间是什么)。

鉴于许多工具在结束时调用`(shutdown-agents)`,你可能无法在之后运行`-main`函数...
...