9

I'm reading about application layers, and want to use this design in my next project (c#, .Net). Some questions:

  1. Is the separation of layers done through namespaces? Project.BLL.Whatever, Project.DAL.Whatever

  2. Is it more appropriate to separate by layers, then components (Project.BLL.Component1), or by components, then layers (Project.Component1.BLL)

  3. For my DAL, is this layer further organized using different classes? If all database calls are put into a single class, there is no organization. Would it be better to split these up with different classes or namespaces?

  4. Are DAL classes typically static? It seems cumbersome to instantiate a DAL object before calling one of its methods each time.

Any other tips for doing things the correct way with these layers would be appreciated.

sooprise
  • 1,065
  • 2
  • 12
  • 17

2 Answers2

8
  1. Yes. And also assemblies.
  2. I'd separate by layers, then components.
  3. Yes. There are different approaches to this, but I'd have an IDatabaseService (abstracting the various manners in which the database is called -- this can almost be a direct mapping of the ExecuteScalar/ExecuteNonQuery/ExecuteReader), and then various data access classes that partition by type of data. For example, you could have a UserDataAccess class that would have simple CRUD methods that create/modify/delete User objects. Another approach would be to have a User object that has the CRUD built right in.
  4. No. That makes it much harder to unit test. You should use dependency injection to pass in dependencies to the constructor of each data access class (such as an IDatabaseService). You would then pass the data access objects into the business objects, like this:

    BusinessObject businessObject = new BusinessObject(new DataAccessObject(new DatabaseService())); businessObject.PerformOperation();

Each business object may need multiple data access objects. Your GUI code would also use one or more business objects. Some business objects may not need any data access objects but should never use the IDatabaseService directly.

Matthew Rodatus
  • 7,551
  • 1
  • 28
  • 32
  • So businessObject.PerformOperation() would looks something like: DataAccessObject.PerformOperation(), since an instance of DataAccessObject lives in businessObject? – sooprise Jun 10 '11 at 16:17
  • 1
    Also, thanks for the tip about dependency injection. That is a new concept to me, and it seems to make good sense. I'll have to learn more about it :) – sooprise Jun 10 '11 at 16:18
  • @sooprise Right -- your business objects should operate on the data access objects that live as private members. Glad you appreciate the tip about dependency injection. It's a crucial concept for maintainable and testable software design. You are most welcome! – Matthew Rodatus Jun 10 '11 at 16:31
2

For questions 1 and 2 go with Matthew's answers.

I have spent a great deal of time trying to figure out the best way to structure the DAL of desktop applications. And the best way really depends on the needs of the application. In one of my apps I went down the road of having a DA class for each database table, which registered itself with a central (i.e. singleton) DataProvider class and handled the CRUD. Each DA class could then decide whether it wanted to cache all the table data in RAM or not (performance!) and/or whether it needed to have the ability to trigger automatic client updates in other clients running on other computers (think multi-user concurrency). This makes it very easy to add new DAL classes, as all they have to do is conform to the registration interface.

Not every DAL needs this kind of functionality, but I did learn that the approach itself (i.e. singleton data provider and simple DAL classes with static registration) made my life a lot easier when I started adding new classes.

I would definitely not recommend building the CRUD into higher level classes, unless this is a very simple application. The DAL is an abstraction of the data storage. If you decide to change your data storage at some point in the future (even if it is only to use MySQL instead of MS SQL), you will be very thankful for that. Plus: BLL objects should be structured by their business logic relationships. DAL objects are structured by the types of storage containers they represent. The differences can be dramatic.

Do NOT make your DAL classes static. What you gain in coding speed you will lose many times over in testability and flexibility.

wolfgangsz
  • 5,373
  • 1
  • 22
  • 24
  • You are right that the specific design is driven by the needs of the application. However, unless I misunderstand your design, I disagree about the use of singletons. Maybe you could explain your approach more. Why Singletons are Evil: http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx – Matthew Rodatus Jun 10 '11 at 16:35
  • I am sorry, but I disagree on singletons. There are very good reasons to use them, and all the things mentioned in that blog sound like excuses from somebody who doesn't want to apply the necessary discipline to his coding. – wolfgangsz Jun 10 '11 at 19:36
  • A detailed explanation of my approach would fill much more than what I can provide here in comments. Send me your email address and I will reply (wolfgangs at manticoreit dot com) – wolfgangsz Jun 10 '11 at 19:37