views:

93

answers:

4

I am working on a project that is responsible for creating a "job" which is composed of one or more "tasks" which are persisted to a database through a DAL. The job and task columns are composed of values that are set according to business rules.

The class, as it exists now, is getting complicated and unwieldy because the business rules dictate that it needs access to many databases across our system to decide whether a job can be created and/or how it should be set up.

To further complicate things it needs to be necessary to submit a list of jobs and it needs to be callable in a variety of ways (as a referenced assembly, via windows service, or via web service).

Here are some examples of the things it does:

  • Generate a job cost estimate
  • Take in an account and/or user to which assign the job
  • Emit an event for job submission progress tracking
  • Merge in data from an outside, user-defined list (.csv, .xls, ect.)
  • Copy files from a local drive to a network accessible drive (if necessary)

My question is: What are the best practices or design patterns to make this as manageable and simple as possible?

A: 

Given your description of the requirements, there's no real "simple" way to go about this. Its requisite functionality is massive and diverse. My only suggestions are to make the entire thing into a DLL library (or even a set of DLLs), to separate the various frontends so that referencing the assembly need not rely on the Windows service (for instance); and to stick to basic OOP commandments like loose coupling.

Reinderien
The current implementation has a common project that contains a class containing logic for a single job submission as well as a class that handles a list of jobs. Additionally, there are different types of jobs, where each type share most functionality but vary in different ways according to business rules. There is a separate Windows Service project that wraps the common library and is callable via WSE3.
AceJordin
+1  A: 

This type of program can get really messy if not kept clean from the ground up. I myself always try to stick with the basic 3-Tier Application (Presentation, Business, Data). There is a lot of good information out there for building applications in this manner, and it's best to do some demo projects, and read what others have to say about the subject. Here is the MSDN reference.

I myself had to redesign an application that did something very similar. Once I got my Data Layer separated and worked out from everything else my life became a lot easier.

My best advice is take the time to Plan a lot. Use diagrams, flowcharts, etc. etc.. When a program is this complex, I like to have the groundwork for my layers laid out before I ever start writing code.

jsmith
This is definitely an example where it started as a simple implementation of a narrowly defined submission process that has grown to encompass multiple job types and increasingly complicated business rules. It has been redesigned once already and is again becoming unweildy. I agree that it needs another redesign according to your advice.
AceJordin
Also, the existing DAL is clean and works well. The business rules defining the use of each DAL type are where it is becoming complicated.
AceJordin
+2  A: 

Seems like the class needs to be refactored as it would appear to violate the Single Responsibility Principle. I would recommend that each one of the bullet points above have its separate implementation class. In this way you would be implementing the facade pattern , where your main class represents the high level abstraction of what the system is doing.

Steve Ellinger
I agree that that the current implementation violates the Single Responsibility Principle heavily. Creating facades for each aspect of job submission would definitely help.
AceJordin
A: 

Besides recommending to use SOLID and go the extra mile to keep it DRY, I'll suggest to introduce the concept of rules in the system.

By modeling the rules you can switch to a more configurable / flexible approach. You can combine multiple rules to expose different operations that affect the outcome in jobs and the related tasks.

This allows you to have rules that are composed of others. Depending on the scenario you have, that could greatly simplify how you deal with it, since some operations that involve implicit rules that are spread across all those system can be expressed as a combination of simple rules. I'd keep it as simple as possible, but as you extend it you might find the need for different ways to combine the rules, and patterns will emerge on their own.

As for SOLID, I recommend to check the ebook here and try to keep an evolving code approach.

eglasius