How to handle this design?

How to handle this design?

Old forum URL: forums.lhotka.net/forums/t/7274.aspx


Goran posted on Tuesday, July 14, 2009

Some parts of this question is CSLA specific, some isnt, but if you have any thoughts about this, I am eager to hear them. Application will need a custom class that would read/write application settings (something like Tools-Options in MS Word). I have several sections in secttings, so I will have 1 parent class (ApplicationSettins) that will contain several child classes. Each child class has nothing in common with other child classes. There will be only one child class of each type (no child collections).

My thinking is to keep all settings in one table in database, and to have parent object fetching all data from this table, and passing SafeReader to each child class contructor, which will fill its properties. As far as updating data, I gues this should be handled by parent object, no child should save its data, since that wold need several trips to database server, and if parent does it , then only once. Since this way I am sort of braking the encapsulations, do you think that parent object should also fill data to child classes? Is this a proper way? Or maybe when updating data I should pass Command object to each child, which will add its parameters with its values, and finally the parent class should call Execute method? I have this parent class using singleton pattern at the moment.

And another related thing that is driving me crasy - one of the child classes - FiscalPrinterSettings, will support several models of fiscal printers (grandchildren). Different printers have different methods for sending data to them, so I cannot make this settings unique to all fiscal printers. So in FiscalPrinterSettings, I also have PrinterA class, PrinterB class, etc. And this classes, as you suggest, have methods to do their jobs.

How to handle this properly? I now have PrinterA with all its properties and methods that is referenced in FiscalPrinterSettings class, and I use this class through this settings class. I think I have gone wrong here - when I need to communicate with some Printer, I use this method

ApplicationSettings.FiscalPrinterSettings.PrinterA.SendData(someData).

Any thoughts, advices?

Thanks in advance,
Goran



Vinodonly replied on Wednesday, July 15, 2009

I will just write how i'm managing this in my app to give you idea. if you like, you can follow the same.

1. My local settings i.e. per user settings are not stored in db but in password protected excel file. I'm using commercial library from syncfusion to read and write it.

2. Db which stores global settings is having 2 tables, parent and child

Single values are directly stored in the parent with no record in child.

But if there are multiple values involved then records are there in child with a flag indicating which is the default value..

I'm not using CSLA for storing settings, instead it is a custom object which basically maintains 2 lists.

1. First one with only single values
2. Second one using multiple values.

The code is designed in that way that any settings added in the table will auto come there.. There is however a filtering option also on get records to filter out and get only few recs...

hope this helps..

Goran replied on Wednesday, July 15, 2009

Hello, Vinodonly, thanks for the response. If you dont use CSLA for this, then how do you handle settings mobility? Ex, my settings can be used by UI (WinForms or WebForms), BL, and needs to be stored/retrieved (it doesnt matter if its kept in excell or sql server, I will call it database in general). There can be 3 different locations for this three layers, so you need to make this objects mobile, right?

Also, you didnt mention where you are storing this settings data, unless you are proposing to read this settings when they are needed, which is probably a bad idea, because of the frequent trips to database server. In this case of fiscal printers, where I need to call some methods on them, I will need to query for settings all the time to see what printer type is used.

If we agree that this settings shouldnt be queried accross several layers, then the main problem is design, or where to store this values, should I have 2 classes, one that will be part of settings, and the other should be printer class, that will contain what fiscallsettings class has, and add behavior also? Or...?

Vinodonly replied on Thursday, July 16, 2009

Sorry for my partial reply..

Local settings are stored in excel files only, I have a auto reinstall mechanism in place which uses some Win32 API's. In short, it preserves the excel settings before installing new version..

Global settings are stored in database only as I mentioned in 2 tables. Parent and child..

A custom settings class is having all the base functionality of reading, writing, updating, adding in db and local lists..

In some cases, settings needs to be set by users, those are then created by specialized csla classes as it gives databinding etc..

But all calls from dataportal uses methods of the main settings class to read, write and get values.. Here I'm heavily using the new lambda expression to call methods repeatedly on settings class to acheive the results..



Vinodonly replied on Thursday, July 16, 2009

Further to my previous msg, some more points

1. DB is not hit everytime when u read settings, instead as I mentioned it is cached in custom settings class - similar to roles class of pttracker. If you want to re-read from db then different overloads are given i.e. to read all settings or for a particular module/bo/category...

2. Admin form which can display all settings (not open to all users) is simply displaying these both lists i.e. default values and the multiple value lists..

Here I'm manually doing the databinding instead of CSLA as I want to display lists and update it (unlike the normal properties of a normal BO).

I think we can also change this custom class to CSLA collections to save this databinding effort...

3. Specialized cases where user needs individual fields and properties can be created with flat classes of csla..

which in turn reads/writes through that custom settings class only..

Vinodonly replied on Thursday, July 16, 2009

I missed few more points, pls read all my answers and advs back if still any doubts..

1. You can do the filtering (based on user rights) on cached lists in custom settings class and with one form you can provide CRUD for all type of settings..

That way you don't hv to create individual classes/forms etc..provided if you are ok with this..

2. I'm not using remoting portal but I have kept all the points in my mind.. Custom Settings class is exposed through a static class called utils and this provides other useful functions also, alongwith some extension methods which I have created..

This is in a seperate project called Library.. I will be deploying this dll on the remote machine.. (in case, if I add a app server)

Goran replied on Thursday, July 16, 2009

Hello, Vinodonly, thanks for the response. We should put aside the way settings are handled through UI (like databinding/manual, rights to read/write, filtering etc). My main concern is how to structure all this to fit into the model correctly.

Lets talk about point 2 in your second post. You say you are not using remoting portal and that you will deploy utils dll to the application server (when you add one). This dll is currently deployed on web server (or client machine, if its a WinForms application). You add application server and deploy util.dll on it. How do these two communicate with each other? If they dont, and you are fetching data twice (for each of them), what happens if user changes settings? It will be applied to web server's util object, and it will be saved to database, but what about app server's util object? It will still contain old data.

My original question is how to fit Fiscal settings into the model. Which pattern should I use? You said this:

3. Specialized cases where user needs individual fields and properties can be created with flat classes of csla..  which in turn reads/writes through that custom settings class only

I will ilustrate my example for better understanding (I simplify things by showing only business propeties and methods)

public class AppSettings
{
    public GeneralSettings General { get;set } // contains only read/write properties
    public ViewSettings View { get;set } // contains only read/write properties
    public FiscalPrinterSettings FiscalPrinter { get;set }
    // etc
    public void ReadSettings();
    public void WriteSettings();
}

In settings window (fiscal printer section), user chooses the type of fiscal printer they have, and then adequate settings for this type of printer are displayed to be configured. All printers have several common properties, and some are printer specific. All printers have same methods, which allows me to use their interface when I need to use printer object in the UI to print bills.
So far I have handled this by having references in FiscalPrinterSettings to all types of fiscal printers objects, where only one is active. I have a GetCuurentInstance method that retrieves selected printer (as interface) which I use later for printer tasks. I am searching for a better design way now, since I am rewriting whole application in OO way using CSLA.

// this is how I handled this up to now
public class FiscalPrinterSettings
{
    // internal references to all printer types
    PrinterA printerA;
    PrinterB printerB;
    PrinterC printerC;
}

I hope I have made my problem more clear now. What pattern should I use with FiscalPrinterSettings?

Vinodonly replied on Friday, July 17, 2009

For adding util in remoting portal I haven't thought more of that but here are some of the things

1. Most probably remoting portal side willl only read settings and not write it.. Suppose in rare situation it writes then most probably i will use csla.globalcontext to transfer the data from there.. or might be a flag which tells UI to re-read data..

There is one more thing which I have set in my app to transfer msgs from DataPortal is to use my own custom exceptions. I understand this is not the right way of using exceptions but sometimes some processing is done in dataportal and after processing, some operations are not valid or there is some msg which I want to bring back to UI.

In that case I throw my custom exception which is catched by my Global Error Handler !! and accordingly msg is displayed to user either in a spalsh screen or messagebox etc..

2. Regarding PrinterSettings, Here are my thoughts

(a) You can define a common interface for all types of printers.. that way irrespective of the printer choosed by user you can call methods on the common interface...

(b) for getting the printer object, use lazy loading and generate the object based on the printer choosed.. So in this case you willl have 2 props

(1) current printer which can be a enum or a string

(2) printer object, which will be lazy loaded depending on the printer which is set in current printer...

(3) you can do the same thing for displaying settings i.e. lazy loading or you can create a collection of printer objects and check in that list, if it is already there then u return that object otherwise you can add a new object in the list...

Copyright (c) Marimer LLC