The Model - PD, UI & SI

szego's picture

There's another long thread running that's spawned some interesting side discussions. I'd like to promote one of these out of there, since it's getting rather confusing and since I think there's a lot of valuable discussion going on I'd hate for it to get lost.

So this post follow on from the comment
Need to clarify the semantics of "the model"
by Rudy.

When we're talking about "the model" we mean the business logic. We always partition an application into layers that include (some of) a User Interface layer (UI), a Problem Domain (PD) or "business logic" layer, a System Interface (SI) layer and a Data Management (DM) layer.

The UI is all about presentation. We use standard techniques like MVC or its variants to ensure these are decoupled, and most importantly there is a one-way dependancy from the UI on to the PD and not the other way around.

The SI layer deals with interfaces to external systems. We use a similar approach to the UI layer to decouple these, which achieves a dependancy from the SI back onto the PD and not the other way around.

The DM layer deals with persistence. These days it's more often a "buy-not-build" situation, as there are plenty of tools out there that can help. I prefer to use some kind of object-relational (OR) mapping technology (e.g. TopLink) here whenever possible, but you might be stuck with other approaches like vanilla JDBC or entity beans in an EJB environment.

The real core of the app is the PD layer. This is where we model the domain - the business we're in. It's the most important piece of the puzzle: if you get it wrong nothing else can save you. If you get it right you can vary the other layers independantly, or even have multiple different types for some of the layers (e.g. several different user interfaces at once).

If we don't specifically state otherwise, when we talk about "the model" we're talking about the PD layer. On an FDD project we will partition out the UI, and if present the SI. Each layer will have its own features list, progress reports, developers, designs, work packages, and codebase. The PD does not depend on anything else, but the UI and SI layers do have a dependancy on the PD. Then each layer is run as a "mini FDD project" - the entire process is performed for each layer.

The milestones described in the process descriptions are best suited to PD and SI layer development - for the UI we will change them to suit the UI technology and design process that's in use. Gavin might also be able to share some experiences deciding on appropriate milestones for UI development. On a similar note Martin has posted a discussion of using FDD for web development over here.

Because of the shape of the dependancies we typically kick off the PD development first. At some point after the initial modelling has been completed the UI interactions designers go to work. When we have a UI design, and the appropriate technology decisions, the UI development can proceed. The UI development sequence is obviously impacted by the PD development - you can't very easily code up the UI for pieces of the PD that aren't done yet. A similar approach is taken with the SI, though in this case the external interfaces and the requirements are usually very well established.

So "the model" we talk about is the PD model. Because of the partitioning there are no presentation details here, nor external system hookups. Depending on the technology chosen, there may be some consideration needed for persistence. This is why I prefer an OR-mapping tool - it's the least intrusive and I don't end up mangling the domain model just to get persistence capabilities.

The UI team will have its own model, that is built with a dependancy on the PD model. Often with UI development a class diagram is one of the less useful design artifacts. Sometimes only framework and support type classes, usually specific to the technology chosen, utilise class diagrams as the best way to express their design. That doesn't mean we don't use them however - just that there's often better ways to express the design.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
szego's picture

Overall Model vs. Domain Model

Back to some of the other comments made:

I suppose this overall domain model is what is meant by people talking about "the model" in this thread?

The model means the PD model. It's not the domain model or the overall model - there's just one model of the business logic.

From process one we start off with mostly shape and little content. Over time we fill in mostly content but little shape change during DBF+BBF iterations. It's all still just the same model - implementation warts and all. Due to the partitioning however there won't be things in here like presentation logic or MVC patterns or external system interface hookups etc. It's purely the business logic.

We use tools like Together/J to keep the code and model in synch throughout the development process. They are the same thing - the code or a class diagram or a sequence diagram are just different visualisations of the same thing - "the design" (though at different levels of detail, and with a different focus). The code is not "an implementaion of" the model - it is "the model". There's no mapping from domain model to implementation model - it's all the same thing.

Does this make sense?

Business Logic versus Application Logic and WorkFlow

Hi Paul, this definitely makes sense.
Thank you for your clarifying responses!



I hope you don't mind, but I have come up with some more questions:

  • I like the idea that the PD layer is independent from other layers. However suppose the PD needs to interact with the SI or the DM layer. Keeping the PD independent from SI/DM can be achieved by providing an interface IService belonging to the PD layer, which is implemented by some 'glueware' that is responsible for coupling the PD layer to the SI layer. The class ServiceImpl implementing this interface IService depends on SI, but the PD layer is unaware of that. The glueware passes the ServiceImpl to the PD layer. I hope I'm making myself clear here. My question is: where is this glueware located in your architecture?
  • Where is the Application Layer, which also could typically be used as glueware connection layers together? Architectures sometimes make a difference between Business Logic and Application Logic. Business Logic (PD) implements business rules, while Application Logic implements e.g. workflow. This allows to reuse business components in different application services. Suppose an application wants to automatically send an email (application) whenever a new sale is made (business). We don't want to implement the sending of the email in the business layer because that is application dependent. You don't use such an application layer, or do you have another solution?
  • What about business processes and workflow, which are typically rather dynamic. At least more dynamic than the individual business transactions, which can be combined in multiple workflows. FDD doesn't seem to say anything about Business Processes or WorkFlow?
  • Another important issue is the separation of a business in multiple domains or multiple components. The Coad-book 'Modeling in Color with UML' e.g. mentions many components depending on each other. I suppose each component can be considered as a single PD. Do you allow these PD's to depend upon each other, or do you use some other technique (like glueware) to make them independent as well?

Please don't hesitate to create seperate threads for these questions, if you feel some issues are best handled individually.



Again, thank you very much for your great help!

Rudy

Jeff De Luca's picture

Separation of Concerns

Regarding your first bullet point - keeping PD and SI separate.

This is an article Paul and I co-authored a loooooong time ago, but never completed or published. It's in good enough shape to answer your question though.

Any application, especially an OO one, should be separated or partitioned into these four layers. User Interface (UI), Problem Domain (PD), Data Management (DM - how objects in the PD are stored and retrieved from a database) and System Interface (SI - how external systems are integrated).

UI | PD | DM | SI

In an OO project, the object model is everything and modelling the problem domain is the foundation of the OO approach itself. The PD is the information asset and thus is the highest risk. Without the correct PD we have nothing. A great UI, a DM solution and all the SI are worthless without the PD. The PD is the embodiment of the business solution in code and the separation of concerns allows for the PD to be modelled and implemented independently of the UI, DM and SI. This is a critical success factor for sustainable and flexible OO systems.

The idea of layers and separation of concerns is not new and the classical example of this is protocol stacks from the networking world such as the OSI stack or IBM's SNA. Here there are a number of layers and at most each layer only knows about those adjacent to it. One layer communicates to another via a well-defined interface. That is, a layer provides a well-defined interface for a layer above it (for example) to make use of.

Each of the four application layers - UI, PD, DM and SI - can vary independently. For example, the UI can vary independently of the PD. That is, we could change the UI and not affect the PD, or we could replace the UI with a different one or even have multiple UIs.

The separation of UI and PD is the most well understood and there are several approaches for this such as MVC (model view controller) and model presenter. The implementation is such that there is a one-way dependency from the UI to the PD. That is, the UI has knowledge of the PD but the PD has no knowledge of the UI. This is how the UI can change without affecting the PD. Thus, we end up with a shape like this.

UI-->| PD | DM | SI

The DM layer we tend not to talk about much anymore as we buy a persistence solution here rather than build our own. Thus, we're really only focusing this article on UI, PD and SI.

UI-->| PD | SI

Now, with the SI we want the same kind of independence from the PD as with the UI. Typically, what happens is is that we think of the SI from a technology standpoint. That is, the nature of the system interface being message based, or RPC based and so on. And thus we think of it in terms of send a message and receive or message, or marshalling and unmarshalling data for a remote call. By thinking of it this way we create a dependency from PD to SI.

UI-->| PD --> | SI

But if we do this then SI can't vary independently of PD. PD has knowledge of the SI and even if only a technology change was made - for example, the way we talk to an external system moves from something like RPC to something like JMS then the PD is affected.

What we want is a one way dependency but in the other direction. A much better way to approach this is to not think of the SI in terms of the underlying technology of the other system interface but by moving up a level and thinking in terms of the PD - of the business.

UI-->| PD |<-- SI (this is what we want)

Take for example an external system interface to a credit card system such as CARDPAC. Instead of thinking in terms of marshalling and unmarshalling for a remote call, we think in terms of what business function (features) are required. That is, we need to determine a credit card balance and to check if the card owner is blacklisted.

We can use this "business interface" to achieve the dependancies we want. We define this interface in the PD layer, and in that interface define the methods to support the business features required.

A class in the SI layer then implements the PD interface. Note that this class is a Java class and the SI layer is a Java layer. It is inside this implementation class in the SI layer that we deal with the actual technology required to access the CARDPAC system. This might be via JMS or might be via JNI to native code or whatever is required.

Now other PD classes can delegate calls to the SI layer through this business interface. Typically we gain access to the implementor via some kind of factory class that knows how to dynamically determine the implementing class at runtime from a configuration setting. See the Java implementation example at the end of this article for details on how this is achieved.

*** need a diagram or something here ***

Many applications these days are to webify existing systems. Thus, there is very little in the PD. However, this is also a terrific example of the value of separating the layers.

Consider a UI that is essentially hardwired direct to an SI (a very common implementation these days). Any change to the backend system affects the web front-end (the UI). Even a thin PD layer, with little more than thin classes such as CreditCard in the example above, gives us wonderful separation of the UI from the SI so that each can vary independently.

Even though many see web apps as replicas of old mainframe style non-OO transactional applications, in fact, a proper OO implementation separating the layers has enormous value and delivers on the OO promise of more flexible and sustainable applications.

But wait, there's more! This separation of concerns also enables some concurrency of effort on DM and SI design and implementation as well as UI - after some PD work has been completed.

And, it washes whiter too. Smiling

Java Implementation Example

Write the Interface

The key to getting a clean separation is an interface in the PD package that describes the required functionality in business terms. Continuing with the credit card example, we'll define an ICreditCardSystem interface. We populate this with methods that represent each of the business operations that we expect to be supported by our system integration layer. Again we've chosen an example mentioned earlier: a way to retrieve the balance of a credit card.

ICreditCardSystem

Write an Implementor

So we have the interface, but someone still has to provide functionality for the business operations we've defined there. We do this with a Java class in an SI package. Note that the PD classes have no direct knowledge of this class, and will only ever see it as something that implements our business interface, ICreditCardSystem.

CreditCardSystemImpl

From the PD classes point of view we don't really care exactly how this class fulfills its responsibilities. It may use some remote call mechanism like RMI, CORBA or XML-RPC, or it might utilise some third-party library that uses a proprietary protocol to communicate with their product. The whole point is that we don't really care and don't need to know.

Build a Factory

So if we don't know about the implementing class directly, how do we get hold of one at runtime? We usually do this via some kind of factory. Most often we use a runtime setting, typically from a properties file, to determine the fully qualified Java class name that we will use as an implementor of our business interface. In this example we have a properties file with an entry like:

com.nebulon.example.pd.ICreditCardSystem=com.nebulon.example.si.CreditCardSystemImpl

So when asked for an object that implements the ICreditCardSystem interface, it looks up the properties file and retrieves a fully qualified Java class name. Using reflection we dynamically instantiate an instance of the class, and check the assertion that this newly created object does in fact implement the interface we are interested in.

getCreditCardSystem()

A simple factory would have some sort of get<InterfaceName>() method for each known external interface, for example a getCreditCardSystem() method that returned an ICreditCardSystem instance. Here is a simple Factory for this example, implemented as a Singleton.

Factory

The getCreditCardSystem method would look something like this:

     1    public ICreditCardSystem getCreditCardSystem()
     2    {
     3        String      name = ICreditCardSystem.class.getName();
     4        Object      impl = null;
     5
     6        try
     7        {
     8            String  fqn = res.getString( name );
     9            Class   cls = Class.forName( fqn );
    10
    11            impl = cls.newInstance();
    12        }
    13        catch ( Exception e )
    14        {
    15            throw new Error( "external system not loaded: " + name
    16                             + ", error: " + e.getMessage() );
    17        }
    18
    19        //  Ensure 'impl' actually implements the interface.
    20        if ( !ICreditCardSystem.class.isAssignableFrom( impl.getClass() ) )
    21        {
    22            throw new Error( "doesn't implement ICreditCardSystem: "
    23                             + impl.getClass().getName() );
    24        }
    25
    26        return ( ICreditCardSystem )impl;
    27    }

A more generic factory might have a single get method that takes the interface class as an argument, but only returned a generic Object value. It could ensure the object was typesafe, but the caller would still have to do a type-cast themselves.

The more generic method would look like this:

     1    public Object getImplementor( Class what )
     2    {
     3        String      name = what.getName();
     4        Object      impl = null;
     5
     6        try
     7        {
     8            String  fqn = res.getString( name );
     9            Class    cls = Class.forName( fqn );
    10
    11            impl = cls.newInstance();
    12        }
    13        catch ( Exception e )
    14        {
    15            throw new Error( "external system not loaded: " + name
    16                             + ", error: " + e.getMessage() );
    17        }
    18
    19        //  Ensure 'impl' actually implements the interface.
    20        if ( !what.isAssignableFrom( impl.getClass() ) )
    21        {
    22            throw new Error( "doesn't implement " + name + ": "
    23                            + impl.getClass().getName() );
    24        }
    25
    26        return impl;
    27    }

But now a caller would have to typecast the result, like this:

 
          sys = ( ICreditCardSystem )factory.getImplementor( ICreditCardSystem.class );
 		  

Despite this ugly typecast of the result, there is some advantage to using this approach. It effectively decouples the factory class from any other PD packages where the various business interfaces might be defined. In this simple example we've placed all the PD classes into a single package, but in any non-trivial application we'd most likely have many different sub-packages defined under PD. If we chose the simpler Factory approach, we'd end up with two-way dependencies between our Factory and these various other PD packages.

In addition, we can easily add new business interfaces to the PD-SI boundary without the need to ever go and update the Factory class. By simply placing a new line in the properties file the Factory will behave correctly.

Delegate to an Implementor

Now we've got all the pieces to the puzzle, we can use them to delegate from any of our PD classes. In this case we might have a simple CreditCard class, that suprisingly wants to be able to retrieve its balance.

CreditCard class

The getBalance method would look something like this:

    public BigDecimal getBalance()
    {
        // Use the factory to create an instance of the si class that implements
        // the ICreditCardSystem interface.

        ICreditCardSystem sys = Factory.getInstance().getCreditCardSystem();

        // Call the getBalance method on the implementing class and return the
        // result to the caller.

        return sys.getBalance( cardNumber );
    }

Here is the getBalance method shown as a sequence diagram:

getBalance()

Summary

Package Dependencies

We've seen how to break the PD-SI dependency into a one-way dependency from SI onto PD. With this implementation we can also swap the implementation of the SI logic without affecting the PD classes by simply changing our properties file.

This is a huge bonus during development. Once the interface is defined, we can easily write a "stub" SI implementation so that unit testing of PD classes can be carried out without any real SI work having been done. Similarly then writing the SI implementation we can write some dummy PD "driver" classes to exercise the SI classes so these can also be tested independently.

It's not uncommon that the PD and SI development happens at a different pace. You might want to put more effort into PD at first to reduce risk. Often you find that although SI might not end up being a huge number of lines of code, the elapsed time to develop this code is greater. Allowing development of each to proceed more independently is a huge benefit, and being able to test each in isolation to some degree before plugging them together generally leads to fewer surprises when you do.

Jeff De Luca and Paul Szego
Jeff De Luca's picture

application layer

regarding your second point - the application layer.

This is beyond FDD but that's ok - it's still an interesting discussion but I just dont want anyone thinking that some of this subjective stuff about arhcitectural implementations is mandated by FDD.

I don't architect systems with a separate layer of this name and function. This whole area is very subjective though and I'm not being prescriptive with this discussion.

Attempts to make business objects, as you call them, to be reusable in different applicaitons are problematic. Particularly, when the means for attempting reuse is to split off the workflow into separate objects. This often tends to relegate the business objects to be much more like data entities.

It's not that common to see a business object truly be reusable across many applications, but I've no doubt there are situations when this is the case. I know many keep talking about this and striving for it, but I've just not seen it happen successfully all that often in practice.

We've come at this reusable attempt many times beofre - even predating objects. When data models first happened we did the same thing. We thought - great - now we could have a standard data model that can be reused. Then we quickly saw that break down into industry data models - e.g. finance, then people realised that even that was too broad and then we saw banking data models vs insurance data models (for example). But then, the Banks realised that even though they were all in Banking, they did things sufficiently differently that the common banking data model was not possible as each Bank customised it too heavily.

And so we've seen the same thing with object models and then with object frameworks and then with reusable components. Despite many attempts by many organisations this just hasn't worked out that well in practice. (where are all the plentiful object frameworks one can buy, or the reusable java beans, or EJBs now...?)

Even something as seemingly enterprise wide as a Customer object is in fact, extremely difficult to make so. In fact, it is extremely difficult (often impossible) to even get a consensus definition on the semantic meaning of Customer within the same company but across multiple applications.

Even making things more like data objects (your business objects with separate objects in another layer for workflow and process) does not help this problem.

Having said all that, Peter Coad did theorise about a plug-in point on a pink moment-interval class type in his color modeling approach. This plug in point allowed for such variations in process. e.g. consider a Sale as a pink moment-interval. The plug-in point is an implementation of the strategy pattern and thus you could have the One-Click Sale vs a Shopping Cart Sale.

In practice, we just never saw this strategy pattern plug-in point coming anywhere close the the "more often than not" requirements of an archetype and so we long ago dropped that plug-in point from the moment-interval archetype.

That doesn't mean you could never do it - just that it wasn't the archetypal case.

Jeff

Relegate the business objects to be data entities

Jeff,

I really like this reply of yours:

Attempts to make business objects, as you call them, to be reusable in different applicaitons are problematic. Particularly, when the means for attempting reuse is to split off the workflow into separate objects. This often tends to relegate the business objects to be much more like data entities.

Any book by any highly reputable author about J2EE design patterns recommends to code 'business logic and business rules' in stateless session beans, using entity beans as 'business objects'. These entity beans shouldn't check much more than data type constraints. I have always thought that this indeed relegates the business objects (domain objects) to data entities, and provides for a functional instead of an object oriented implementation using the session beans.

What is your opinion on this? Is it really necessary to implement business activities in stateless beans, using entity beans as data entities called "business objects"?

I do agree that workflow/application related issues should not be implemented in the business objects; e.g. when a new account is created, an email must be send. We shouldn't implement the sending of an email in the 'createAccount' method, no? This is what I mean by the application layer.

Looking forward to your comments,
Rudy

Jeff De Luca's picture

Architecture involves consideration of many things

Hi Rudy,

when I said that I was speaking in the context of pure modeling. Putting this in the context of J2EE is a whole other set of considerations. J2EE brings a significant and substantial architecture into play of which modeling is just one element. Yes, the implementation of many session bean - entity beans does tend to relegate the entity beans as not much more than data holders. And yes, I don't think that is the best object model. But you can't just extract that one aspect alone and make a decision on it. Surely, you have adopted J2EE in the first place because you need many of the significant architectural features it brings to the table (clustering, failover, and many many more).

Finally, I didn't say that workflow/application issues should not be implemented in the "business objects." I simply said that Coad's pink moment-interval archetype does have a strategy pattern interface that you could use for the "make me one of these" differences you cited (e.g. create an account and create an account with an email). And I said that we have not found that strategy pattern interface to be archetypal and thus have dropped it from the moment-interval archetype. That does not mean that we would partition the need to send an e-mail into a separate object in a separate architectural layer called "the application layer."

Jeff

Jeff De Luca's picture

business process and workflow

regarding your third point - business processes and workflow.

You're right - FDD doesn't say anything about it (explicitly). FDD doesn't say anything explicit about a lot of things. It's not a defined, prescriptive, stereotypical (i.e. unchanging and unvarying) process. It's much more like an agile process framework. It is much more of a system though than a collection of practices (e.g. XP) and it has focused more on the system aspects than many of the discrete practices or techniques. In some cases it says to do a certain practice or technique explicitly such as inspections - but it doesn't tell you how to run one. In other cases it is much more implied - like coding standards.

In working on a better set of FDD processes the expression of certain techniques and practices is one of the things I am contemplating. That is - there are many that I always do, but which ones should be brought into FDD explicitly. Clearly coding standards is one that should, but then there is a whole mini-system to do with inspections and coding standards and how they should be symbiotic. How much of this to bring in explicitly is a complex question and the essence of what makes a good well-bounded process framework.

Jim Highsmith has a slide that quotes Dee Hock (of VISA) that expresses this well. From memory it goes something like...

"Simple, clear, precise rules lead to complex, intelligent behaviour"

"Complex rules lead to simple, stupid behaviour"

Jeff

Jeff De Luca's picture

multiple domains - PD layers

regarding your final point - separation of business in multiple domains or multiple components.

I don't understand what you mean. Can you try asking again? (unless I've answered it below)

For any given project, we only have one PD. e.g. thebank.com.lending.pd.xxxx Using Lending at a Bank as the example, you do have Credit Evaluation as one major area (subject are in FDD-speak) and Approving a Loan as another, and Prospecting and so on.

thebank.com.lending.pd.crediteval.xxxx

thebank.com.lending.pd.approval.xxxx

and so on.

Yes, there are dependencies between these various packages within the PD package and this is business as usual dependency and package management implementation.

Paul Szego or Steve Palmer could explain more about the details of this than I could.

Jeff

szego's picture

PD and Components

Hi Rudy,

as Jeff says we just have the one PD for an application, and using Java as an example will have some package hierarchy within that to break it down further. So to address your question directly:

I suppose each component can be considered as a single PD

the answer really is no. The term 'component' is another one of those heavily overloaded terms, and means different things to different people. The focus here is on architectural concerns, and not so much on "re-usable components" or what the component based development crowd would term "strong components".

About the only place we use that term is in the modelling we talk about "component diagrams". In the context of process one it's simply the object model that we've constructed in support of a domain walkthrough, as it tends to focus on one small, well-defined part of the problem domain.

Here's another place where some of the FDD metrics comes from experience: the 20 minute domain walkthrough. We've found over time that this is a pretty good guideline for how long the walkthrough should take. It imparts about the right amount of domain knowledge that we're comfortable trying to model in groups in one session. Much more than that and we've found it's trying to bite off too large a chunk in one go. Much less and you're spending too much "process overhead" time doing the walkthrough, split into groups, model, present & merge for too little return on this investment (i.e. the pieces are too small and overall progress slows).

We've also found that the object models produced roughly fit on one piece of flip-chart paper using post-it notes and marker pens. Again from experience this is "about right" for what we want to tackle in a model-in-groups iteration. Much more than this and the model is getting too complex, and we've found that to get coverage different groups focus on different parts of that component model and we don't get the full benefit of every group scrutinising the same parts of the model. Much less and the model is so trivial it becomes tedious. Worse than that - rather than stop and say "I'm done" after 5 minutes developers seem to have a tendancy to spend the next 25 minutes over-engineering the hell out of what should have been a simple model :)

NOTE: these are all guidelines.

Of course some walkthroughs end up being trivial. Some are big - when we find this we typically break it into smaller pieces. Sometimes we only find this out once we've started the modelling - if I'm playing the architect or lead modeller role I often notice this while walking around the room seeing how each team is doing - and we usually limit the scope of the first model/present/merge iteration and attack the remainder over successive iterations.

So back to components. After each domain walkthrough we and up with what we called "component diagrams". Periodically (e.g. at the end of each day or two) we will merge all of the component diagrams back into the overall model. The overall model is the PD.

Due to the way the domain has been broken down, the component diagrams tend to be a pretty good starting point for decomposition of the Java package hierarchy (similar techniques for other languages apply). This is one time that good tool support comes in very handy - remember we enter these models into a tool (e.g. Together/J) as we go along (typically once or twice a day during the modelling) and obviously the package hierarchy "emerges" as we progress. Changing the package of an existing class is a pain to do manually.

There is no direct correlation between the walkthroughs, components and the package hierarchy (or the features list - but that's another topic). But it's not suprising that there's some similarities - they are all based on a functional decomposition of the domain. Consider the walkthroughs: we asked our domain expert(s) to "talk about your business, in a series of 20 minute topics". They are usually very good at this - they know their business and people like to talk about where their expertise lies. Initially each component will focus on a subject introduced during a walkthrough. If a walkthrough sheds more light on a previous subject we'll go back and tweak or extend an existing component.

So the "components" that emerge are similar to the "subjects" at the top level of the decomposed feature list. If you've got halfway decent modellers these should be fairly apparent: a small cluster of classes that are relatively tightly coupled relative to other classes outside of that component. Nothing new here - standard stuff.

I don't know how this term started being used with this process - I wasn't around at that point. From observation however it does stand up that these object model fragments do in fact become components in the architectural sense. They are well defined, they are in the same subject-area of the domain and address related ideas or concerns, they are loosely coupled to other components, and internally may be strongly associated.

HTH, Paul.

szego's picture

Rudy also asked: What abo

Rudy also asked:

What about the other classes however, which we for now could call "implementation classes". These are all classes necessary to realize a multi-tier application, including a presentation tier, a business tier, and a data management tier. I'm hereby supposing that the overall domain model classes are not included in this definition of "implementation classes".

You're spot on that we parition the system into these layers. We simply identify classes by the layer they're a part of - so a PD class is a PD class. If something's in the code it's part of the model. We don't say that anything other than a PD class is an implementation class.

I think perhaps the definition of "implementation class" is a bit up in the air. Perhaps some people use it in the context of mapping from a domain model to an implementation model - and that a class that exists in the latter but not the former is considered "an implementation class"? If this is the case then it doesn't apply here, as we only have the one model and not several.

The other way I've heard the term used is more inline with a "utility class". It's where we have functionality that relates more to the gritty details of making software run, and not so much with the business itself. An example might be in a multi-threaded server-side app: there could be a class that helps track User for the current thread, for whom a request is being processed. Or perhaps to provide access to the transactional state, which is managed from the presentation layer in accordance with the interaction design.

When doing DBF, I suppose adding implementation classes is allowed and is not considered as an alarm-bell ringing change to "the model"?

While these things certainly do exist they're usually trivial and have little impact, if any, on the "shape" of the rest of the PD model. Due to the nature of the Features List in FDD we never specifically focus on such classes - they're always built as a side-effect of implementing a feature. So there might be a feature for "determine the current User" that necessitates a helper classes - that's fine.

But it is a new class, and we would stop and check what impact we're having on the shape. It's a trigger that we may have missed something significant. It doesn't automatically mean something is wrong.

szego's picture

shape change

Nuno said:

If you use MVC to implement the UI or other approach that enforces the creation of a layer between the Business Tier and the Interface Tier, then your Business Tier is "safe".

The sequence diagrams of the business tier only become invalid if the business rules change.

Exactly. And this is precisely what the "shape change" trigger is all about: if the the shape changes, then what we're really saying is that we didn't understand the business properly. If that's the case we really need to take a step back and figure out why.

Rudy also asked:

Suppose we want to introduce some design patterns to decouple the presentation tier from the business tier. By doing this, some of the existing design packages - including the sequence diagrams - might not be valid anymore.

Nuno's reply was:

Changes on the UI should not require changes in the business tier, the domain model should not be tightly coupled with the UI

Right. The fact that the UI is decoupled is all that matters. The only way you're going to affect the PD is if you mix presentation logic in with the business logic - and you should NEVER do that. If they're decoupled you can do whatever you like in the UI, and it doesn't affect the PD. You can have multiple different UI's, or you can change it over time - it doesn't affect the PD.

Concerning my following quest

Concerning my following question:

Suppose we want to introduce some design patterns to decouple the presentation tier from the business tier. By doing this, some of the existing design packages - including the sequence diagrams - might not be valid anymore.

I'm trying to understand how work packages are used, and I would like to know what happens when it turns out that some sequence diagrams or former designs have become invalid. My question was not really about decoupling the layers, but about the FDD processes and about what to do when former design packages/documentation become invalid when future changes are made.

Rudy

Jeff De Luca's picture

Answered

Answered in this long thread.