Salesforce Asked on October 4, 2021
I worked on Managed packages for nearly 10 years now and never missed Custom Metadata Types
. Not before they came and not after they were announced. I didn’t come across a single great and technical severe reason to use Custom Metadata Types over regular Custom Object.
Unlike Custom Objects they:
The only use case where CMDT are somewhat nice is, that you cannot package Custom Object records in packages. But that is also not an issue. You can perfectly store hundreds of Custom records in JSON serialized form in a single packaged Static Resource and unpackage them on install.
So tell me what your reasons are to favor them over Custom Objects?
Here are some "advantages" vs using a Custom Object:
@seeAllData
, it actually makes integration testing the current configuration of the ORG much easier.However (IMO), Salesforce missed too many features to make them the clear choice in every scenario:
I've created a public google sheet that attempts to compare the features of each of the configuration options (please add comments if I missed anything).
My Approach
Correct answer by NSjonas on October 4, 2021
I've always seen them as an alternative to Custom Settings as much as an alternative to Custom Objects.
However, one use case that stands out where they were really useful was in configuring mappings in a point-to-point integration inbound to Salesforce where they essentially acted as the middleware.
We could create mappings of values from the source system to values in specified fields on specified SObjects in SFDC, and kept this to be a declarative exercise. Again, nothing that couldn't be done in JSON, but this was a Professional Services engagement where the customer was extremely keen to avoid code-heavy solutions (and they'd have classed JSON manipulation as that) due to having no available in-house resources for that.
Answered by barrick on October 4, 2021
Robert - in response to your point about Custom Metadata being hard to set up in unit tests
I use the selector pattern to query all sobjects, including Custom Metadata, then, use mocking via dependency injection to return the results to the testmethod. This decouples the testmethod from any live custom metadata (and thus achieves test isolation). Here is a small fragment
Standard fflib Selector and apexmocks pattern follows; assumes an Application class as per fflib pattern.
Since you can't construct Custom Metadata label/developername, I resort to the JSON deserialize approach. Here, I'm using the SObject Fabricator repo but there are other ways to do this including maps, json strings, or other libraries. Once you go the dependency injection route to unit tests, it is inevitable you will need at some point to have to construct sobjects that aren't supported by new TheSObject(..)
. I liked SObject Fabricator for its expressiveness.
fflib_ApexMocks mocks = new fflib_ApexMocks();
// Given mockSelector results
MyCustomMetadata__mdt[] mockMdts = new List<MyCustomMetadata__mdt> {
(MyCustomMetadata__mdt) new sfab_FabricatedSObject (MyCustomMetadata__mdt.class) // [
.setField(MyCustomMetadata__mdt.Label,'foo')
.setField(MyCustomMetadata__mdt.SomeField__c,true)
.toSObject(),
(MyCustomMetadata__mdt) new sfab_FabricatedSObject (MyCustomMetadata__mdt.class) // [1] not troubleshooter
.setField(MyCustomMetadata__mdt.Label,'bar')
.setField(MyCustomMetadata__mdt.SomeField__c,false)
.toSObject()
};
// Given mock selector(s)
MyCustomMetadatasSelector mockMdtsSelector = (MyCustomMetadatasSelector) mocks.mock(MyCustomMetadatasSelector.class);
mocks.startStubbing();
mocks.when(mockMdtsSelector.sObjectType()).thenReturn(MyCustomMetadata__mdt.SObjectType);
mocks.when(mockMdtsSelector.selectByLabel(new Set<String>{'foo'}))
.thenReturn(new List< MyCustomMetadata__mdt> {mockMdts[0]});
mocks.when(mockMdtsSelector.selectByLabel(new Set<String>{'bar'}))
.thenReturn(new List<MyCustomMetadata__mdt> {mockMdts[1]});
mocks.stopStubbing();
// Given mocks injected
Application.Selector.setMock(mockCrsdToDescriptionsSelector);
// when code-under-test invoked
Test.startTest();
new MyClass().doStuff();
Test.stopTest();
// Then verify
.. asserts and/or mocks.verify
Note that if the selector method is called with a set containing only foo
, the first mocked custom metadata is retrieved by the dependency-injected selector. And, if called with a set containing bar
, the second mocked custom metadata is retrieved.
Since you can't construct Custom Metadata label/developername, I resort to the JSON deserialize approach. Here, I'm using the SObject Fabricator repo but there are other ways to do this including maps, json strings, or other libraries. Once you go the dependency injection route to unit tests, it is inevitable you will need at some point to have to construct sobjects that aren't supported by new TheSObject(..)
. I liked SObject Fabricator for its expressiveness.
I know you use your own testobject fabricator so adapt as necessary.
Answered by cropredy on October 4, 2021
Some benefits not listed but I like are:
I still agree that a lot should be improved and not being able to fully replace hierarchical custom settings also make them a little less appealing. Plus, unit tests experience with them still more painful.
Answered by Jeferson Chaves on October 4, 2021
We've implemented them and it was one of the biggest disappointments as an ISV, here's why:
There was also some obscure SOQL limitation that I can't remember at the moment.
Basically it's only upside (deployable, wow) hardly justifies all the downsides.
Answered by dzh on October 4, 2021
A reason I haven't seen articulated yet applies specifically to the managed package context:
Packaged, protected Custom Metadata Types are an ideal solution for secret storage in a managed package context. While Protected Custom Objects and Protected Custom Settings can also offer secret storage, only Custom Metadata Types allow those secrets to be packaged and deployed, and protected from everything outside the boundary of packaged Apex.
Answered by David Reed on October 4, 2021
The big reason for me to use Custom Metadata is the logical separation between Custom Metadata and Custom Objects. In my head they serve a different purpose and that helps me better organize things in my org. I would store any configurations for my applications in Custom Metadata rather than Custom Objects. The way I see it Custom Objects should retain data about records in the org.
Additionally as NSjonas pointed out CM doesn't count against the governor limits in the org. They can be refreshed to sandboxes and are cached data which would provide better performance.
Answered by Arthlete on October 4, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP