[R-pkg-devel] Courtesy methods and explosive dependencies

Ben Bolker bbolker @ending from gm@il@com
Tue Jun 5 20:46:30 CEST 2018


  This seems like a nice solution -- the only disadvantages I can think
of are (1) extra hassle (2) it might generate messages about function
masking when the upstream package (e.g. broom) is loaded?

On 2018-05-25 12:00 PM, Neal Fultz wrote:
> In the estimatr package, we provided a shim to support broom without
> transitively depending on the tidyverse:
> 
> 
> tidy <- function(object, ...) {
>   if (requireNamespace("broom", quietly = TRUE)) broom::tidy(object, ...)
> else UseMethod("tidy")
> }
> 
> https://github.com/DeclareDesign/estimatr/blob/master/R/S3_tidy.R
> 
> It's not ideal but it seems to make our functions work whether or not the
> end user has broom.
> 
> 
> S4 methods (eg texreg) were more difficult, and we ended up registering the
> generics in .onLoad:
> 
> 
> .onLoad <- function(libname, pkgname) {
>   if (suppressWarnings(requireNamespace("texreg", quietly = TRUE))) {
>     setGeneric("extract", function(model, ...) standardGeneric("extract"),
>       package = "texreg"
>     )
>     setMethod("extract",
>       signature = className("lm_robust", pkgname),
>       definition = extract.lm_robust
>     )
>   }
>   invisible()
> }
> 
> https://github.com/DeclareDesign/estimatr/blob/master/R/zzz.R
> 
> 
> Since this is in .onLoad, it's a little buggy if the user has estimatr and
> then installs texreg, but again seems to mostly work.
> 
> We would appreciate any feedback the list may have on these design patterns.
> 
> 
> -Neal
> 
> 
> 
> 
> On Fri, May 25, 2018 at 8:38 AM, Lenth, Russell V <russell-lenth using uiowa.edu>
> wrote:
> 
>> I agree that most of the package dependencies in multcomp are worth
>> having, but that is not the point. The point is that if a developer wants
>> to write a method for a generic function offered in another non-base
>> package, that creates false dependencies: packages that users are required
>> to have, but that aren't actually used by the method. I certainly wasn't
>> trying to diss multcomp; that was just a concrete illustration.
>>
>> Russ
>>
>> -----Original Message-----
>> From: Martin Maechler [mailto:maechler using stat.math.ethz.ch]
>> Sent: Friday, May 25, 2018 2:13 AM
>> To: Lenth, Russell V <russell-lenth using uiowa.edu>
>> Cc: r-package-devel using r-project.org
>> Subject: Re: [R-pkg-devel] Courtesy methods and explosive dependencies
>>
>>>>>>> Lenth, Russell V
>>>>>>>     on Thu, 24 May 2018 23:14:42 +0000 writes:
>>
>>     > Package developers, I am trying to severely cut down on
>>     > the number of dependencies of my package emmeans. It is
>>     > now 48, which is quite a few (but that is down from over
>>     > 100 in the preceding version, where I made the unwise
>>     > choice of including a particularly greedy package in
>>     > Imports). I hate to force users to install dozens of
>>     > packages that they don't really need or want, but it seems
>>     > very hard to avoid.
>>
>>     > Case in point: emmeans provides additional methods for
>>     > 'cld' and 'glht' from the multcomp package. Accordingly, I
>>     > import their generics, and register my additional
>>     > methods. But because I import the generics, I must list
>>     > multcomp in Imports, and that results in the addition of
>>     > 16 required packages, some of which I never use. More
>>     > important, I believe that NONE of those 16 packages are
>>     > required for the correct functioning of my courtesy
>>     > methods. The only things I really need are the generics.
>>
>> There must be a mistake here -- I think in your perception:
>>
>> 'multcomp' does *not* have excessive dependencies (though I'd say one too
>> much):
>>
>>> tools::package_dependencies("multcomp")
>> $multcomp
>> [1] "stats"     "graphics"  "mvtnorm"   "survival"  "TH.data"   "sandwich"
>> [7] "codetools"
>>
>>> tools::package_dependencies("multcomp", recursive=TRUE)
>> $multcomp
>>  [1] "stats"     "graphics"  "mvtnorm"   "survival"  "TH.data"
>>  "sandwich"
>>  [7] "codetools" "methods"   "utils"     "zoo"       "Matrix"
>> "splines"
>> [13] "MASS"      "grDevices" "grid"      "lattice"
>>
>>>
>>
>> Apart from "base + recommended" packages (which *everyone* has installed),
>> these are just 4 packages:
>>
>>      mvtnorm
>>      TH.data
>>      sandwich
>>      zoo
>>
>> where  mvtnorm, sandwich, and zoo  really are among the (formally
>> undefined) recommended-level-2 R packages... so I do wonder if you really
>> had needed to install.
>>
>> The 'TH.data' { TH <==>  maintainer("multcomp") } package I think should
>> not be in the strict dependencies of 'multcomp' but rather in its
>> "Suggests".... something I'd say must be true for all data packages:
>> The whole idea of data packages is that they should be needed for
>> interesting help page examples, vignettes, maybe even tests, but not for
>> package functionality.
>>
>> In sum: I'd strongly advise to not change from keeping multcomp among your
>> imports.
>>
>> Martin Maechler
>> ETH Zurich
>>
>>     > On the flip side, emmeans defines some generics of its own
>>     > that I invite other package developers to extend so that
>>     > emmeans supports their models. If those packages import
>>     > emmeans, there is an overhead of 48 dependencies; again,
>>     > most of these are packages that are not needed at all for
>>     > those packages' methods to work. I don't like being
>>     > responsible for that.
>>
>>     > I believe this is a very common problem, not just with my
>>     > own packages. It's one thing to extend a base method like
>>     > 'print'; but extending methods in contributed packages
>>     > creates these dependency explosions. I have hundreds of
>>     > packages installed on my system - a couple dozen I care
>>     > about, another few dozen that seem fairly desirable, and a
>>     > couple hundred that I don't even know what they're for,
>>     > other than that things will break if I uninstall them.
>>
>>     > I do know of a couple ways to reduce these dependencies in
>>     > the case of my multcomp dependencies:
>>
>>     > 1. I could simply export my S3 methods for cld and glht as
>>     > functions, rather than registering them as S3 methods.
>>     > Then I could move multcomp to Suggests. The downside is
>>     > that it clutters the namespace for emmeans.
>>
>>     > 2. I could define the generics for cld and glht in my own
>>     > package, and export them; and move multcomp to Suggests.
>>     > Again, it clutters the namespace, and creates warning
>>     > messages about (if not real issues with) masking.
>>
>>     > Probably (1) is better than (2), but is it better than
>>     > what I do now? Is there something else that I (and
>>     > probably a whole lot of other people) don't know?
>>
>>     > I wish there were an ImportGenerics or an
>>     > ImportWithoutDependencies or some such field possible in
>>     > DESCRIPTION.
>>
>>     > I appreciate any suggestions. Thanks
>>
>>     > Russ
>>
>>     > --
>>     > Russell V. Lenth  -  Professor Emeritus Department of
>>     > Statistics and Actuarial Science    The University of Iowa
>>     >  -  Iowa City, IA 52242  USA    Voice (319)335-0712  -
>>     >  FAX (319)335-3017 russell-lenth using uiowa.edu  -
>>     >  http://www.stat.uiowa.edu/~rlenth/
>>
>>     > ______________________________________________
>>     > R-package-devel using r-project.org mailing list
>>     > https://stat.ethz.ch/mailman/listinfo/r-package-devel
>>
>> ______________________________________________
>> R-package-devel using r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>>
> 
> 	[[alternative HTML version deleted]]
> 
> ______________________________________________
> R-package-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-package-devel
>



More information about the R-package-devel mailing list