13

So, in a project of mine (a Second Generation Managed Package) I have a dependency on fflib. My initial idea was to include fflib-apex-common and fflib-apex-mocks as 2GPs with the same namespace as my solution. However, this would require a refactoring of fflib, because to make this work I would either need to decorate all the required classes with @namespaceAccessible(see here) OR replace every public access modifier with global. Not good. I don't really want to touch the code of fflib.

The only other way is to just copy fflib to my source directory (not really copying but submodule-ing it to my source directory). I don't like that approach either. My gut feeling tells me I don't want to have fflib in my package. Also, I'm wondering why no one seems to have released fflib as 2GP already. I guess there has to be some reason for this?

To me, it feels like I'm caught between a rock and a hard place. I'd really like to use fflib just as a dependency in my sfdx-project.json file.

What are your opinions on that topic, or can you give me any best practice recommendations please?

5
  • 2
    Your suggestion makes sense (having this available in a separate 2GP). How about creating a PR against the fflib repo adding NamespaceAccessible annotations like you suggest?
    – Phil W
    Commented Dec 20, 2021 at 12:04
  • 2
    @PhilW I thought so as well, but then I found this: github.com/apex-enterprise-patterns/fflib-apex-common/issues/85, and even though it's 6 years old Andrew makes it quite clear that he prefers to have fflib being embedded it in the package. So the question is how much chances a PR has getting merged.
    – lightxx
    Commented Dec 20, 2021 at 12:08
  • 3
    That answer is predicated on 1GP managed packages, where "global" is a nightmare because it causes freezing of APIs and version-to-version compatibility issues. I don't believe namespace accessibility has the same constraints and should, therefore, be quite supportable in the code base. My only concern: what happens when you use this annotation outside a 2GP? I've not tried the latter. I would hope it is effectively ignored, but can't be sure.
    – Phil W
    Commented Dec 20, 2021 at 12:15
  • 2
    I'll cross-post this on Twitter to see if John Daniel has thoughts
    – cropredy
    Commented Dec 21, 2021 at 5:28
  • 1
    @cropredy thanks!
    – lightxx
    Commented Dec 21, 2021 at 9:33

2 Answers 2

7

I'll start this answer by recognizing that questions which solicit opinions, rather than objective answers, are frowned upon on StackExchange.

Having said that, the question was framed beautifully and this is an important topic.

I've been giving this a lot of thought lately. I'm hopeful that I can provide a constructive response based on my experience delivering Platform Expert consultations to more than 100 partners since 2GP went GA.

2GP's support of multi-package, same-namespace (MPSN) solutions is profoundly transformative. Improved reuse of code, better separation of concerns, faster package installation, safer and more frequent upgrades, and greater autonomy and agility during development are all benefits enabled by 2GP.

Taking full advantage of these benefits requires an evolution of how packaged Salesforce apps are built, especially when it comes to critical building blocks that our community has come to rely on, like fflib-apex-common and force-dot-com-esapi.

I don't think it's enough to add @namespaceAccessible to the existing libraries and call it a day. The ability to share logic across packages without being forced to create global APIs unlocks entirely new ways of thinking about how we solve common problems. Keeping one foot in the past by having to worry about whether our libraries are backwards compatible with 1GP holds us back.

Instead, I believe that...

  • Important libraries should be forked to allow 2GP-specific customizations to be made without expectation of backwards compatibility with 1GP.
  • A "bedrock" template should exist, bundling key community libraries into a single package, forming a foundation for MPSN solutions.
    • I suggest this instead of separately packaging each library because there needs to be a balance between the development and the distribution/support aspects of the packaging lifecycle, especially when dealing with thousands of subscribers at scale.

I know that many AppExchange developers are stuck on 1GP until 1GP=>2GP migration becomes available, but there is a steadily growing cohort of developers who cut their teeth solely on 2GP. There are also teams who've worked with 1GPs for years and are now doing double-duty building on 1GP and 2GP. These are the groups who would benefit from, and hopefully contribute to, new community-led efforts for 2GP specialization.

I've been test driving these ideas both inside and outside of Salesforce for the past couple of months. My current plans are to create an "ISV Bedrock"-style framework that delivers some of what I've discussed sometime in FY'23 (i.e. after February, 2022).

The OP's question and the thoughtful comments added by my friend Phil W. give me confidence that I'm moving in the right direction. I'm looking forward to hearing the thoughts and perspectives of others on this topic.

2
  • 1
    I am generally supportive of the suggestions in this answer, though wary of the idea of "library bundles". It is too easy to bloat these by adding more and more stuff that is peripheral to the key package goals. I would much rather have dedicated packages for specific elements, with these extended as needed for the peripheral "add-ons". The tough ask is just how such packages should be namespaced. This is, perhaps, where a special accessible-across-namespaces-without-globals namespace could help, where the packages for this namespace are curated (though not maintained by) Salesforce.
    – Phil W
    Commented Dec 23, 2021 at 16:32
  • 3
    @PhilW - You make an interesting suggestion here. One idea that we talk about internally (safe harbor) is being able to one day deliver cross-namespace "allow-list" functionality. This would give namespaceAccessible-like abilities to packages with different namespaces to interact in ways similar to what you mention. Your suggestion takes that to the next level by granting special packages global accessibility without global Apex. I quite like that idea. I'll bring this up with Dileep the next time we speak. Commented Dec 23, 2021 at 17:47
5

G'day folks. Apologies for being a bit late to this discussion.

@lightxx -- There are pros and cons about separating the fflib classes out to a new package.

All things being equal, it makes sense to isolate the fflib classes into two different packages; one for Apex Mocks and one for Apex Common.

Having said that, there is currently a couple of downsides. The first being the need to have each package go through the security review separately. The second issue becomes the current lack of support for "bundled package deployments." It is on the roadmap, but currently not available. That lack of support for that feature creates issues during upgrades and support for AppExchange.

The earlier comment that you referenced from Andy Fawcett that the fflib classes should be bundled in the package is somewhat dated and pre-arrival of 2nd Generation Package. Having said that, the issues mentioned above still factor into this question.

There was an effort to outfit the Apex Mocks and Apex Common classes with the @NamespaceAccessible annotation. You can see an earlier PR Attempt in Apex Mocks here. In the end, the decision was to abandon the attempt because of issues at the time with the annotation. Those issues have been fixed. Since then, there has been no real interest that I am aware of into resuming this work until now. I, and others in the Apex Enterprise Patterns team, have discussed the idea of starting a new attempt but there has been no serious effort made in that direction. If this is something that you would be interested in helping with, I would suggest opening a feature-enhancement issue on the Apex Mocks and Apex Common repos and we can continue the discussion there.

I hope this helps.

3
  • If you wanted to create a separate 2gp package of fflib and add in the @NamespAceaccessible annotations, what impacts does that have in security review and publishing your app on appexchange? Do you have to now submit 2 packages for review? When a customer installs the app are they responsible for then installing the fflib 2gp separately or is app exchange smart enough to resolve the dependency? Commented Feb 1 at 22:15
  • 1
    G'day @TemporaryFix. Yes, both packages would have to go through security review; for 2GP, you can submit 4 packages as part of the same "solution" and only pay the $999 once per attempt. The other comments above would still apply -- all methods would need to be decorated with NamespaceAccessible. Commented Feb 5 at 13:47
  • 1
    And because of the current lack of the Salesforce "Package Bundles", the concept of ISV's separating their solution into multiple packages might be the correct technical thing to do but it makes for a pretty poor user experience. You would be asking your customer on the AppExchange to "first, go install package A.. then install package B.. then install package C.. etc. Commented Feb 5 at 13:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .