The Artima Developer Community
Sponsored Link

Weblogs Forum
Layers, Levels, and DIP

17 replies on 2 pages. Most recent reply: Aug 2, 2008 1:20 AM by john smith

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 17 replies on 2 pages [ 1 2 | » ]
Robert C. Martin

Posts: 111
Nickname: unclebob
Registered: Apr, 2003

Layers, Levels, and DIP (View in Weblogs)
Posted: Feb 20, 2004 8:46 AM
Reply to this message Reply
Summary
It is often said that high level layers should depend on lower level layers. However the Dependency Inversion Principle says that high level policy should not depend upon low level details. What's up with that?
Advertisement
As I read through DDD (Domain Driven Design by Eric Evans), I am concerned by the concept of Layers. I know this is an old saw, but I'm beginning to wonder about it.

DDD describes the following layers in this order:

   UI--->App--->Domain--->Infrastructure
DDD also says that "higher" layers should depend on "lower" layers. Indeed, he stresses that when lower layers need to communicate upwards they should use callbacks or Observers. DDD is not the only source for this concept; it's pretty universal.

So what makes UI "higher" than "app"? Isn't it lower because it's a detail? In fact, isn't the highest level layer the domain layer? Certainly it is at the highest level of abstraction.

Perhaps the "highness" of a layer is not related to it's abstraction? Perhaps it's just it's position in the diagram above? If so, what justifies that position? The infrastructure, for example, seems to be at the same level of abstraction as the UI. Both are details. Both are replaceable without changing the nature of the app. Why are they at two different extremes.

Consider the Dependency Inversion Principle. One way to state this principle is that high level policy should not depend on low level detail. Yet the layering principle says that high level layers should depend upon low level layers. Clearly there is a mismatch here. Indeed, in the diagram above *everything* eventually depends upon the infrastructure; which is the the lowest level most detailed module of all. Could we be talking about two different dimensions of level? Could it be that a module is high level in one dimension and low level in another? What are these two dimensions?

These two dimensions are apparent in the work of Steve Mellor and Gregor Kiczales. Both of them have tried to address this problem in different ways. Gregor created the notion of aspects, so that infrastructure could be woven into an application, and could "Depend" on that application instead of the app depending on it. Indeed, AOP is a very interesting mechanism for conforming to DIP. Mellor created "translation" which is really just AOP at a higher level of abstraction. He created the infrastructure independent from the application, and then wrote another program called a translator to bind the two together. In both cases the infrastructure is orthogonal to the rest of the app.

The dilemma of level, and the two solutions, imply that we aren't thinking about this problem correctly. Infrastructure does not seem to be a layer at all. Somehow it is orthogonal to layers. Somehow it is both at a low level and at a high level. It's at a high level because it represents a policy for using the underlying platform. It's at a low level because it's a detail that most of the app wishes it didn't have to know about.

Perhaps the diagram should be drawn like this:

    |UI|--->|APP|--->|DOM|
   \----------------------/
              A
              |
            |INF|
In other words, the UI, APP, and DOM are traditional layers, with the dependencies pointing in the direction of abstraction. (Apparently this means the the greater the abstraction, the lower the level. I still don't understand why that is.) And these layers are somehow independent of the infrastructure, and the infrastructure somehow manages to make itself felt whether through AOP, or Translation, or some other mechanism.

Without AOP, or Translation, we might draw the diagram this way:

    |UI|--->|APP|--->|DOM|
      |       |        |
      V       V        V
   |UIinf| |APPinf| |DOMinf|
   \----------------------/
              A
              |
            |INF|
In other words, each of the layers uses an abstract interface that represents it's infrastructure needs. It does not know what infrastructure it will be using. It simply states it's needs through an abstract interface and expects the infrastructure to implement that interface and supply the required functionality.

Presumably the |INF| module would implement those interfaces with some kind of adapter that would then forward the calls and messages to the infrastructure itself.

Thoughts?


Chris Dailey

Posts: 56
Nickname: mouse
Registered: Dec, 2002

Re: Layers, Levels, and DIP Posted: Feb 20, 2004 3:16 PM
Reply to this message Reply
Bob,

I'm disadvantaged in this discussion, because I haven't studied up much on AOP. However, a thought occurs to me about what you wrote before mentioning AOP.

There is a distinct difference between level of abstraction and level of dependence. But we can probably make a table that relates them. (I hope this turns out.)


| Low | High |
| Dependence | Dependence |
-------------+--------------+---------------+
High | Domain | Business, |
Abstraction | | Application |
-------------+--------------+---------------+
Low | Utility | Implementation|
Abstraction | | |
-------------+--------------+---------------+


Domain classes are those that are very abstract yet are not implementation specific. They are more conceptual pieces.

Business classes are those that depend on the domain, and tell how a business runs. That kind of business classes depends only on the domain. Application classes fit in this box as well, but it depends on Domain and Implementation. It has to instantiate everything and kick off the whole process.

Utility are low level concepts such as Files or Streams or Sockets or Connections or Transactions. Depends on noone -- or only the OS.

Implementation implements Domain and uses Utility to do its business.

So what you and Eric Evans called "Infrastructure" would be called "Utility" and "Implementation" in this model.

I unfortunately don't have time to elaborate on any of these thoughts right now, but I'll look back in a day or so to see if it sparks any ideas with you.

Cheers,
Chris

Rick Kitts

Posts: 48
Nickname: rkitts
Registered: Jan, 2003

Re: Layers, Levels, and DIP Posted: Feb 20, 2004 4:20 PM
Reply to this message Reply
>So what makes UI "higher" than "app"?

(Unrealistic)Anticipation of potential for re-use? Sort of transitive surface area issues? You could put many Apps on the Infrastructure, many UIs on the App. I think this has proven mythical and perhaps you've identified a predjudice that needs to be overcome.

Robert C. Martin

Posts: 111
Nickname: unclebob
Registered: Apr, 2003

Re: Layers, Levels, and DIP Posted: Feb 21, 2004 11:39 AM
Reply to this message Reply
>DIP is really applicable when dealing with layers. If gives a lot
>of flexibility in the design.
>
>The following article describes an application of DIP when layers are
>involved:
>
>http://www.eventhelix.com/RealtimeMantra/Object_Oriented/dependency_inversion_principle.htm
>

Nicely done. This separation of layers using interfaces seems perfectly appropriate. The layers are completely decoupled from each other. None of them know about the others. The concept of "higher" and "lower" layers is removed from the code.

But this brings back the question of the Layers pattern. As described by Evans in DDD "upper" layers know about "lower" layers, but "lower" layers cannot know about "higher" layers. Why has that been so widely accepted? As the paper in the above link shows, the layers can be completely decoupled.

One of the great advances of OO technology was that it allowed us to write software that separated runtime dependencies from source code dependencies. Consider, for example, this statement in C++:

shape->Draw();

The module containing this statement invokes the Draw function. Now let's say that the 'shape' variable happens to point to an instance of the Circle class. At runtime the calling module depends upon Circle::Draw. However, the source code of the calling module knows nothing about Circle. The runtime dependency is different and separate from the source code dependency.

Procedural programming does not provide this capability, unless we use pointers to functions, which are typically considered too dangerous and cumbersome to make frequent use of. Thus, procedural programs tend to have their run time and source code dependencies coupled. If module A calls module B at run time, then the source code of module A depends upon module B.

Modules call functions in other modules in order to invoke the services of those modules. Thus, the calling module is typically at a higher level of abstraction than the called module. This flow of control from higher abstraction to lower abstraction is true, regardless of whether the system is object oriented or not.

Now since runtime couplings flow from high level to low level, and since procedural program couple run time and source code dependencies, then the source code dependency structure of a procedural program will be from higher level to lower level. Indeed, this is exactly what the practice of Structured Design promotes. High level modules invoke lower level modules which, in turn, invoke yet lower level modules. This is unfortunate because it means that in procedural program we cannot easily decouple high level policy modules from low level detail modules.

Fortunately for us, the dependency structure of an object oriented program is not constrained to follow this pattern. The runtime dependency structure can be decoupled from the source code dependency structure. This decoupling is desired because we would like to create high level modules that independent of the lower level details. Thus a good object oriented design will be punctuated with high level modules that *do not* depend upon lower level moduels. Instead, they will depend upon abstract classes or interfaces.

It seems to me that the Layer pattern, as descibed by Evans, and many others, violates this principles. It states that the high level layers *should* depend on lower level layers; thus making the layer structure equivalent to a procedural program.

Edwin Hautus

Posts: 1
Nickname: ehautus
Registered: Jan, 2004

Re: Layers, Levels, and DIP Posted: Feb 22, 2004 3:23 AM
Reply to this message Reply
I blogged some thoughts about this topic:

http://www.jroller.com/page/ehautus/20040222#layering_and_abstraction

Guillaume Taglang

Posts: 18
Nickname: gouyou
Registered: Jul, 2003

Re: Layers, Levels, and DIP Posted: Feb 23, 2004 3:11 AM
Reply to this message Reply
My thinking is that you are forgetting something.

Each of the layer is composed of 2 things in a proper design: interface and implementation. When you have the interface/implementation separation, you have no problem following the Dependency Inversion Principle: each of your layer is not depending on the details of the lower layer, but on its interface and you can replace at will the implementation or details.

I do not get your point about the infrastructure. Your layer structure is looking like something like this:

Upper....
| |
v |
Lower |
| |
v v
Infrastructure

which is perfectly accepted in all the layer documentation (you have to depend only on lower layer). Concerning the DIP, no problem the Upper layer doesn't depend on the details or implementation of the Lower layer, it just happens that the Upper and Lower layer have a common dependency on the infrastructure ...

Clint Shank

Posts: 1
Nickname: clints
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 23, 2004 5:55 AM
Reply to this message Reply
This is very interesting. For years, I've been structuring my Java code based on the Layers pattern. That is, all my code is packaged into ui, controller, domain, data access, etc. packages. Then when I'm coding, I make sure the import statements follow the layers dependencies. So if I'm coding a ui class, this would be okay:

package com.mycompany.ui;
import com.mycompany.controller.*;
import com.mycompany.domain.*;
import com.mycompany.*;

So I've adopted this convention of ensuring that I can go up a package hierarchy or to the right (as in the layers diagram), but never can I go down a package hierarchy or to the left. For example, all these imports would violate the convention:

package com.mycompany.domain;
import com.mycompany.domain.subpackage.*;
import com.mycompany.controller.*;

But now, your comments are making me rethink this. What do you think? How do you structure your code? Do you follow a structuring convention?

Malte Finsterwalder

Posts: 20
Nickname: jufoda
Registered: Aug, 2003

Re: Layers, Levels, and DIP Posted: Feb 23, 2004 8:52 AM
Reply to this message Reply
I think there are certainly several different categorizations for software modules.
It depends on your categorization scheme whether you say a software module is higher, lower or equal compared to another module.

When I talk about layered architecture the categorization usually is: Higher modules execute (call) functionality in lower modules. It's Ok that a higher level module knows about a lower level module but not the other way around.
Action starts at the top and drills down. (Callbacks are the exception.)

Let's take Bob's example:

UI--->App--->Domain--->Infrastructure

The UI is where the action starts: e.g. the user pushes a button. This calles the underlying business logic that in turn calles the data access layer. The business logic never calls the UI. The data access layer never calls the business logic.
Since the UI calls the business logic it needs to know something about the business logic, so in this sense it depends on it. The business logic never calls the UI, so it doesn't need to know about it.
This results in the UI depending on the Application and calling Application functionality but not vice versa.

The infrastructure is indeed a little different. Usually all layers access the infrastructure so the infrastructure is indeed somewhat orthogonal. That's why it's usually not part of the layered architecture categorization. We talk about 2-tier- and 3-tier architectures. The tiers beeing UI, business logic and persistence. Nothing about infrastructure here.

Bob draws up a totally different categorization scheme. It's based on more abstract vs. more concrete.
This different categorization orders modules in a different way, of course. Now the UI is lower (less abstract/more concrete) than the business logic, for example.

The interesting questions to me are:
1) How do these two categorization schemes play together?
2) In what way is it helpfull to think about your application in one or the other categorization?

Let my try a take at these questions:
A good layered architecture encapsulates the business logic against all the "surrounding technology". A good design encapsulates the business logic from the concrete persistence medium as well as from certain concrete parts of the infrastructure. So in a good design, both categorizations are adhered to. The call structure should be from top to bottom (UI->Business Logic->Persistence) not the other way around.
The dependency on implementation technology should be from highes level of abstraction to lower levels: e.g. encapsulate the concrete persistence technology.

Kirk Knoernschild

Posts: 46
Nickname: kirkk
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 23, 2004 7:37 PM
Reply to this message Reply
I've always considered this a separation between the vertical and horizontal elements of an application (which I've called partitions) with dependencies similar to the following (relationships may also exist from Domain UI to Non-Domain Service and Domain Service to Non-Domain BO):
Domain UI           Non-Doman UI
| |
V V
Domain Service --> Non-Domain Service
| |
V V
Domain BO -----> Non-Domain BO


You can pretty easily throw some interfaces on top of the Non-Domain aspects, and we'd have similar resulting structures. I actually talk about this on page 210 of Java Design: Objects, UML, and Process.

What I've found possibly more interesting is the intent behind the structure. It's often cited that the advantage to layering lends you the ability to slap a new UI on top of your application. In practice, however, this is usually flawed because, while structurally the layers are well-defined, behaviorally they are not.

For instance, in the Java world, it's pretty common to find the Domain Service layer returning a bean to the UI. Assuming this bean contains the data required for display, the Domain Service must have known how to build the bean. This knowledge inherently couples the Domain Service to the Domain UI, even though there is no structural relationship. This would be painfully evident if one ever wanted to create a rich client-side UI to replace a browser based UI, which would likely not be consistent in navigation nor display. In such a case, the bean may not have everything necessary for the new UI. So while the intent was there, the approach is flawed. I've found a couple of things that work well here.

First, always create a second UI. It sounds like a lot of work, but a robust test suite can help serve as the second UI if desired.
Second, a builder passed to the Domain Service layer can traverse the Domain Business Objects, and build the beans required by the display that instantiated and passed the concrete builder.

And while I now may have gotten a bit off-topic from the original post, it's been my experience that this is a larger issue that is still not being dealt with very well.

--kirk
www.kirkk.com
www.extensiblejava.com

Patrick J Nolan, Jr

Posts: 1
Nickname: patjnolan
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 23, 2004 7:53 PM
Reply to this message Reply
I found this discussion very interesting.. I am reading Domain Drive Design and Fowler's stuff and had many of the same questions. Perhaps someone can give some feedback on this?: Is it acceptable/preferred to have domain objects ascend the layered architecture?

Let's say, for example a two object domain model is described as Company to many Employee:

// Company domain object
public class Company {
  List employees; // holds Employee objects
}

We have a use case that says a user can select a company and the application will list its employees. The call sequence would look something like this:


Presentation --> Controller --> Service --> DAO
. |
/|\ |
| \|/
| .
\-- <-- Customer (Domain Object) <--- <--- <-

Here, the DAO instantiates the domain object (holding associated employees in the List) and it "bubbles" up to the presentation layer. Is this appropriate or flawed design? I mean, which layer should have the concern of instantiating domain objects (ie concrete subclasses)? I would imagine only one layer should create the concrete instances of domain objects and then return their interfaces to the layer above. In my designs, I have put this concern in the persistence layer. I'd be interested in hearing anyone's thoughts on this.

Thanks,
Patrick J. Nolan, Jr.

Nilesh Pereira

Posts: 1
Nickname: enaiel
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 24, 2004 7:22 AM
Reply to this message Reply
In my mind, UI and App depend on Domain, while Domain doesn't really depend on Insfrastructure.

So my diagram is more like this (if it comes):

+-+-+->Domain
| | | |
UI->App
| | | |
+-+-+->Infrastructure

Does that make any sense? Or am I doing something terribly wrong?

scot mcphee

Posts: 75
Nickname: scotartt
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 24, 2004 3:24 PM
Reply to this message Reply
> So what makes UI "higher" than "app"? Isn't it lower
> because it's a detail? In fact, isn't the highest level
> layer the domain layer? Certainly it is at the highest
> level of abstraction.


Robert, I agree with your conclusions; "Infrastructure" is really everywhere at all layers in an app. Although for some apps you could divide the insfrastructure into layers too (e.g. Struts, Session EJBs, Hibernate).

I always thought however that the concept of "higher" and the reason the UI is thought of as "higher" is simply this sort of reasoning;

The user is God.

God lives up on High.

Therefore things that God touches are "higher", all the way way down to the Hell of Persistence.

Another way to thing of it; think of a car engine. The obvious bits are "higher" i.e. in the cabin with the driver, or just under the bonnet (hood for Americans), where you might fill the engine with oil water and petrol. Anything more complex needs a mechanic who unbolts stuff to get at the "inside" which is generally lower in the car.

Maybe we should think of concentric cirles of "inside" and "outside"? That to me sounds more like the way a lot of systems are modelled? For example in a complex business system that has many different interfaces and gateways to other systems; as you get more "inside" the system or the functional layers it becomes acceptable to interface to other parts of the system which are just "inside" your layer. E.g. it might be acceptable to link together two company internal systems at the EJB level but defined outside parties must come through external interfaces (such as EAI system) that lie just "outside" the inner sanctum of the raw domain layer. Joe Public comes via the web site or telephone, whcih might be seen as "outside" the EAI layer.

Just my $0.02.

Jared Groth

Posts: 1
Nickname: jgroth
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 24, 2004 9:12 PM
Reply to this message Reply
The way I think about this (and I've always thought this was the idea behind DDD) is that, in some sense, the domain classes really are the application. Unfortunately, users can't interact directly with these classes (though the Naked Object framework suggests otherwise). So we have UI classes to deal with the nitty-gritty detail of displaying data to users. We also have the App/Controller classes that "script" the interaction of domain classes in order to accomplish some predefined tasks (e.g., a use case controller).

So the approach UI-->App-->Domain works for me since I see the first two layers as interpreting for the user. And I don't want Domain to know about the UI and App layers because I'd like to believe that my Domain classes could be used with a completely different UI (e.g., a web based interface instead of a rich client) or in a different application (e.g., Employee and Company could be used in a payroll or PO processing application). In other words, I want to isolate the domain classes from the application, because I want them to be reusable. Hence the notion of using callbacks, interfaces, or whatever to make sure the domain classes don't have any dependencies to the app.

Similarly, I want the domain classes to be as free as possible from technical details (e.g., persistence) to ensure that I can change them (new platform, app #2 can't use a db like app #1 does). So it makes sense for the domain to be independant of infrastructure as well.

Just a thought...

Stan James

Posts: 4
Nickname: j3
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 26, 2004 11:33 AM
Reply to this message Reply
Sorry I haven't been through this in detail, so I may be repeating some ideas.

I like the conventional higher layers depending on lower layers for reuse. For example, we have an application server that is used by a web UI, a Swing client UI, and a service API for other systems. UIs depend on the model.

I like DIP for isolating change. We seek to have a stable core system with plug-in product lines. DIP seems to be key to making that work.

I posted a presentation I used to introduce DIP to the team here: http://www.surfscranton.com/architecture/DependencyInversion.htm (I should just post the PDF file because it has a lot of notes, too.) There is a slide that shows hard "uses" dependencies going down for reuse, soft "implements" dependencies going up for robustness. We quickly realized we have to do both at once. For the discussion we drew architectural layering dependencies going down as usual, and the inverted dependencies needed for robust core going right to left.

Colin Froggatt

Posts: 1
Nickname: colin68
Registered: Feb, 2004

Re: Layers, Levels, and DIP Posted: Feb 26, 2004 2:05 PM
Reply to this message Reply
<snip>
The infrastructure is indeed a little different. Usually all layers access the infrastructure so the infrastructure is indeed somewhat orthogonal. That's why it's usually not part of the layered architecture categorization. We talk about 2-tier- and 3-tier architectures. The tiers beeing UI, business logic and persistence. Nothing about infrastructure here.

Bob draws up a totally different categorization scheme. It's based on more abstract vs. more concrete.
This different categorization orders modules in a different way, of course. Now the UI is lower (less abstract/more concrete) than the business logic, for example.
</snip>

I agree with Malte on this and also see infrastructure as orthogonal to the rest of the system. I believe the popular understanding of a layered architecture is based on this. I havn't looked at Bobs work to comment on his scheme.

Alan O'Callaghan describes an alternative take on organising systems which can lead to a layered system in his 'time-ordered coupling' pattern, part of the ADAPTOR pattern language (described here: http://www.argo.be/europlop/Papers/Final/OCallaghan.htm).

It organises components based on rate-of-change (or stability). The more stable components (data model/persistence) reside in the lower layers and the volatile components (UI) in the higher layers.
The resulting system is described thus (his words):

"A system partitioned according to the different change rates of its components localises the effects of change. "Slower-moving" partitions constrain the design of those with faster change rates, resulting in a system which is stable but flexible both to different kinds of change, and to changes with differing frequencies"

cheers, Colin

Flat View: This topic has 17 replies on 2 pages [ 1  2 | » ]
Topic: Metaclasses in Python 3.0 [2 of 2] Previous Topic   Next Topic Topic: Vise - A Testing/Refactoring Tool for Java

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use