-2

I have been studying Design Patterns and I am looking to implement them into my latest project.

I am working on a Windows Service that regularly checks a database table for a new entry. Depending on the entry found, the service will perform a number of processes.

Possible processes include:

1) Generate report and send email with report attached

2) Run query and log data to another table

3) Send notification email

What design pattern is best suited? I have been considering the Factory Pattern.

My design process so far...

1) Create Interface

2) Create Abstract class which implements the Interface

3) Abstract Methods:

- CheckTable()
- GenerateReport()
- SendEmail()

4) Factory Design Pattern:

- The client(windows service) asks the Factory for a new object (based of the database entry found)
- The factory instantiates this and returns to the client
- The client then calls the relevant methods to send email or run query.

Does this look correct? Or am I making this more difficult than it is?

Or should I be using the Observor Pattern?


UPDATE:

OK. I have taken your advice and looked for the simplest way of doing this.

Is the below correct? I have created an Interface and then a class to implement this Interface.

There could be a number of different reports/emails to generate. Should these be added as new methods in the Interface?

Do I need an Abstract class?

// interface
internal interface IJobs
{
    void SendEmail();
    void PublishData();
    void GenerateTestReport(string userID, DateTime period);
}


// concrete class
public sealed class JobsFactory : IJobs
{
    #region SINGLETON

    private static JobsFactory INSTANCE;

    private JobsFactory() { }

    public static JobsFactory GetInstance()
    {
        if (INSTANCE == null)
        {
            INSTANCE = new JobsFactory();
        }
        return INSTANCE;
    }

    #endregion

    private readonly WorkbookFactory _workbookFactory = WorkbookFactory.GetInstance();

    #region IJobs Members

    public void SendEmail()
    {
        // send email
    }

    public void PublishData()
    {
        // publish data
    }

    public void GenerateTestReport(string userID, DateTime period)
    {
        string reportTestFilePath = this._workbookFactory.BuildTestReportWorkbook(userID, period);
    }

    #endregion
}
  • 17
    Looking at a task and asking, "Hmmm, what design pattern could I use to improve my code?" is a red flag. Unless you already know a pattern and it suggests itself to you, implementing it is usually a mistake. – Kilian Foth Jan 12 '15 at 11:41
  • 1
    @KilianFoth quoting your prior answer, '"I'm trying to do X, which design pattern should I use?" is usually the wrong question to ask...' – gnat Jan 12 '15 at 11:43
  • 1
    these steps are all things that SQL can do with triggers and store proc. IMHO it seems over thought for simple T-SQL. – Franck Jan 12 '15 at 12:33
18

I'll tell you a story. Many years ago, when I was a young, inexperienced programmer and GoF had not long before published their Design Patterns book, and Java was a new language and the only user interface library generally available for it was AWT, and AWT applications all looked ugly as hell, my company decided to switch development from C++ to Java. But AWT was out of the question: our applications were required to look and feel like native Win 32 apps, and you simply couldn't achieve that with AWT back then. So, I was tasked with learning JNI and implementing a framework that would let us build native windows user interfaces using Java.

I had not long before read about Design Patterns, and was eager to use them, so I looked at my project and thought about which ones would fit where. The idea I was most proud of was this: I'd have a native Window object that encapsulated a win32 window handle, but in order to allow the application to attach behaviours to the window, I'd use Chain of Responsibility. This would let applications use existing behaviours and combine them in new ways, and everything would be great.

So I implemented Chain of Responsibility, and it was a bit more complex than just having a single Behaviour object that managed everything, but I wrote a handful of tests using it and everything worked beautifully.

Then we deployed the framework and started to write real applications using it, and you know what? Not once did we ever use the facility to chain multiple behaviours in a single window.

The lesson here is simple: don't start by using the Design Pattern catalogue to shop for extra flexibility in your application. Start by thinking about what flexibility you are really likely to need, and then about how you can implement that flexibility. It might be that a standard pattern is the best way to achieve that. It might be there's a simpler, more direct way. It may even be the case that you have a rigid, well-defined problem that is small enough that you can design the entire solution simply without needing any scope to change behaviour later, in which case anything even approximating a design pattern would likely be overkill.

To borrow a phrase from Kent Beck, "do the simplest thing that could possibly work". If that happens to end up looking like a pattern, that's great. But don't worry if it doesn't.

  • 1
    +1 for fit the solution to the problem rather than looking for solutions you can fit your problem to – Jimmy Hoffa Jan 12 '15 at 19:44
  • 1
    Amen brother. Design patterns and the GoF were a necessary phase that the industry needed to go through. What we all (should have) learned from that is YAGNI. If you coincidentally have some code that happens to match a pattern, yippee skippy, but don't be driving your code toward things you'll never use because someone somewhere likes to throw around the phrase "best practice". "Best" is inextricably linked to context, and attempts to separate it are almost always a sign of a juvenile developer. – Calphool Jan 12 '15 at 19:59
5

I'd just start out using no patterns.

var records = CheckTable();
foreach(var record in records)
{
    GenerateReport(record);
    SendEmail(record);
}

Start simple, not everything needs a pattern. If you start doing a lot of different tasks, or allow tasks to be configurable in the order and the number of tasks run per record, then think about abstracting it out by refactoring.

2

Since you need to do what seems to be polling, you could take a look at the Observer Pattern. This would allow your service to call your methods so that they can take appropriate action.

That being said, as it has been mentioned in the comments, you seem to have design patterns the other way round. The task should lead you to a design pattern. Trying to wrap your requirements around a particular design pattern is not the best way to approach design.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.