I am working on refactoring quite big, 4 years old, web-based system written in JAVA.
This is typical 3 layered (spring promoted architecture) with UI based on Struts & JSP, Service layer -spring managers accessed by remote EJB 2.1 and DAO layer using Spring LDAP and Hibernate (spring managed of course).
System is used by multiple kind of users: managers, administrators, employees, team leaders, team leader specialist and a few more. About half of methods of each manager/service in the system has big switch statement:
Moreover these kind of switch statements are spread all over the system, i also can find them in jsp or within struts action classes - depending on user type different managers are executed or are executed with different (user type specific) parameters
case manger: dosth();
case team_leader : dosthelse();
case: employee: doEvenSthElse();
It all looks terrible and is very hard to maintain.
According to Fowler's Refactoring book the best way is to replace these switch statements with polymorphisms. Following Fowler's advise i would start by employing "Replace Type Code with Subclass" or "Replace Type Code with Strategy" and then use "Replace Conditional with Polymorphism".
This way i would encapsulate all user-type dependent behavior into single subclass or interface implementation.
The problem i see with this concept is that my interface would be very big, it would contain great number of methods (about 100 methods). Of course the implementations would delegate processing to other managers but still classes could be very big and would use nearly all managers that exist in the system.
The other problems i can think of now, is how to integrate this kind of solution into Spring DI: create/lookup userType bean in servlet filter and then pass it along as parameter to managers (problems with serialization since using remote EJB 2.1 beans ) or maybe let each manager lookup userType bean itself?
The other solution that comes to my mind is to partition user-type dependent behavior in different manner. Instead of creating one GOD class that encapsulate every user-type dependent behavior, create separate manager implementation for each user type. Using Spring AOP with custom TargetSource(dispatching based on thread local set in servletFilter) Spring would route every request to specific (user-type dependent) manager implementation.Adding new user type would require implementing a multiple interfaces.
Does anyone have any other ideas how to cope with such a problem?