3 ms·
Re >2. Do no work in the constructor The author doesn't propose a solution here, so I'm worried he's thrown out the baby with the bath water. Yes, it's true th
by dlss 14y ago
Re >2. Do no work in the constructor
The author doesn't propose a solution here, so I'm worried he's thrown out the baby with the bath water. Yes, it's true that you should have no File IO in a constructor when it violates the SRP. At the same time (and as the author notes), it's very convenient to have Foo.fromFile(String path) or similar.
Here's what I think the compromise looks like:
public static OptimizedPage fromFile(String path) throws IOException {
return OptimizedPage.from(path, FileReader.readFile(path));
}
Which seems like having your cake and eating it too.
Or to put it another way: that File IO needs to happen either way -- forcing the caller do write:
OptimizedPage foo = OptimizedPage.from(path, FileReader.readFile(path));
whenever they mean
OptimizedPage foo = OptimizedPage.fromFile(path);
Is a subtle violation of DRY.
- lmm 14y agoSo yes - static factory methods - or, if it gets complex enough, a distinct factory object - are the right place to do work that would otherwise need to be done in the constructor. Use package-private constructors to enforce that people don't bypass them.
- dlss 14y agoThose are factory methods because I think OptimizedPage.fromFile(pathName); reads cleaner than new OptimizedPage(pathName); Do you think there's a real difference (besides readability) for preferring a factory method to a constructor in this context?
- lmm 14y agoAs a library vendor it gives you more flexibility, particularly if you make the method return an interface rather than the concrete type. Also it can make working with frameworks that call a constructor by reflection easier (you probably know if this is happening though). It's certainly worth separating the "inner" (i.e. the one that takes a FileReader) from the "outer" constructor so that you can call the inner one for testing (perhaps with a mock FileReader), but admittedly you can accomplish that equally well with a public constructor that calls a protected constructor. For internal code I doubt it makes a lot of difference - you can always change it if you need it - but I prefer to use static factory methods everywhere for consistency.