问题描述
我开始研究一系列 R 包,所有这些包都共享大量的公共代码,这些代码都存放在自己的包中,我们称之为 myPackageUtilities
.所以我有几个包
I am starting to work on a family of R packages, all of which share substantial common code which is housed in its own package, lets call it myPackageUtilities
. So I have several packages
myPackage1
、myPackage2
等...
所有这些包都依赖于 myPackageUtilities
中的每个方法.有关真实示例,请参阅 statnet on CRAN.这个想法是未来的开发人员可能会创建 myPackageN
,而不必重新编写/复制所有支持代码,这个未来的开发人员可以简单地使用 mypackageUtilities
来获取开始了.
All of these packages depend on every method in myPackageUtilities
. For a real-world example, please see statnet on CRAN. The idea is that a future developer might create myPackageN
, and instead of having to re-write/duplicate all of the supporting code, this future developer can simply use mypackageUtilities
to get started.
有并发症:
1) 部分 mypackageUtilities
中的代码供最终用户使用,其余的则用于内部开发目的.最终用户代码需要使用 roxygen2 正确记录.此代码包括 S3 类和泛型,以及用户的各种帮助函数.
1) Some of the code in mypackageUtilities
is intended for end-users, and the rest is for internal development purposes. The end-user code needs to be properly documented using roxygen2. This code includes both S3 classes and generics, as well as various helper functions for the user.
2) 依赖包(myPackage1
、myPackage2
等)可能会扩展在 myPackageUtilities
中定义的 S3 泛型.
2) The dependent packages (myPackage1
, myPackage2
, etc.) will likely extend S3 generics defined in myPackageUtilities
.
我的问题是:组装所有这些的最佳方式是什么?这里有两个自然的(但非详尽的)选项:
My question is: What is the best way to assemble all of this? Here are two natural (but non-exhuastive) options:
- Imports下包含
mypackageUtilities
:对所有依赖包,强制用户单独加载mypackageUtilities
, - 在 Depends: 下包含
mypackageUtilities
用于所有依赖包,并且对从mypackageUtilities
导出的内容非常有选择性,以免造成搜索路径混乱.所有内部(非导出)代码都必须通过myPackage1
中的:::
等访问.
- Include
mypackageUtilities
under Imports: for all the dependent packages, and force users to separately loadmypackageUtilities
, - Include
mypackageUtilities
under Depends: for all the dependent packages, and be very selective about what is exported frommypackageUtilities
so as to avoid cluttering the search path. All of the internal (non-exported) code will have to accessed via:::
inmyPackage1
, etc.
我最初问了一个类似的问题在这里,但很快发现情况很快变得复杂.例如:
I originally asked a similar question over here, but quickly discovered the situation gets complicated quickly. For example:
- 如果我们使用 Imports: 而不是 Depends:,那么
mypackageUtilities
中定义的任何泛型都不会被myPackage1
等找到.- 这使得使用
mypackageUtilities
提供的通用模板变得困难/不可能,并且几乎违背了整个设置的目的.
- If we use Imports: instead of Depends:, then any generics defined in
mypackageUtilities
aren't found bymyPackage1
, etc.- This makes using the generic templates provided by
mypackageUtilities
difficult/impossible, and almost defeats the purpose of this entire set-up.
也许我深深误解了命名空间的工作原理,在这种情况下,这将是消除我的误解的好地方!
Perhaps I am deeply misunderstanding how namespaces work, in which case this would be a great place to clear up my misunderstanding!
推荐答案
欢迎来到兔子洞.
您可能会惊喜地发现您可以将
myPackageUtilities
中的函数导入到myPackage1
中,然后从myPackage1
中导出来制作可从全球环境中访问.You may be pleasantly surprised to learn that you can import a function from
myPackageUtilities
intomyPackage1
and then export it frommyPackage1
to make it accessible from the global environment.所以,当您说
myPackageUtilities
中有一个函数应该由最终用户在myPackage1
加载时访问时,这就是我将包含在我的myPackage1
So, when you say that you have a function in
myPackageUtilities
that should be accessible by the end user whenmyPackage1
is loaded, this is what I would include in my documentation forfn_name
inmyPackage1
#' @importFrom myPackageUtilities fn_name #' @export fn_name
(参见 https://github.com/hadley/dplyr/blob/master/R/utils.r 例如)
这仍然留下了如何链接到原始文档的问题.恐怕我对此没有一个好的答案.我目前的做法是,基本上,从原始源复制参数文档,然后在我的
@details
部分写入请参阅文档 code{link[myPackageUtilities]{fn_name}}
That still leaves the question of how to link to the original documentation. And I'm afraid I don't have a good answer for that. My current practice is to, essentially, copy the parameters documentation from the original source and then in my
@details
section writeplease see the documentation for code{link[myPackageUtilities]{fn_name}}
最后,我仍然认为您最好的选择是从
myPackageUtilities
导出所有将在myPackageUtilities
之外使用的内容,并在每个您希望myPackageUtilities
中的函数可从全局环境访问的包.In the end, I still think your best bet is to export everything from
myPackageUtilities
that will ever get used outside ofmyPackageUtilities
and do a combination import-export in each package where you want a function frommyPackageUtilities
to be accessible from the global environment.这篇关于开发一套依赖 R 包的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
- This makes using the generic templates provided by
- 这使得使用