At my company, we have a solution composed of a WinForm (multiple per client) and an API (one per client). This solution is deployed on different clients that require the solution to behave differently according to their desires. The same code base must support UI customizations (client logo, buttons visibility) and functionality customizations (calling the same WebMethod with different flags).
Currently we manage this flexibility on the WinForm side by having an Organization
class that contains all these customizations (flags). The API is totally client-agnostic. Thus, the WinForm's methods look like this:
this.Logo = CurrentOrganization.LogoImage;
API.GetProducts(Organization.UsesPagination);
In the past, we had conditional build directives scattered among the code:
#IF CLIENT_A
API.GetProductsWithPagination();
#ELSE
API.GetProducts();
#ENDIF
Today, we have a single zone with those conditional build directives that, according to the build configuration, instantiates the required Organization
class. Afterwards, there are no more IFs, parameter passing.
I'm a bit worried this is not the best design or the most maintainable solution. I studied the State pattern… I guess the Organization
is my strategy object, since it tells other methods how they should behave through flags.
Is there a better way?
- Storing configurations on a DB table? (requires more requests to the API, which costs time)
- Storing configurations on a *.config files? (someone can easily change the app behavior by editing the file)
Best Answer
First thing you should check is how many lines of code a typical
Organization
class implementation has, and how it is structured. If it has less than 100 lines of code, and the class consists mainly of properties providing some flags or data, do not worry. If it has more than 2000, and it contains a lot of business logic, you should consider to split it into smaller pieces, or to generalize some flags or properties. Nevertheless yourOrganization
class can still be a facade to the configuration data.Even if you use a DB table or a configuration file, you will still need an
Organization
object which loads the configuration from the DB table or configuration file into memory to provide those data to the rest of the program. This enables you or an admin or someone else to add new organizations, or to change features of existing organizations without actually changing the code. So use a DB table or a configuration file if you have that requirement - not because you want to achieve a better maintainability.