tags:

views:

210

answers:

2

Hi,

So I'm working on making a draft of my program.

This is my plan:

GUI
---
Business Logic
---
Data

You should be able to replace either GUI or the Data layer without issues. Every layer watches itself. So GUI will call methods from Business logic and the methods will always return a status and perhaps some data. How the GUI should respond to the data, should always be decided in the GUI layer. Business logic should have no influence over this. So the relations with GUI and business logic has been solved. I hope you can follow me.

Now for something more concrete. My plan for the data layer, is to use an database. Now, how should Business Logic call methods from the data layer?

Perhaps I should make an enum, that corresponds to different hardcoded SQL queries, which the data layer is aware of?

E.g.

Datalayer.GetResults(Queries.GetAllCustomersIDs);

Queries being an enum.

If this is the right way, what should GetResults return? a string array? but what if the query has multidimensional data?

Should I then have 2 generic methods instead?

Datalayer.GetSingleDimensionResults(SingleDimensionQueries.GetAllCustomersIDs);
Datalayer.GetMultipleDimensionResults(MultiDimensionQueries.GetAllCustomers);

Or should I perhaps have a query for each kind of data request?

Datalayer.GetAllCustomerIDs;
DataLayer.GetAllCustomers;

etc.

+2  A: 

Your Data "Layer" should probably be more than a set of semantic queries and you should encapsulate it in an API, otherwise your Business Logic layer will have to know too much about the implementation of your Data layer. The same reasoning you have used between your GUI and Business Logic layers should apply, and for the same purpose.

Simon
could you show an example of this would look?
CasperT
+5  A: 

In general, what I use to do is:

Data layer:

For data access, I create an Interface, for each object. Each interface lists all the public data access methods for the object in question. To hold the data, I create container types, for each object as well, which can be structs or simple classes only with data. I also rely on language data set, like lists, to hold my data, so I not linked to a particular database type. After that, I create a class that implements the data interfaces, this class has all SQL and access the database, so in case of change in the data storage technology, this is the only class that will be changed.

Business layer:

Does all the logic with data, how to validate, wich methods from the data interfaces should be called and in which order. This class receives and "send" data to the data storage or GUI, using containers (lists for example) where the data types are my containers mentioned above.

GUI:

Calls business logic methods and show / format data presentation. There's no logic here other than call the right methods of the business logic.

Small code example of a container (C#)

    //Interface for Department class data access. DataStorage assembly

    namespace DataStorage
    {
        public interface IDepartmentDS
        {
            void Open();  //Open data conection
            void Close(); //Close data conection
            List<Repositories.Department> List(); //Gets all departments (from data base)
        }
    }


    //This class holds all data regarded a department. There's no logic here. Repositories assembly

    namespace Repositories
    {
        public class Department
        {
            [Browsable(false)]
            public Department()
            {
            }

            [Browsable(false)]
            public Department(String Symbol, String Name)
            {
                this.Symbol = Symbol;
                this.DeptName = Name;
            }

            public Department(Department department)
            {
                this.Symbol = department.Symbol;
                this.DeptName = department.DeptName;
            }

            [Browsable(false)]
            public String Symbol { get; set; }

            public String DeptName { get; set; }
        }
    }


    //This class implements the data manipulation itself, accessing the real database.
    //However the data exchange outside this class is done via repositories classes and 
    //Generics - Lists mainly

    public class DataStorage : IDepartmentDS
    {
       //Here I use to put generic functions to connect with the database, format stored
       //procedure parameters list etc.

       //Implementation of the List method declare in the Department Interface
           List<Repositories.Department> IDepartmentDS.List()
            {
                String query = String.Format("SELECT * FROM {0}", DepartmentTable);
                int rows = 0;
                DataSet ds = ExecSqlCommand(query, out rows); //this method is private to this class

                if (ds == null)
                    return null;

                List<Repositories.Department> list = new List<Repositories.Department>();
                foreach (DataRow row in ds.Tables[0].Rows)
                {
                    list.Add(new Repositories.Department((String)row[DepFN_Symbol], (String)row[DepFN_DepName]));
                    //DepFN_Symbol and the others are just const variables representing the column index
                }

                return list;
            }

    }

public class DepartmentLogic
{
   public DepartmentLogic()
   {
      .....
   }

   public List<Repositories.Department> GetAllDepartments()
   {
      //Here I create an Instance of the DataStorage but using the Department interface
      //so I restrict the access to Department data methods only. It could be a good 
      //idea here to use the factory pattern.

      IDepartmentDS department = (IDepartmentDS) new DataStorage();
      department.Open();

      List<Repositories.Department> departments = department.List();

      department.Close();

      return departments;
   }

}

This Business logic example is, indeed, very simple, just shows how to retrieve data from Storage layer, but as long as you have access to data, you can manipulate it in the way you want. Just a comment here: maybe this solution should be re-thinked if implemented in a very busy server with thousands of requisitions because it can use lots of memory.

For the business logic and also UI point of view, all data are communicated between modules using general purpose containers like Lists. The link point between all those modules are the containers classes so all the classes are more less well decoupled.

UI makes requisitions to the Business logic classes, so it acts like a service provider. Doing in that way, changing the UI will not affect the classes below to it.

The Business logic requests and send data to the Data storage classes using general purpose data, so changing the data base / storage technology should not affect it.

That's the way I use to do and I'm trying to improve it ;)

Andres
Could you give an example where the business logic retrieves some data from the data layer?
CasperT
I understand what you mean by containers and so on. But i am still not sure how it should retrieve the data - which way is the best.
CasperT
I think I am being thrown off by this: " Each interface lists all the public data access methods for the object in question. " I really would appreciate some small examples
CasperT
I put some code fragments that I got from an application that I wrote. I hope it can help
Andres
One more thing. Throw in an example where the business logic calls some methods from the data-layer and retrieves some data.Then I will accept your answer :)
CasperT
Ok :), added! I hope it can clarify the example.
Andres