1

I'm having trouble figuring out a clean way to implement my layering.

Here are the layers I have (lower layers support upper layers, either through inheritence or composition):

Business Logic Layer (BLL)
Datastore Layer (DSL)
Database Layer (DBL), Web-Service Buffer (WSB)

When a BLL object makes a get request, getRecords(), it in turn asks the DSL to fulfill it.

The DSL then decides on weather to use the local DBL, or to use the WSB (which communicates with a remote web-service front end to a "master" DB).


Option 1 - Composition (BLL has-a DSL, DSL has-a DBL)


My problem is that since the DSL and DBL objects are composed within the BLL, they know nothing of the containing BLL, and so how are they supposed to make specific DB querys that include the BLL fields ?


Option 2 - Inheritence (BLL : DSL, DSL : DBL)


Even if the lower layers now have access to a BLL through public/protected inheritence, the question still remains as to how DSL and DBL are to know exactly which specific query strings to generate. I suppose that the BLL could keep a set of static strings, but then that creates a two-way dependency, which I assume is a really flawed design with horrific consequences.

Note: Each BLL has a corresponding table that it is serialized to / deserialized from.

Note: I do not want to use reflection, and would like to limit the use of generics (unless there is absolutely no other way. I'm using genreics for my WSB, which is working out fine, though my prime concern is with generating the BLL-specific query strings within the DSL and DBL layers).

Note: There are going to be many diverse BLL objects that will be using the DSL and DBL layers, not just one (otherwise this would be trivial).

public class BL1 
{
  private DSL _dsLayer;

  public getRecords() 
  {
    // ...
    _dsLayer.getRecords();
    // ...
  }
}

public class DSL 
{
  private DBL _dbLayer;
  private WSB _wsBuffer;

  public getRecords() 
  {
    if(_dbLayer.getRecords() != null)
    {
      return records;
    }
    else
    {
      return _wsBuffer.getRecords();
    }
  }
}

public class DBL
{
  private string _db = "file.db3";

  public getRecords()
  {
    select ????? - how to know what fields to grab
  }
}

Thank you for taking some time in answering this, it is greatly appreciated.

samus
  • 6,102
  • 6
  • 31
  • 69
  • Good read for this: "Partitioning and Layering Fundamentals" http://www.google.com/url?sa=t&rct=j&q=&esrc=s&frm=1&source=web&cd=4&ved=0CGgQFjAD&url=http%3A%2F%2Fdownload.microsoft.com%2Fdownload%2FB%2F9%2F5%2FB9539E4E-BBCE-4C7C-9624-53EA2A504622%2F01-Article%2520Partitioning%2520and%2520Layering%2520Fundamentals.docx&ei=gKMOUIWbH4aj2QWLsoDwAw&usg=AFQjCNFrgb2wS17feQeLafwTnNtx9Fp0xA – samus Jul 24 '12 at 14:03

3 Answers3

2

You should go with Composition. I don't think Inheritance makes sense because these are completely different type of entities and really one cannot inherit from the other. What fields will they inherit? And who inherits from whom?

The BLL will need to pass the list of 'fields' to get to the DSL. Either as parameters to the DSL methods or in some other way. The DSL methods just receive some list of fields as parameters and work with them. I think that is a feasible solution.

Also, you should create Interfaces at each Layer and program against them instead of using the type itself. So for e.g, in the sample code that you wrote, change DBL and WSB to IDBL and IWSB. This will help you test better and allow for loose coupling in the code.

public class DSL 
{
  private IDBL _dbLayer;
  private IWSB _wsBuffer;
....

}
Punit Vora
  • 5,052
  • 4
  • 35
  • 44
  • Yeah I guess your right about a "field-list" argument being passed to the DSL. For some reason I thought this would create a dependency, but its just a function argument like any other right ? Thanks desigeek. – samus Jul 17 '12 at 15:18
  • Passing arguments is not the reason or source of dependency. The class whose method you will be using will be the dependency for your container class (so DSL is a dependency of BLL etc). To separate that dependency, you should create an interface, derive your dependent class from it, and declare the relevant member of your calling class as an interface instead of the dependent type itself. something like IDBL and IWSB in the answer. This is one of the basic tenets of 'dependency injection' principle. – Punit Vora Jul 17 '12 at 15:31
  • Are you saying to have BLL implement IDBL (BLL : IDBL) ? If so, won't I then have to write specific IDBL method implementations for each BLL object (which I will have quite a few, at least 10) ? – samus Jul 17 '12 at 15:47
  • ... err, never mind the specifics of that last questions, however the concept remains. I only want to write DSL/DBL once, and if interfaces are involved won't I have to implement the interface methods for each type of BLL (which are many) ? – samus Jul 17 '12 at 16:12
  • I think I know what you are saying: `public class DBL : IDBL {...}` `public class DSL { private IDBL _dbl; }` – samus Jul 17 '12 at 16:22
  • Yup. your last comment is what i meant to say. – Punit Vora Jul 17 '12 at 16:26
  • Thanks. After reading http://lostechies.com/jimmybogard/2009/09/03/ddd-repository-implementation-patterns/ , the question I've been trying to ask throughout my last few comments is basically weather I want to implement a **"Generic Repository Interface"** or a **"Generic Method Repository"**. Just need to decide. – samus Jul 17 '12 at 18:13
  • I see now that your suggestion above is a fundamental concept in DDD. I didn't realize its relevance until after seeing the full picture. Thanks, a very good tip that I'm almost certainly going to work in. – samus Jul 17 '12 at 18:35
  • ... Actually, according to Greg Young (http://codebetter.com/gregyoung/2009/01/16/ddd-the-generic-repository/) - _"So the answer here is to still use a generic repository but to use composition instead of inheritance and not expose it to the domain as a contract."_ I will be staying away from interface contracts and utilizing composition to expose functionality to the datastore. – samus Jul 17 '12 at 18:48
  • desigeek: after reading "Partitioning and Layering Fundamentals" from microsoft, I realize what your are suggesting above. Its referred to as "interface composition" in the paper (composition of interfaces, not concrete objects). I will be using this technique, thanks. – samus Jul 24 '12 at 14:13
1

In general, inheritance should be used when you have an 'Is-A' relationship. Since you cannot say BLL 'Is-A' DSL or DSL 'Is-A' DBL, then I would be looking at composition over inheritance. This has the side effect of making testing each logical layer easier because you can stub or mock each dependency.

Typically, in any exposed API, the server side (so DSL in terms of BLL -> DSL), would need to expose objects to do its work. You are right in pointing out that DSL should not know about BLL objects. So the challenge is to write a clean API for the DSL that is exposed to BLL for querying data.

I would suggest looking at both the Repository and Specification patterns from DDD. These help to solve some of the issues that you are bringing up.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
  • Very helpful insight, and I love generalizations, so thanks for the links (I've got Fowler's book too, so I'll definitly be checking out the Repository pattern in there as well). – samus Jul 17 '12 at 15:28
  • Question: When writing an API, are all the methods typically static, or is there usually an instance variable involved (that is, will there be an explicit DSL member in a BLL, or just calls to static DSL API's ? – samus Jul 17 '12 at 15:33
  • instance vs static is not really related, IMHO. Think of all the great .NET APIs that exist in the framework. Many of them require you to make a new instance of the object before using it. Typically, I shy away from statics for composition because it makes things harder to test (because it requires a tighter coupling between the components). As a suggestion, Looking at Dependency Injection might be interesting for you. – Davin Tryon Jul 17 '12 at 22:33
1

Composition. Because of everything that dtryon and desigeek have said and also
because in your case Inheritance looks unnatural + it will make all your
layers tightly coupled and will hardly limit making of any amends to source code.

I believe it could be helpful to take a look at prefer-composition-over-inheritance SO-topic.

Community
  • 1
  • 1
alex.b
  • 4,547
  • 1
  • 31
  • 52