I'm not sure which of these two "patterns" is the best. Currently I use option A (in conjunction with a provider for implementing persistence), but I'm now erring towards B, especially in light of unit tests being able to use the "dependency injection" model.
Option A:
class ClassA
{
ClassA() { }
Save();
static List<ClassA> GetClassAs();
}
Option B:
class ClassA
{
ClassA() { }
Save();
}
class ClassARepository
{
ClassARepository() { }
List<ClassA> GetClassAs();
}
I think what I'm asking is, is it good practice for a class to expose static methods that return collections of instances of itself?
Edit
There seems to be a general consensus that Option B is the better choice. Looks like I have plenty of refactoring ahead :S
Option B is more flexible.
You either divide completely persistence of the object from the data and logic or keep all in the one class. Move 'Save' to 'ClassARepository' or keep 'GetClassAs' inside 'ClassA'.
No, I wouldn't consider that bad practice as a hard and fast rule, though I'm assuming that this is for some kind of instance tracking or resource monitoring? If so, just remember that there will have to be logic behind the scenes to ensure that objects that would otherwise be out of scope don't stick around in your static collection only. I'm not sure which language you're using, but if it's C# you could consider storing it internally as a
List<WeakReference>
.Option B looks better because A mixes two ideas, two kinds of functionality. There's the actual function of the A class and the separate function of managing the collection of A's.
As the application grows it's also likely that you'll need additional functionality in your repository - findById, retrieving subsets, etc.etc. Shoehorning this into the A class will get messy.
And, as you've noted, option B is easier to test.
Option B looks a bit like the ActiveRecord pattern (I Assume the Save method in ClassA will use the ClassARepository ? ), which is good in some situations, but, if you have rather complex domain-model, I wouldn't use the 'ActiveREcord' pattern.
Instead, I would use such a model:
Which means that all persistence related logic is put in the ClassARepository class, and ClassA has also no direct access to the repository.
Generally no - such collections are often singletons, and if they are (as in your example) then the usual reasons for singletons being considered an antipattern, as well as the reasons which static is considered harmful.