1

Some time ago I was interested in creating a class that would extend one of the custom objects, so I can make some instance methods or other stuff that would be helpful in apex logic. Pretty quickly I realized that it cannot be done ootb and it's explained here How to add an instance method to a custom SObject? . I came up with a workaround, but my gut tells me this is a bad idea. Say I have a custom object called 'MyProduct__c'. The object has two fields: 'field1__c', 'field2__c'. What I could do is make a class that represents a base of that custom object:

public with sharing abstract class BaseMyProduct {

public Id Id;
public String Name;
public String field1_mco;
public String field2_mco;

public BaseMyProduct() {

}
public BaseMyProduct(MyProduct__c sObj) {
    Id = sObj.Id;
    Name = sObj.Name;
    field1_mco = sObj.field1__c;
    field2_mco = sObj.field2__c;
}

public MyProduct__c toProduct() {
    return (MyProduct__c )JSON.deserialize(JSON.serialize(this).replaceAll('_mco', '__c'), MyProduct__c.class);
}

public static MyProduct__c toSObject(BaseMyProduct customTc) {
    return (MyProduct__c )JSON.deserialize(JSON.serialize(customTc).replaceAll('_mco', '__c'), MyProduct__c.class);
}
public static List<MyProduct__c> toSObjects(List<BaseMyProduct> customTcs) {
    return (List<MyProduct__c>)JSON.deserialize(JSON.serialize(customTcs).replaceAll('_mco', '__c'), List<MyProduct__c>.class);
}

The class has all relevant fields, and the custom field suffix '__c' is replaced by something else, in my case it's '_mco'.

With this base class I can implement others that extend this one, implement some method helpers there:

public with sharing class MyCustomProduct extends BaseMyProduct {

public MyCustomProduct() { }
public void doStuff() { ... }

}

do whatever logic I have to do and cast everything with 'toSobjects' or 'toProduct' methods to be able to perform a dml. The example is kind of lame and may not necessarily illustrate why I'm trying to do that, I can figure out a better one if that's necessary. Would that work fine? Is there a better solution? For some reason I have a bad feeling about the JSON serializing and deserializing, but wasn't able to test it on a larger DML operation to see if it breaks on larger structures.

1 Answer 1

2

You are correct that JSON should be avoided entirely. It is a huge performance penalty to use serialization in Apex, as a general rule. I would say a much better structure is to just store the record itself as an attribute.

public with sharing class MyWrapper
{
    final SObject record;
    public MyWrapper(SObject record) { this.record = record; }
    public void doStuff() { /*implementation*/ }
}

Structurally, if you find this wrapper concept useful, the above is the most appropriate (simplest) design. However, I would caution that you have a paradigm mismatch if you are trying to apply this concept to trigger logic, as it focus on single record processing, whereas your trigger logic should focus on collections of data (List<SObject>). Use this pattern only for controller bound logic.

A couple notes:

  • Try to use whole words for your variable names
  • As far as naming goes, a single instance of an SObject is a record
2
  • Agreed, round-trip de/serialization is excessive here (using a shotgun to shoot a fly). Using composition here instead of inheritance accomplishes the same goal (perhaps sacrificing a little extra typing in client classes for a much lighter footprint on CPU limit/processing time).
    – Derek F
    Commented Jun 5, 2023 at 15:00
  • Yeah, I understand the wrapper thing and I also understand the necessity of processing everything in collections, I'm just trying to figure out a neater, more readable solutions. Thanks
    – Szosteczka
    Commented Jun 5, 2023 at 15:06

You must log in to answer this question.

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