none
Project Design Help [Advice Needed ... Please] RRS feed

  • Question

  • First of all, I'm a noob, so be nice! 

     

     

    About 33% way through my project I am beginning to see potential design flaws.  Allow me to attempt describe the structure of my project (my understanding of n-tier design(3 tier)):

     

     

    [Current Structure]

    Presentation Layer:

    1)  Displays the visual components to the end user.

    2)  Creates instances of the Business Logic Layer to retrieve data from the Data Layer

    3)  Data is retrieved from the Business Logic Layer in the form of a DataTable or DataRow

     

    Business Logic Layer:

    1)  Contains various methods to establish connection to SQL database

    2)  Methods include things like

        A)  Update a row

        B)  Insert a row

        C)  Get a row or an entire table

     

    Data Layer:

    1)  SQL Express Database (Multiple tables with relationships)

     

     

    I'm noticing in my Presentation Layer, I have to explicitly state table column names.  This cant be good.   So tonight I am developing 2 classes in my Business Logic Layer.  One class will represent a DataRow.  Where I have public get/set properties for each column of my table.  The second class inherits a generic list of type my first class.  I was planning on using the first class to represent a DataRow, and the second class to represent a DataTable.  However thinking about it some more, I realize that in order to fill the generic list which is my second class, I have to step through each row of a DataTable.  This is going to take more processing time then just simply passing the DataTable to the Presentation Layer.

     

    Simple example of the two classes I have created:

    public class bllMasterItem

    public class bllMasterItemCollection : List<bllMasterItem>

     

    I'm a little lost here.  How is a situation like this accomplished in a professional environment?

     

    Friday, July 11, 2008 4:33 AM

Answers

  • Currently you have implemented an n-tier architecture but there is no logical layering.  You don't have to logically layer your application for it to be n-tier.  As you have noticed there is a dependancy between the tiers.

     

    You could model your domain as POCO object (plain old clr objects) and return this to your user interface. 

     

    For example, if you have a customer table you will have a Customer class that has the appropriate properties.  these will be set by your data access layer. 

     

    You could return generic collections to model groups of customers.  So your method to get all customer may have the following prototype;

     

    Public ICollection<Customer> GetAllCustomers()

     

    Your business layer could hook up the relatioships between objects...customer having addresses for example.

     

    This will remove the dependancy on the column names.  Your solution will be more cohesive and therefore cheaper to maintain.

     

    However, as you noticed this will have an impact on performance.  This is a classic tradeoff - increasing maintanability or manageability may reduce performance (imagine the overhead of writing log files as an example).

     

    As indicated in previous posts, the MS entity framework is worth looking at as are ORM tools and code generators to generate data access layers.

     

    hope this helps.

     

     

     

    Friday, July 11, 2008 10:06 AM
  • Between your business and presentation layer, should be a business layer.

     

    Your data layer would typically perform database specific functionality, so might be functionality to do with the database to which you are connecting, or the tables, and columns, and mapping of these from the database to some domain models.

    With the correct design, using interfaces, you should in theory be able to swap databases, or rename a column in a table, and still leave the business layer and presentation layer as they currently exist.  This is the point of the data layer, it is known as seperation of concerns, and is based around the premise that you seperate out all functionality for a particular "area".  This seperation, through interfaces also allows loosely coupled code to be developed, and so the swapping and changing of data related details may take place without rippling through your code from top to bottom.

     

    Your data layer should be passing back a collection (read "bunch of", not necessarily ICollection, or IList) or domain related objects, so they are in a form that is relevant to the business layer, and business domain.  The data layer as you have it defined, is the database, which isn't a layer at all, it is its own application, the data layer would connect and populate objects from your database.

     

    With your suggestion, using List<>, I would recommend that you define a collection type specifically for your domain model.  The reason being that if you, for example changed the implementation from IList to ICollection, this is a simple process, and nothing is necessarily implied or coupled to the list or collection implementation directly.  If you expose your List<> functionality directly, you will be coupled to the List implementation, which makes your code potentially brittle.

     

    So define:

     

    public interface IMasterItem, and define the public properties and methods for the domain object, then implement by deriving your MasterItem class from it.

     

    The collection would be defined as:

     

    public interface IMasterItemCollection

     

    this could be:

     

    public interface IMasterItemCollection : ICollection<IMasterItem>

     

    or it could be:

     

    public interface IMasterItemCollection : IList<IMasterItem>

     

    or it could be:

     

    public interface IMasterItemCollection

    {

    /// Some implementation relevant to your situation, defining only what you need and nothing more

    }

     

    You would then perform mappings between what you have in your data layer, being read through a datatable, or datareader, or whatever you have available.

     

    Although there is a lot more to it, the Entity Framework, and LINQ enables this situation to be done easily, but I recommend that you understand how to do it properly by hand before starting down the path of these technologies.

     

    I hope this helps you to get started.  Please ask more questions if you are still unsure.

     

    Good luck!

     

    Martin Platt.

     

     

    Monday, July 14, 2008 2:39 AM
  • You should continue to assume they're distributed so stick with WCF. Practically, if you're abs. certain you won't have physical separation then just reference them...but try to go the distributed route.

    Thursday, July 17, 2008 8:20 PM

All replies

  •  

    I think practically you've got two choices. You can remain in the, "I want to display my data tables" mode and just go with direct data-binding. I very much doubt anyone here would advise that for reasons that I'm sure you appreciate. The other is to stop and look at the model. I.e. you need to look at modeling the objects in your domain, rather than starting with the data and reverse engineering the model from it. Then again perhaps you should look at Entity Data Framework too

    Friday, July 11, 2008 6:01 AM
  • I agree with pkr comments.  

    You could have started with entity objects, and map the entity objects to data objects using an ORM tool like NHibernate or Entity Data Framework.  I would recommend you should still do that, if you have time...

    If you dont have time, go ahead and finish it.

     

    Here is an url to an architecture model http://gajakannan.com/netarch.aspx where I have explained this in detail.

    Friday, July 11, 2008 6:24 AM
  • First off, thank you very much for both your responses.  I'm hoping for an optimal "simple" resolution to this situation, although I accept that the answer may not be so easy a task. 

     

    I'll refrain from marking an answer at this time, as I'd like to leave it open for further input ( if further input is an option ). 

     

    If there is a quick fix that will allow for future scalability and redesign according to current architectures, I'd really like to know.  My current project is more or less proof of concept, however it has potential to be used in a live environment, and I would like it to be as easy as possible (relatively speaking of course) to make necessary changes that could meet current design practices.

    Friday, July 11, 2008 7:10 AM
  • Currently you have implemented an n-tier architecture but there is no logical layering.  You don't have to logically layer your application for it to be n-tier.  As you have noticed there is a dependancy between the tiers.

     

    You could model your domain as POCO object (plain old clr objects) and return this to your user interface. 

     

    For example, if you have a customer table you will have a Customer class that has the appropriate properties.  these will be set by your data access layer. 

     

    You could return generic collections to model groups of customers.  So your method to get all customer may have the following prototype;

     

    Public ICollection<Customer> GetAllCustomers()

     

    Your business layer could hook up the relatioships between objects...customer having addresses for example.

     

    This will remove the dependancy on the column names.  Your solution will be more cohesive and therefore cheaper to maintain.

     

    However, as you noticed this will have an impact on performance.  This is a classic tradeoff - increasing maintanability or manageability may reduce performance (imagine the overhead of writing log files as an example).

     

    As indicated in previous posts, the MS entity framework is worth looking at as are ORM tools and code generators to generate data access layers.

     

    hope this helps.

     

     

     

    Friday, July 11, 2008 10:06 AM
  •  

    Like I said in my first sentence, I'm a noob.  But....

     

    As a current work around (until I have a better grasp of perhaps the MS entity framework), I should go ahead and model my database in the form of a class(s), like how I indicated in my first post?  However I see for the collection you are using a generic collection.  I dont know anything about the ICollection, but I will definately look into that, as anything that begins with an I .... scares me right now, and I need to get over it.

     

    How much of a degredation on performace can you estimate I will experience (in terms of a lot, a little, not too bad, etc....)

     

    Example:

     

    I may have 100 user requests (not necessarily concurrent, but lets just say within a very short time .. perhaps 30 to 60 seconds) to return one row via the BLL from my Data Layer.  This row will have a relationship with another table of like perhaps 1000 records.  So with this in mind, my BLL will build the table using SQL (this of course will take time), and then my BLL has to then iterate through the records to create the collection, and then pass that on to my Presentation Layer. 

     

    At the moment my solution has a seperate project for each layer, but it is not distributed (obviously).  In the future I would like to alter it so that it can be distributed.  I have only the slightest clue about how to accomplish this.  Something to do with serialization (which I've done before), remoting, and XML (xml scares me too!) 

     

    With all that in mind, should I go ahead and proceed with just doing the row/class, and table/generic collection to persist my database across the BLL, and PL?

    Saturday, July 12, 2008 3:23 AM
  • Between your business and presentation layer, should be a business layer.

     

    Your data layer would typically perform database specific functionality, so might be functionality to do with the database to which you are connecting, or the tables, and columns, and mapping of these from the database to some domain models.

    With the correct design, using interfaces, you should in theory be able to swap databases, or rename a column in a table, and still leave the business layer and presentation layer as they currently exist.  This is the point of the data layer, it is known as seperation of concerns, and is based around the premise that you seperate out all functionality for a particular "area".  This seperation, through interfaces also allows loosely coupled code to be developed, and so the swapping and changing of data related details may take place without rippling through your code from top to bottom.

     

    Your data layer should be passing back a collection (read "bunch of", not necessarily ICollection, or IList) or domain related objects, so they are in a form that is relevant to the business layer, and business domain.  The data layer as you have it defined, is the database, which isn't a layer at all, it is its own application, the data layer would connect and populate objects from your database.

     

    With your suggestion, using List<>, I would recommend that you define a collection type specifically for your domain model.  The reason being that if you, for example changed the implementation from IList to ICollection, this is a simple process, and nothing is necessarily implied or coupled to the list or collection implementation directly.  If you expose your List<> functionality directly, you will be coupled to the List implementation, which makes your code potentially brittle.

     

    So define:

     

    public interface IMasterItem, and define the public properties and methods for the domain object, then implement by deriving your MasterItem class from it.

     

    The collection would be defined as:

     

    public interface IMasterItemCollection

     

    this could be:

     

    public interface IMasterItemCollection : ICollection<IMasterItem>

     

    or it could be:

     

    public interface IMasterItemCollection : IList<IMasterItem>

     

    or it could be:

     

    public interface IMasterItemCollection

    {

    /// Some implementation relevant to your situation, defining only what you need and nothing more

    }

     

    You would then perform mappings between what you have in your data layer, being read through a datatable, or datareader, or whatever you have available.

     

    Although there is a lot more to it, the Entity Framework, and LINQ enables this situation to be done easily, but I recommend that you understand how to do it properly by hand before starting down the path of these technologies.

     

    I hope this helps you to get started.  Please ask more questions if you are still unsure.

     

    Good luck!

     

    Martin Platt.

     

     

    Monday, July 14, 2008 2:39 AM
  • Yeah, I was wondering what the point of a data access layer was. 

     

    Last night I had a revelation while looking at my business logic layer, and trying to decide how I was going to implement my classes.  This is when the light finally flickered a little and turned on, albeit dimly.  I realized that my business layer would be used to create the objects of data to pass to my presentation layer, and at the same time as it was currently written, I would be accessing the underlying database to create the objects.  If the database were to be changed to oracle, I would be modifying my business logic layer to accomodate that.  That is when I began thinking about seperating the actual access to the database, i.e. reads, writes, updates, etc... and I then at that moment realized..... "Hey wait a minute! Thats the data access layer!"  haha  Thank you very much for confirming that, the light glows a little brighter now.

     

     

    Another thing too ( this is getting weird, I dont know if you are reading my mind or what ) but I was thinking about creating a custom collection, that is to say a class that inherits icollection<masteritem>, now what I notice is this is not exactly what you indicate, but I think its along those lines. 

     

    What I was thinking (but no idea how to implement it yet) was

     

    Public Class MasterItemCollection : ICollection<MasterItem> 

     

    What you show is

    public interface IMasterItemCollection : ICollection<IMasterItem>

     

    Differences I see ( and sorry I'm not trying to turn this into a syntax or OOP help session ) is the key word interface instead of class, and that it appears as if you are thinking about making MasterItem inherit ICollection as well, thus making it generic too.  My head is spinning now, I think the first thing I'll do is find out what interface means, not too mention how a generic representation of my data row <IMasterItem>, and data table <IMasterItemCollection> will function in terms of the scope of my project.

     

    Thank you for your input, and everyone else too!  Please keep it coming, as my short term memory makes me come back here to review what you all say a little too often.

    Monday, July 14, 2008 3:24 AM
  • If you want more information about interfaces a good source is 'programming .net components' published by O'reilly. 

     

    Interfaces are a one of the principles of component oriented design used to decouple an implementation from the service.  This leads to loosely coupled and therefore more flexible and maintainable software.

    Tuesday, July 15, 2008 12:49 PM
  • Tuesday, July 15, 2008 1:06 PM
  • I'm sorry to bother you all again, but I have a stupid question.  How does the PL, BLL, and DAL communicate with each other in a non-distributed application.

     

    For example I have 3 projects in my solution (PL, BLL, and DLL)  In keeping with the advice in this thread, I have created a couple interfaces and classes:interfaces to represent my data from my database.  I assume these interfaces/classes should be in my DAL, so that they can be returned to the BLL, and passed on to the PL.

     

    This would mean project references as follows:

     

    PL would reference BLL, and DAL

    BLL would reference DAL

    DAL has no project references

     

    Is this right? 

     

    If my question shows a complete lack of understanding, please, just tell me to go buy a book, and I'll be on my way.... Smile

     

     

    Thursday, July 17, 2008 10:33 AM
  • You should continue to assume they're distributed so stick with WCF. Practically, if you're abs. certain you won't have physical separation then just reference them...but try to go the distributed route.

    Thursday, July 17, 2008 8:20 PM
  •  pkr2000 wrote:
    You should continue to assume they're distributed so stick with WCF. Practically, if you're abs. certain you won't have physical separation then just reference them...but try to go the distributed route.

     

    I didnt know what WCF was until http://msdn.microsoft.com/en-us/library/ms734712.aspx .  Seems pretty straight forward, and is exactly what I'm looking for.  Thank you very much.

    Thursday, July 17, 2008 10:23 PM