Recently my lead during code review asked me to remove soql query from inside the constructor. I am afraid to ask him the reason as it can be too simple however to me its not making much sense. Please share your thoughts if anyone has encountered any issue or if aware of what possible problem this may cause.
2 Answers
Most of the code I have seen in Apex has a SOQL in the constructor. Well having a SOQL in the constructor is not bad practice unless its very bad and heavy SOQL which increases the page load time.
That being said,
What if you are doing a SOQL in the constructor and then not using that variable/list. In that case it makes sense to postpone that SOQL into a getter. This will improve page loading time. If you just want to use any other method in the class that does not uses the list from SOQL. In that case the constructor SOQL is bit overkill.
Usually, I use lazy loading which would be something like
public MyClass{
public static List<Account> accountList {
public get {
if (accountList == null){
accountList = [SELECT ID FROM Account];
}
return accountList;
}
private set;
}
public MyClass(){
}
public void myMethod(){
}
}
Then when using it:
MyClass mc = new MyClass(); // This wont fire SOQL, thus performance is better.
mc.myMethod(); //Works just fine
List<Account> accList = mc.accountList ; //This will make SOQL when you need it
.
-
2+1. Only other thing I'd mention is that if a
QueryException
(or any exception) gets thrown in the constructor the resulting error message is not very useful. I don't think that makes it necessarily bad practice though. Commented Feb 20, 2019 at 15:13 -
On top of Pranay's excellent explanation, just wanted go highlight a scenario where you actually will need to write a SOQL in a Constructor.
Consider a scenario where you are building a custom VF page for editing a record. In that case, you will need to query the record first and then display the fields accordingly on the VF page. This wouldn't be possible if you did not perform the SOQL in constructor. Excerpt below from the documentation link:
public MyController() {
account = [SELECT Id, Name, Site FROM Account
WHERE Id = :ApexPages.currentPage().getParameters().get('id')];
}
In summary, it depends on the use case that you are trying to solve. If you can delay the instantiation of the objects, then there's no real significance of making a query in constructor, instead use lazy loading approach.
-
Lazy loading would work here? when i refer account variable in VF the getter will be called Commented Feb 20, 2019 at 18:44
-
@user3209853 Not in this scenario. The intent is to decide depending on the use case. If it can be delayed or is needed upfront. Commented Feb 20, 2019 at 19:02