class Foo {
abstract doStuff() {}
}
class Bar extends Foo {
doStuff() { ... }
}
class Baz extends Foo {
doStuff() { ... }
}
From a functional perspective doStuff
does exactly the same thing, however if it should be done to bar or baz then the implementation is completely different.
I try to separate data from business logic, so as doStuff
is business logic and not class behavior, it should be outside.
class Foo {...} // accessors inside
class Bar extends Foo {...} // accessors inside
class Baz extends Foo {...} // accessors inside
class Manager {
doStuff(foo) {
if(foo instanceof Bar) {
return this.doBarStuff(foo);
}
if(foo instanceof Baz) {
return this.doBazStuff(foo);
}
throw;
}
doBarStuff(bar) { ... }
doBazStuff(baz) { ... }
}
Usage of instanceof
has always been considered as a bad pattern for me and I always try to use polymorphism instead. However by separating business logic from data, I found myself stuck.
I could use a kind of accessor getType()
and use a switch to avoid the usage of instanceof
, but for me it is nearly the same issue as it seems to not use all polymorphism benefits. At the moment I have only 2 child classes and it should not be extended in the near future. So for now, I prefer to use instanceof
instead of an accessor. People that read the child class will ask "What is it ?" about getType()
because it is not related to data but it is a "flag" used by business logic switch.
By using a trait or composition to write business logic, business logic will be write in different files but just make it more difficult to read IMO.
What would you advise? Is there some other way I have not considered to fix it?
doStuffWithFoo
, I will need to process a collection of Foo so in any case the switch will be done somewhere.