function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Kenji775Kenji775 

Silly public variable question

hey all,

So since I don't really have any programming training and just kinda figured things out by hacking along, I don't know some pretty basic things. In this case, I have a variable that will be shared by many methods in my class. Of course I have made it public, so it is accessable by all.

 

Now, the contents of this variable take some time to compute, but currently every method calculates it and sets it, because they have no way of knowing if it has been set before (I could have it evaluate for null, but that seems messy). As I add more methods to this class, any comination of which may run (based on after/before, insert/update/delete/undelete) is there a keyword I assign the variable that will make it so my methods set it if it hasn't been in that instance, or skip it if it has? I think there is a keyword called final, is that what I am looking for? 

 

I know, it's kind of a dumb question, but I would really like to know, so I'm swallowing my pride here :P Feel free to mock if neccesary. 

sfdcfoxsfdcfox

Perhaps the best way to do this is to make the "set" method to private, and make the get method public. Then, in your get method, check to see if you've already calculated the value, and if so, return the value. This way, you only really need to calculate the result once. Here's what it might look like:

 

public String myValue {
  get {
    if(myValue!=null) return myValue;

    String calculatedValue = '';

    // do complex stuff here

    // now that it is set, return the value.
    myValue = calculatedValue;
    return myValue;
 }
 private set;
}

To answer some questions you had in here:

 

The method I presented above means that while any class can access the value, we can have the calculation delayed until the exact moment that the value is needed (termed "lazy evaluation"). None of your code has to check to see if the value is already initialized.

 

The "final" keyword, in contrast, means you can only assign a value during the constructor or static initialization method (for static variables). This means that any code that uses the class that has the variable automatically incurs the execution penalty, even if the entire bit of code never uses the specific variable.

Kenji775Kenji775

Very cool, thank you for the information, that makes a lot of sense. I think the only other fact that I have forgetten to mention that may muddy the waters here is that the value is built by iterating over a set of passed in objects, so would the set method have access to a local variable within the calling method? Currently it looks a bit like this. It is unknown which method may be called first, and in some cases one will be called but not the other. How would I adapt your code for this kind of situation?

 

public map<string,contact> contactUniqueIdList = new map<string,contact>();

public static void MethodOne(list<contact> contacts)
{
	for(contact con : contacts)
	{
		contactUniqueIdList.add(con.uniqueId__c,con);
	}
	//do other stuff with the list
}

public static void MethodTwo(list<contact> contacts)
{
	for(contact con : contacts)
	{
		contactUniqueIdList.add(con.uniqueId__c,con);
	}

	//do other stuff with the list
}

 

thank you so much for the help, I really do appreciate it.

sfdcfoxsfdcfox
public class ContactUtil {
  public static ContactList contactUniqueIdList {
    get {
      if(contactUniqueIdList == null)
        contactUnqiueIdList = new ContactList();
      return contactUniqueIdList;
    }
    private set;
  }

  public class ContactList {
    private Map<String,Contact> _contactMap;
    public void add(List<Contact> contacts) {
      if(_contactMap!=null)
        return;
      _contactMap = new Map<String,Contact>();
      for(Contact c:contacts)
        _contactMap.put(c.UniqueId__c,c);
// Do other calculations here. } public Set<String> keySet() { if(_contactMap==null) return new Set<String>(); return _contacts.keySet(); } public List<Contact> values() { if(_contactMap==null) return new List<Contact>(); return _contacts.values(); } } public static void MethodOne(List<Contact> contacts) { contactUniqueIdList.add(contacts);
// Contacts are ready for use.  } public static void MethodTwo(List<Contact> contacts) { contactUniqueIdList.add(contacts);
// Contacts are ready for use. } }

Let's go over the code in some more detail...

 

First, we have a static variable that checks if it is null, and if so, automatically initializes itself before returning the value. The "set" method is private to avoid accidentally writing code that could assign a new value to this variable. It does not prohibit modification of the object through its setter methods (coming up), but simply makes it so you can't accidentally write code that could wipe out the calculations we've already done. ContactList is what we call a "wrapper class", which gathers together all the common methods and helps reduce the chance of writing code that could be inconsistent. Also, you can change the wrapper class once, and all other classes that depend on it will continue to work without modifying other parts of code. This is the essence of "object-oriented programming."

 

ContactList is our wrapper class. In it, we make it so it only performs the calculations once. After this, both methods will have a prepared list available to them without checking if the calculations have already been performed. As you can see, by moving the "null checks" and calculations to a single area, we simultaneously avoid excessive if statements, reduce code complexity and code size (overall), and foster code reusability. The amount of time you'll save coding is proportional to the number of times you can reuse the same code.