Showing posts with label OOD. Show all posts
Showing posts with label OOD. Show all posts

Tuesday, June 15, 2010

About Entities, Aggregates and Data Duplication.

There's been an interesting discussion about Aggregates on the Italian DDD mailing lists. When things become complex, a simple example might just turn too simple. So I came up with this medium-sized one. Hope it won't be too long. Ok, so let's start from our first User Story

User Story #1: Placing an order
As a Customer
I Want to place an order
In order to purchase some goods

The simplest implementation of the story is essentially stateless: every time a customer wants to order something, needs to re-enter the data. In the DDD perspective, the resulting model is based on a single aggregate (we're deliberately ignoring the catalog for now) whose root is the Order class.

DDD order story 1.1.jpg


The stateless nature of the service makes it really easy to implement: a Customer is just a Value Object, created and eventually dropped at needs. Also we took some shortcut: we've chosen to implement Address as a String. Item is sort of natural value object, while LineItem is somewhat in the middle: we can change quantities, while the order is in open state, but we can implement this also using droppable Value Objects, easing the integrity burden for the aggregate root.

Some businesses (like buying train tickets) might just work like this, but our marketing is more inclined to manage customers in a more long-term way, so here are two more user stories.

User Story #2: Returning customer
As a Customer
I Want to retrieve my profile
In order to place more orders

Story #2 breaks our assumption about the aggregate boundaries. If we stick to the aggregate rule-of-thumb, if we want to delete an Order, we probably don't want to delete also the corresponding Customer. So we need a separate aggregate for that. What would happen if we decide to delete a Customer? Should we delete all orders? We don't have enough information to answer that, yet, we'll mark it as an outstanding question for our next meeting with the domain expert. Let's try the model with two aggregates and see how does it perform.





We now have a relationship crossing the aggregate boundary. We have promoted Customer to become the root of the newly created aggregate, so there is no potential integrity violation. Still we have to watch it closely, because this is where problems related to lazy/eager loading will arise. We also added username and password to Customer.

User Story #3: Different shipping address
As a Customer
I Want to specify a valid shipping address
In order to ship to a different destination

Multiple addresses are a call for a separate type to manage Address. We don't have so many responsibilities so far, for this class, except validation (which as Udi Dahan would say, doesn't necessarily belong to the domain layer) but the smell of duplication is probably enough to go for a separate class. We try to keep the model as simple as possible, so we treat Address like a value object.

DDD order story 3.jpg

User Story #4: Editable customer profile
As a Customer
I Want to edit my profile
In order to update it if needed

Story #4 makes explicit what we've been suspecting: Customer needs to be an entity, because it has a nontrivial lifecycle. No revolutions at Domain Model level, but this triggers a question: "What happens if I have an outstanding order and the customer changes its data before the order is dispatched?" This is the type of questions you don't want to answer as software developer. So we walk up the stairs to have a talk with the Domain Expert. We come back with two fresh user stories:

User Story #5: Specify Billing and Shipping address
As a Customer
I Want to specify independent billing and shipping addresses
In order to deliver goods to different locations

This one is relatively easy: just reinforcing our design. We'll now have two references from Order to Address, which are managed by the Customer. We just store a default Address in the Customer aggregate (we could do better) but's ok for now.

DDD order story 5.jpg

Story #6 is a little trickier, it comes from the legal department and tell us what we probably expected.

User Story #6: Track past orders
As a Legal Department
I Want to track orders
In order to in order to manage litigations

The domain expert state it clear: once an order is placed, it can't be changed in any of its parts, be it the content or the Customer. In case of litigation, it must behave exactly like printed paper. But Customer does not, its lifecycle is different from our needs, we'd need a separate class for that. We're lacking fantasy and call it CustomerData.

DDD order story 6.jpg


Everything is looking a lot different from the beginning. The two aggregates are now largely decoupled: we can change or delete an order without affecting the customer or deleting or unregistering a customer without losing tracks of its past orders. On the other hand we have explicit duplication here. Customer and CustomerData look so similar we're feeling guilty. Did we violate DRY principle? At first look the data is the same, but if we think about behavior, or class lifecycle, Customer and CustomerData are clearly two different beasts. But more often than not, when the starting point is the data model, instead of the domain model we end up thinking that's the same data, hence the same class. I bet experienced data modelers do not fall into these pitfalls as well, but I've seen these problems recurring quite often.

Once we accept that little bit of data duplication we have a system which is a lot easier to evolve and maintain, with aggregate roots as integrity enforcers within their boundaries, and agnostic about the rest.

To add some salt, don't forget aggregates are also building blocks of distributed systems: suppose we'll need to send orders to a remote system. Sending just the single aggregate and the referenced value objects is probably the cleanest way.

Monday, June 29, 2009

So ...what exactly is a context? - Part 1

One of the premises of Strategic Domain Driven Design is that in every non-trivial application there will be multiple models at play. This may sound controversial to some, but since a model is a representation of a portion of the problem domain aimed to serve a specific use, the need of multiple models promptly arises as our application grows in size and/or complexity.

The Ubiquitous Language plays many roles in DDD, among others it may be considered an integrity check for any model in play assuring that every role involved in software development, from domain experts to developers, shares the same language and agrees on the specific meaning of every term which is part of the ubiquitous language.

The Ubiquitous Language should be the only language used to express a model. Everybody in the team should be able to agree on every specific term without ambiguities.

Code is the primary expression of the model, other artifacts might be necessary along the way to capture requirements or portions of the design, but the only artifact that will be constantly in sync with the application behavior is code itself. Ensuring that every term is precisely defined and that is consistently used in every representation of the model greatly helps ensuring integrity of our application. Model integrity comes at a (reasonable) price: the model cannot be extended indefinitely, but can be shared, coherent and acknowledged only within a given Context.

So, ...what exactly is a context?
In Domain Driven Design, a Context is defined as
“The setting in which a word or a statement appears that determines its meaning”
which might sound rather ...vague, at first read. But I’ve learnt that Eric Evans always chooses carefully each word, especially in the key sentences. So the definition above describes exactly what a context is (at least in the Domain Driven Design context). This definition says nothing about the size, shape or other characteristics of a context, so they are likely to be consequences of the link between the word or the statement and the meaning.

But this definition calls for examples, here is a trivial one. The word Account has a very precise meaning in the banking context, and in a typical application, we would probably model it with a balance and an accountNumber attribute, and so on. But in the context of Web Applications, an Account is closely related to credentials, such as username, password, and so on, and we would tend to model it in a very different way.

Trying to force the two definition within a single class might result in awkward code, whose conceptual integrity has been undermined by the attempt to fulfill two distinct models within the same class. Admitting that the same term might be referred to two distinct concepts is crucial for model integrity.

Making the contexts explicit, we are making both models clearer and unambiguous.

The term Account does not have a single non ambiguous meaning, but in a given context the meaning is well defined.

Ok, this first example might be too trivial: the term Account refers to two different concepts, and simply calling them BankingAccount and LoginAccount might have solved the problem. A more subtle distinction might arise when the concepts is the same but but used in different ways, thus leading to different models.

Let’s suppose we’re working with an application managing payments. We’ll probably use this application to manage our Banking Accounts, keeping track of current balance and past operations. The model for our Banking Account might be a BankingAccount class like the one below.



Some PFM apps allow us to manage also payments, keeping a Payee Registry. In this scenario, a Payee is normally associated with one or more Banking Account, but in this case we won’t know anything of the internals nor we can issue any operation on those accounts. Does it make sense to model the Payee account with the BankingAccount class we’ve just defined?


Well... it does sound reasonable: it’s the same concept, I mean, in the real world our account and the payee’s one might even be in the same physical bank. Still, it doesn’t feel completely right: we are not supposed to issue any operation on the payee Banking Account, or to track anything on that. Even worse: doing so would probably be a bad mistake within our application.

In this case, we’re using the same concept in different ways, and this will lead us to different models. Even if the class is already defined in the application, a different context calls for a different model.

Again, name clashes might be solved in different ways at the code level, you can effectively partition the system by adding meaningful prefixes to the classes, or using packages, or in some other way. What matters now is that there are ambiguities, and a term can be effectively defined only within a given space.

So, a Context is a “space” where a given concept is precisely defined without ambiguities, so that it can be safely used in the Ubiquitous Language. If the same concept appears different times with different meanings within an application, we’re probably heading towards multiple Bounded Contexts within the same application.

In Domain Driven Design, a model is intended to serve a specific use, and nontrivial applications often tend to be used in different ways: trying to accommodate every use within a single model is a meaningless effort. It will end up corrupting your model with ill-defined or ambiguous term making the model you developed within a context less valuable. Contexts cannot be expanded indefinitely: Context Boundaries are needed to define which concepts are in and which ones are out, and to ensure conceptual integrity to the model within the context.

Tuesday, November 20, 2007

Is Domain Modeling a “liberal” activity?

This post might sound quite stupid, but I guess this is nothing new… There's been a long debate going on between two parties: those who prefer modeling a system starting from an Object Oriented domain model, and those who prefer starting from a Data Model. I am not talking about legacy systems where this choice is somehow context-driven, I am talking about the rosy scenario: just starting from scratch. My personal style is to never-ever start modeling from the data. I did it, when I was younger, and was developing a MSAccess VBA application. But that's it. In a OO system an Object is a richer entity than a Table: there's behavior that comes into play and I think that the table is sort of a projection of the domain model. To be completely honest, I have to admit that I am far more familiar with UML and Java than with ER diagrams or SQL, but that's not the main reason for me to do that.


I started to suspect that there is something more deeply rooted here. Ok, we can't really classify UML or ER modeling as a "primal instinct" – although some graffitis might be classified as "Cro-Magnon UML profile" – but peers tend to choose one way or another one "by heart" unless when constrained by the tools in use. Getting to a precise, DDD-like, domain model is a complex task, which involves a deep understanding of the real domain, that can be achieved through empathic discussions with domain experts and users. The goal is to understand a different culture, and the way is to respect it. Doesn't it sound a little bit like "make love not war"? From the data-driven guys point of view, this sounds a lot like "he had a difficult childhood" or "we've got to consider the environment he's been growing in" which results in a big loss of time. The domain is just another word for the data model, which is made up by data and constraints, all the rest is "OO-hippy stuff".


I assure you I was sober, when I thought this. I still think this is fairly stupid, but it fits a lot of my collegues… ;-)


Friday, August 10, 2007

So …what is lock in anyway?

When designing an application architecture, one of the things to consider is how to deal with lock-in on third party components. The problem is generally multi-faced (a component might be freely available as open source, or being tied to a license fee) and is generally managed on a risk analysis basis. It can also be tied to large scale aspects such has hardware choices, Operative systems etc. I'll focus here on choosing 3rd party libraries and components for a generic enterprise application (thinking of JEE, but not necessarily only of it). On the practical side this is managed by taking care that the component substitution cost is kept as low as possible. Typical approaches were to intercept and wrap dependencies, with a proxy or an adapter class: no direct access to the 3rd party component is allowed, access to the provided service is available only via the adapter class. In a J2EE context looked like everybody was concerned about Log4J, so the logger wrapper became the architect-level counterpart of the String-manipulation class that every developer felt obliged to write at a certain point of his career.


Technically speaking, you want to reduce coupling between the caller and the provider of a given service, so you extract a more or less generic interface from the service, and provide a (usually brainless) adapter to the 3rd party component. This way you achieve compile time decoupling from the component, at the price of a small increase in complexity (a bit in the code, a little more in documentation, guidelines and control). This price is generally proportional to the complexity of the used portion of the component API (which is one of the reasons why everybody wrapped Log4J…).


The point is that this effort is not really worth a lot of times. For basically two reasons:

  1. You are trading a certain cost now for a possible one in the future (ok, you've done risk analysis on the subject, but… you've got the point.)
  2. You are probably overestimating substitution cost. Ok, I am telling you but I am thinking me, 'cause I know I did… Common refactoring techniques, enhanced IDE support, or even a trivial search and replace capability make this type of code-level change really faster. Developers are generally worried about the number of occurrences of a given required change more than the diversity of the single ones.

What's left out, is more subtle effects of lock in… which results in way of organizing the surrounding components, or in the way to structure the application. In those cases, you can still enhance the capability of your adapter, providing an higher level of service abstraction, but as before you end up paying more at the early stages for a possible risk that could be better mitigated some other way.


Sunday, June 17, 2007

Things they wouldn't teach you of in college - Part 2

In my previous post, I focused on some of the scope differences between software project assignment in the university, and real world projects, Pointing out that there is no maintenance phase. Well, it ca be if you fail the exam and have to evolve your personal assignment, ....but don't take it as an advice.

You are not alone
Well, time is not the greatest scope limitation you have to cross: being in a team can be far more challenging. One of the first thing you'll have to learn is sharing your code with your team, a practice which involves knowledge of SCM tools mechanics (first encounter with a CVS, Subversion or VSS is often a sort of initiation ceremony) and of the group mechanics as well. Something like "who breaks the build takes the blame" or "the last one to commit gets the conflict", but it's just the fact that the team as a whole carrying on the burden of the whole development. So you need coordination, and you need to agree with your teammates on the borders of your own activity.

Sharing the code also shows the symptoms of the "it works here!" syndrome, making it clear that you can't rely on your IDE (or on your memory) anymore, but you need more specific tools such as Ant or Maven to carry on the build process. The notion of repeatability, platform independence, environments and so on (have you ever heard the term "production environment" while at the university? I didn't).

A more subtle question is related to the notion of good code. Writing code just for yourself is close being an onanistic practice: good code is something somebody else finds useful. Which means that:
  1. it works
  2. easily
  3. understandably
Code must work. This might sound trivial, but the point is that code should do what is expected to do. Expectations, unfortunately, could be quite non deterministic if left alone. So you gotta get a grip on what people expects your software to do, and to the average developer's expectation, which leads basically to one word (and one adjective): good documentation.

Documentation can make a lot on ease of use, but doesn't address point 2 completely. Software must be easy to use: doesn't matter if steps from 1 to 17 are thoroughly documented in MyFabulousPieceOfSoftware.howto, if you can achieve the same result in 3 steps, or one. The two things come together: as Vincent Massol points out in an old post about documentation driven development, documentation could be a good test for code and an inspiration for refactoring. If documenting takes too much it's probably because interfaces are far too complicated, or are not placed at the right level of abstraction. It's too easy to mess with interfaces and method signatures when we design both the client and the server class, for example 'cause we are stuck in the mud doing it, but we forget that we don't want classes that call our methods to be stuck in the same complexity that we are.

Understandability of the code refers to the internal mechanics of our systems. And to the beauty of the design. This is a tough lesson: a clean model is potentially useless if nobody else can understand it. It will lead to a cathedral in the desert, or - worse - to the code equivalent of a ghost town. Even if you are the best OO designer around, you can't write code that nobody else can maintain. Elegance in software can have dreadful effects, if nobody but you can appreciate it. Don't get me wrong, clean elegant software it's most of the time better than spaghetti code, but in a team, design elegance must stabilize on a level that can be reachable by a large enough number of teammates. To achieve this you can lower down your expectations, or raise team modeling skills. I tend to favor the second option as much as I can.

Sunday, October 15, 2006

Plea of a Together Orphan


Despite all the criticism surrounding it at JAOO, I am still working with UML sometimes (not that often, I am currently stuck between Excel, MsProject and – if I am lucky – PowerPoint). When asked about which UML tool to use, I used to answer “Together is the best choice, if you can afford it”. But in the last couple of years I simply tried to evade the answer.
In the recent past, Together proved itself the best for mainly 3 reasons:
  1. Full roundtrip – despite some “not pure UML” tricks roundtrip really worked, so you could really keep in sync the model and the implementation code. You needed an OOP aware modeller to get all the benefits from it, but that’s what I used to be. Rose’s reverse engineering procedure really seemed terrible compared to this.

  2. Code inspection features – the audit section was pretty interesting and made together a great tool for inspecting an unknown big project. As a consultant I used it proficiently every time I had to explore somebody else’s code (I am not a zealot in applying all of the rules, but you get quite a good outlook of the coding practices, or malpractices, the team used to adopt) in a CSI fashion.

  3. Keyboard shortcuts – after a while, it really took me seconds to come out with a small domain model, almost without using the mouse. Adding classes, attributes, methods and interfaces was all done via keystrokes. Given that the classes’ source code was actually created at the same time, creating domain classes was faster than with an IDE. I ended up using it as a whiteboard, while discussing the model with the colleagues, cause it was faster than the whiteboard.
Clearly there were things that you couldn’t really do, even if they were available, like designing a GUI (Swing or Web), debugging, and so on. There were also a lot of annoying small bugs in generating PDF documentation, cutting and pasting images and so on.

Standing the test of time
Unfortunately, things never remain the same – panta rei – so did CASE tools as well. Well, Rose didn’t change that much in a few years, showing the same inconsistencies in the user interfaces over and over again. Together, meanwhile, blew it completely. They started a new version from scratch on the Eclipse platform. This was not a bad idea per se, given the weight of the original user interface, but they dropped all the keyboard shortcuts, and even if the GUI looks a bit nicer, it takes more and more time to come up with a model, cause you’re always selecting-dragging-dropping, exactly the things that made a lot of developers hate CASE tools in first place. Auditing tools are not such an advantage anymore, when you can include Checkstyle or PMD checks both in the IDE and in the build script, so you end up only with the roundtrip… but at the same price (

The only tool that really took modellers’ productivity seriously so far is Magic Draw UML, which added some nice features to the user interface that actually made drawing a model pretty faster. Still I can’t help myself… I don’t like it, it looks like a toy to me. It’s just a look and feel stuff… The guys at Visual Paradigm tried to replicate the solution, but they got it from the wrong side, and everything there looks counterintuitive, but shiny (they have plenty of colours and gradients, I guess it’s UML in Colors 2.0). Sparx’s Enterprise Architect looks promising, with an interesting price, but it’s not yet what I would like to have.

Back to basics
Given the new landscape, I’ll have to find another tool… I don’t need (and honestly I hate it) any code generation tool. I need only a fast modelling tool, so I am switching back to the whiteboard, and I’ll be using a camera to take pictures of it. Hope it’ll be readable.

Tags: , ,

Saturday, September 23, 2006

The Flawed Interface Principle - Part 2


After re-reading my last post, I felt quite disappointed: the main point could have been squeezed up in
  1. the more you add stuff to a system, the more you’re likely to bring mess

  2. if you do things by yourself you’re probably getting a better result (but in more time)

  3. interfaces are dangerous.
Ok, point number one, is right, but really sounds too obvious to deserve a post (I'll never win a Nobel with that...). We’ll get on it later.

Point number two is simply dangerous: you simply don’t start a project developing everything from scratch, but start choosing the available components on the market (let’s say… JBoss, Hibernate, Log4J etc.) No way I am telling that you should re-invent everything from scratch! If time is a constraint (and in software development always is) then the better trade off is somewhere else, remember that we moved from a two-minutes micro waved junk food to an 6/8 hours preparation delicacy. Moreover, there is normally no reuse purpose in cooking. While reusable components are the keys to successful projects.

Point three. The real meaning is that interfaces are tricky. In OOP theory, an interface is just a substitution point. As a client class, I declare the need of an object instance able to perform certain operations, namely the public methods of the interface. I can’t make no assumptions about the implementing class, I just expect that somebody (a factory method or the classloader) will provide the needed runtime implementation. What I don’t know is just what’s behind the interface. Which is both powerful and dangerous.

What lies behind
In complex systems, the value of interfaces is their ability to simplify the overall picture. A complex subsystem can be masked by an elegant Façade allowing designers to ignore implementation details. I’ll make another example with a pretty simple interface: the electricity plug on your wall. It’s a pretty simple interface: 3 holes, 220V, 50Hz. Every electronic device can work everywhere (at least in one single country). The plug mask the whole complexity that lies behind so you can happily ignore about tri-phase cables, power plants, and so on. Unless they start building a nuclear power plant near your home, or stocking plutonium in your garden…
We got closer to the point. Complexity is still there. Interfaces make it more manageable, by allowing us to ignore details, not to delete them.

Crossing competence boundaries
While developing complex J2EE applications, a common problem to face is a version clash between (indirectly) required libraries. Xerces is a common suspect in such circumstances, cause it’s often referenced by the application server, the application itself and one or more used libraries often use it as well. Normally the solution is nontrivial and has to do with fine tuning of the application server classloading mechanism. Still you need an expert J2EE architect to drill and solve the problem. Sometimes is not so easy to find a good one, but it’s a well defined professional profile.

Things are not that easy when you start crossing competence boundaries. One of the first borders is the Java-SQL. How many applications have you seen that could be told to be optimized both on DB and Java performances?

If you start adding more layers, like running on a virtual environment instead of a real one, such as VMWare. How many details are you missing in the meanwhile?

Problem determination in Babylon
Here we go. We built our beautiful tower, by putting freely available components together. The tower is high and majestic. Then we have a problem. If the problem is in the glue we used to put the things together, it’s an easy task. After all gluing is all we did. If the problem is in one brick, we have to determine where the problem is (which can start to be a nontrivial task), and update, refactor or substitute the faulty component.
If the problem is in the interaction between two or more components, or in what happens behind the scenes (or the public interfaces) then you’re in deeper trouble: cause you need cross concerns competence and you probably won’t have it. And it’s not easy to be found as well.

Tags: , ,

Saturday, September 16, 2006

Food processing chain and The Flawed Interface Principle


While I was discussing with a friend, preparing a speech about complex system management, I realized that there is a close analogy between food processing industry (and its worst effects) and what usually happens on large complex systems.

Grandma’s good old taste
Suppose you want to make some pasta, tagliatelle Bolognese for example, that you used to like in your childhood (ok, it’s getting pretty clear that this post it’s gonna get targeted to Italian geeks that like to cook… a pretty narrow audience niche…).
You can go to the supermarket and buy the ingredients you need, but then you have to make a choice
  1. buy the “all-in-one” package that you just have to warm up (microwave or frying pan)

  2. buy the pasta and buy the sauce, cook the pasta and then mix it by yourself
…
  • buy the eggs, the floor, the meat and the vegetables and actually make the pasta and the sauce
If you are a good enough cooker, you’ll notice that there’s a close connection between how much time you spend in cooking, and the final result.

Still, even if good, the result still doesn’t taste as good as your grandma’s. Next step is forgetting about the supermarket and buy the staff straight from the farmer. Suddenly eggs start to taste differently and so do the vegetables.

Ok, in the end you have to surrender: you can’t beat your grandma in cooking. It’s just an axiom. But sometimes you can get close. The interesting thing is that once you managed to get that close to the taste of your childhood you can’t even think about eating option number one at the top of page. And even if the label (and the pictures) tries to tell you that it’s the same thing, you just know it’s a completely different stuff from what you really want.

Question is: “How could it get that far?”
The answer is pretty simple: by systematically doing a substitution of the original ingredient with its industrial equivalent. And here is where we get back to software.

The Flawed Interface Principle
The keyword is “substitution”, how could you possibly do that (remember the oop substitution principle…)? Because every ingredient’s decoy looks or smells (almost) like the original, and if you change only one ingredient the difference could be small enough to go unnoticed.
Put in another way, food decoys implement just part of the original ingredients’ interface, generally the look (maybe with the help of some good photographer), but not others, less documented or testable, such as smell, for example.


If you start reading labels of pre-prepared foods, you realize also that they have more than twice the ingredients needed of the original recipe. Stabilizers, preservatives, enhances, colourings (whose role is just to satisfy the visual interface), and so on.

The point is that nontrivial interfaces are seldom complete. Even if they can be thoroughly documented, there is probably nobody checking if the whole system can fit together (at least I’ve never seen it happening in the software development industry). Every component you add in a system has a burden of internal complexity (libraries, for example, but not only) that can’t be completely masked by encapsulation, but only 99%.
The net result in complex software systems is that if you consider that every implemented interface between components has a certain probability to be flawed, you come to the conclusion that every time you add (or more fashionably plug-in) some component in a complex system, you are getting one step closer to the whole system collapse.


Tags: ,

Tuesday, August 08, 2006

RAD development and domain modeling


Java web programming suffered bad development performances in the last years, mainly related to the complexity of the presentation layer. As a coordinator for J2EE learning classes, I found often embarrassing to define a competence stack for the web programmers which included Java, J2EE concepts such as Servlets and JSPs, a bit of XML and HTML (and HTTP of course) some JavaScript and a MVC (so some Design Pattern concepts got in as well) framework, normally Struts. Given that in another language, such as Delphi or Visual Basic, programming for the presentation layer is made ultra-simple, this pile of necessary knowledge really looked scary.

Moving from Struts to JSF

Although the JSF approach is far from being perfect, it’s just a great leap forward compared to the old mainstream Struts:

- at the architectural level, JSF removed the need for a layer, making it possible for the presentation layer to manage model objects instead of dealing with extra-flat ActionForm classes. In many cases, inability to handle data which was not a String led to an extra layer of DTOs to simply handle transportation and type translation between the web layer and the business layer (pretty boring stuff indeed)

- in the IDE, designing a web user interface has become simpler and more productive since JSF support is built-in and not only an a not-so-well-designed-plugin. Many components are designed on top of basic layers (Servlets and JSPs), so you normally shouldn’t bother about them.

Data Aware components

JSF toolkits offer also the possibility to use data-aware components in a web oriented paradigm. This way you can expose a RowSet directly on the web page and rely on the data-aware component for synchronizing page data with the underlying database. It’s definitely not OOP but it might come in handy in many cases.

The main message is probably intended for the average orphan Delphi programmer: “your paradigm works in java as well, and on the web too!”.

Everybody happy?

So, looks like the Java web developer is now given two tools when constructing a simple web application. Anyway my feeling is that data-aware components are just a bad idea for a developer with a J2EE background.

1) data-aware component are popular in not-so-OOP languages (ok, languages jave OO capabilities, but I’ve never seen a VB programmer define a domain model), in such a scenario your application is just a collection of CRUDs (create-read-update-delete) and this is not exactly a great idea.

2) You have to define a place to put your business logic anyway, and since JSF allows you to use POJOs …why not use the POJOs? If you prefer to put all of your domain logic in the presentation layer you’re free to do it, but I have to warn… you’re probably going to hurt yourself.

3) Data-aware components fits well in closed client-server architectures. Here the architecture is not so close, we’re already on the web, so the chances for exposing a service on another channel (be it a web service, or a palm interface) are far higher than before.

4) Tools like Hibernate, or Spring really make data-aware component less interesting. Off-the-shelf ORM tools weren’t that popular in the client-server days, but now they really are part of the scenario. It was different were EJBs were hype, cause “domain modelling” really sounded like “business layer”, and this sounded like “EJB” (or worse: “entity beans”) meaning finally “heavyweight mess”.

So, even if some debate is still going on, I really think that data-aware component aren’t that interesting for somebody with a java background. They might come in handy for newcomers to the java platform that can postpone learning some heavy topic in the J2EE landscape for a while, but it really sounds like a short-term choice.


Tags: , ,

Sunday, July 30, 2006

Why CRUD use cases are intrinsically evil


When performing analysis for a new system, many people find useful to shrink several use cases in a single one, and tagging it with the CRUD stereotype. This choice has a clear advantage in terms of readability of the use case diagram, while the stereotype (often associated with a different color) just triggers a multiplication factor when defining estimates for development time.

Readability and estimates are just a small part of the game when it comes to actually design the overall system. A Use Case is intended not only to be a measurement of the overall complexity of the system, but also a useful tool to capture the real goal (for a good exploration on the matter, please read Alistair Cockburn’s Writing Effective Use Cases) of the different parties involved in the use case. Just a simple order-invoice combination cannot be well represented by two CRUDs due to the many interactions possible between the two data types.

A system made up by a pile of CRUD usually ends up in a data-centric application, where part of the complexity of the interaction between different data types becomes a burden on the user, instead of a system’s responsibility. A user-focused use case (or an XP-like user story) should instead capture the flow of the interactions between different data types. If you’re not modeling what lies beneath a CRUD and another one, you’ll simply have to face it later on in terms of cluttered implementation or a not-so-usable application.

Separating use cases concerns
In nontrivial systems I found useful to separate the different concerns by defining two layers of use cases:
  • Business Level use cases focus on the user interaction with the system, they provide a detailed description of the user’s goal as well as other party’s, and span across multiple data types;

  • Implementation Level use cases focus instead on the artifacts needed to realize the use case, such as web pages, persistence methods, complex data manipulation and so on, generally tied to one or few data types.
The first layer depends on the second one for the implementation, and in trivial cases there is no need to separate them.

Testing the resulting system
A not-so-small difference in the two styles is that we can choose which use case layer is best suited to provide the specifications for building our test suite: at the business case level we can probably test more with less effort, and catch some awkward combination of data that tests based on the implementation level couldn’t catch. Of course the better combination is to define (unit) tests for the implementation level to be used as bricks for the business level tests.

If acceptance test are to be run by a real user, they’ll probably follow some path defined in business level use cases, instead of merely trying to add or modify some data and see what happens.

Enter the domain model
Such a modeling style, prepares the background for a domain model type of system (as opposed to the data-centric one). If we are to model something which lies in the correlation between two or more different data types, the best place to define it is in the domain model, be it in the component behavior or in the use case controller class. The default choice for data centric systems I’ve seen so far, has always been presentation layer… :-(

A significant exception
Apart from very simple systems, data centric applications (and thus CRUD-like use case modeling) are the best choice when the overall business processes aren’t completely defined, so instead of having a complex, but incomplete, system driving the user (possibly to a dead end) it’s probably better to have the expert users in control, and let them the possibility to tweak the system as they need (a possibility greatly appreciated in call centers, for example). However, this situation it’s not a great symptom of the whole organization’s health (but might be the driving force in a startup, for example), more often it is a sign of a poorly done analysis.


Tags: , ,

Sunday, June 11, 2006

Why Object Oriented Designers should rule the world


I was drowning into the abyss of the Italian bureaucracy in the last few days, going from an office to another one to fetch the papers needed to ask for another paper. A notary public asked me to get papers from the local registry office. The data was on paper, so the officer wrote an official document with a typing machine (a mechanical one). Of course there was something wrong in it, but since it was the referring to the notary’s county of the original document author and the notary was the same that asked me for the document (in other words, he asked me to get something he wrote) I hope this is a minor mistake…

The second paper (same papers I already had but I needed a fresher timestamp on it) forced me to go to another municipal office, where they told me
  • I had to go to the land registry office (is cadastre the right word?) asking for some maps

  • I had to pay €100,00 at a post office

  • I had to buy two special stamps worth €14,62 each
I searched in the internet yellow pages, for the land registry office address, but I got the wrong one. I phoned to a yellow pages service and I got almost the right one. Once I got in, the place looked like some kind of transit station on the way to hell: dozens of people camping in a large hall waiting their number. Luckily I had something simple to do and my queue was relatively fast. Of course I had to pay €35,00 for the maps I asked (just reading what was needed to complete the request for the other office (are you feeling lost? Me too).

Then I went to the post office to pay the €100,00 and buy the stamps. Obviously, there were no stamps of that size, so the lady started trying various combinations of different stamps (in a variant of the knapsack problem) to achieve the exact sum of €14,62. Welcome to the third millennium!

I then brought the maps back to the first office and they told me most of them were not needed for my type of request (grrr), so they just took one. I am now waiting the phone call of another officer telling me some papers are missing.

…So what?

Ok, I might be a sort of a strange guy but I can’t help it: every time I go to a public office I start thinking about it in terms of OO modelling. It just doesn’t make sense to me that all of a transaction complexity is put on the user shoulders. It’s exactly the same problem you can face with badly designed interfaces in server code.
A server class (as the name states) is supposed to serve multiple clients. A good design decision is to hide complexity behind the server class API, so that you can write simpler clients. Since clients are written in different context and times, you pay once on complexity on the server side and save every time somebody writes client software.
Bureaucracy is normally doing the opposite: to achieve thin processes on the server side (enabling eternal coffee breaks), officers are moving the burden of complexity on the users: forcing citizens to locate external services, pay (in the silliest possible ways).

The more I look at it the more it doesn’t look like a way to save time at all: if a frequent connection has to be established between two separate offices, then using the citizen (which is 90% of the times doing this thing for the first time) is the most inefficient way of all! Citizens have to be trained to go there and ask that and that, and this is a repeated waste, citizens are not experts so they could make more mistakes than trained officers on a standard procedure, so the process results more error prone.

Can anybody do something about it? Unfortunately this is pretty hard, because requires somebody with a pretty large scope, authority, and completeness of vision: a dictator? An emperor? An alien from a distant planet? Since crossing organizational borders or ruling the empty spaces is one of the most difficult management activities, I am pretty pessimistic about that.

Test Driven Bureaucracy

In the OO world, the best way to achieve a simple API is to develop in a test-first style. This way the developer thinks first from the client perspective (resulting in low complexity of the desired process interface, mostly a money for paper bargain), and then implements the service, keeping most of the complexity behind the server interface.
I just wonder how a similar approach might perform if applied to bureaucracy, I guess we’ll have a lot of surprises (in Italy whole institutions are totally useless) by crossing a test driven methodology with a strong OO-like role/responsibility analysis. As the picture shows, even if pessimistic, I haven’t lost all my hopes.



Tags: , ,