For some time, I have been working with EJB and with people who tell me they know what components are, after all. I am not so sure. I'm getting the feeling that components come much too fine-grained, especially with EJB. Not that EJB enforces such fine granularity, but all known uses implement it. Let me explain what I have in mind.
So what is a component after all? Before I try to explain my answer to that question (and thereby presumably adding to the general confusion), I'd like to look into the issue of component instances
. Everybody seems to focus on delimiting components against each other. We're talking about component classes
here. However there seems to be consensus that it's fine if there are a lot of component instances of the same type around.
For instance, let's assume we have an Account
component type. This component is fairly large grained in that it encapsulates account information, account transactions etc. Mapping to an RDBMS might involve tables for the account itself plus tables for the business transactions. However, there will be one instance of that component per actual account. Now, lets assume there is another component type called Customer
. Again, this is a reasonably large-grained component. Think of what information this customer might contain. A lot of database tables will probably be involved. On the other hand, we will again have one Customer instance per actual customer.
A lot of people I know will agree that this is a sensible component structure, with reusable Customers and Accounts that can be used in various applications. But then it happens: Our requirements change. Our customers discover that they need another application that associates each customer with a specific account! On the conceptual level, it doesn't look too bad: Just one dependency between Customer and Account. A single, harmless line on the component diagram. But look what happens underneath: Each and every instance of our Customer component type now has a reference to an instance of our Account component type. And it becomes even worse: Not satisfied with only one account per customer, our users demand a set of accounts! Some accounts might even be shared by several customers! Thousands of cross-component dependencies that lurk to have their end-points activated upon an innocent customer query. What about performance? What about integration, deployment, etc.? Briefing for a descent into hell.
The situation obviously calls for intermediate, connecting components, or perhaps a relationship service to ensure referential integrity and so on. Or maybe we should merge Account and Customer. But then, all components that use the two would be affected. We seem to be in a situation where a lot of added complexity is inevitable.
So far the problem. Now, what's the proposed solution? Let me begin with an analogy. Consider a word processor. Quite obviously, the actual documents are entities. But are they components? In the previous scenario, they would probably be. However, I have the strong feeling that the word processor itself would be a much better component. It represents a set of functionality defined over documents, but any word processor can handle several documents at once. If fact, a decent word processor can even handle multiple views of the same document at once. Documents are persistent, but from the word processor's point of view, documents may come and go while the processor remains. (I'll come to the difference between "session" components and "entity" components later on.) In a networked environment, we might even have several word processors that edit the same documents.
With that analogy in mind, let's reconsider the Account and Customer example. What are the components in this example? Perhaps, we will have an Accounting System
and a Customer Administration
. Perhaps we will find other groupings, for instance for different account categories of different kinds of customers. However, a true component along the lines of the analogy would have to be able to deal with a set
of entities, and a set that changes over time, too. It is easy to see how this affects the cross-component dependencies that arose in the example above. Now, we usually have only one instance of Accounting System
and only one Customer Administration
. Consequently, there will be only a single dependency, even on the instance side. Much easier to handle than the abundance of instance-side references in the previous situation.
This may sound as if I am proposing only singleton components. That is not what I intend. Singletons are guaranteed
to be sole instances of a class. Such a guarantee is hard to maintain in a networked, distributed environment. Furthermore, I consider the Singleton pattern to be dangerous anyway. The major drawback (that the GoF fails to mention) is you give up a good deal of flexibility. What if you need another instance some time in the future? After all, you never know!
So why could we have several instances of a component type at all? In my opinion, there are at least two reasons:
- Several (a lot of) users access the component concurrently. Having one component instance per user would give a performance benefit at least. Perhaps a pooling approach with one instance per active user would even be more efficient. Fortunately, EJB helps here by leaving this rather complex task to the container provider. This is, in my humble opinion, one of the few advantages of EJB over CORBA.
- Different users or the same user in different roles access different sets of entities. For those different aggregations of entities, different component instances may exist. Consider financial accounting and employee compensation that both use accounts, but not the same ones.
The latter is the more interesting because it cannot easily be automated.
Before I finish, let just prattle on a little on session (client-specific, transient) vs. entity (shared, persistent) components or beans. I believe, much of the fine/coarse-grained confusion in EJB is caused by entity beans. Seen in this light, Sun was probably wise in not requiring them in EJB 1.0. Things have changed, though, mainly because just about everybody complained that EJB was useless without them. There seems to be a consensus that entities have to be represented by entity beans. I do not agree. As a consequence of my views described above, whether a persistent entity is involved is meaningless for deciding whether the component should be persistent or not. And right: you can access entities from EJB Session Beans just fine.
The real question to ask is: Do I want the component
to be persistent? Do I want it to be shared? To strain the analogy once again: What happens when your computer crashes while you are using the word processor. Sure enough, you would like to have your documents secured. But what about the word processor itself? You might want it to restart with the same documents opened as before the crash, and the windows arranged properly, and perhaps even the cursor on the same line. If that's what you want, the component itself is persistent, it has persistent state. Make it an Entity Bean.
On the other hand, you might be happy if the documents are saved, but you'd like to open new accounts, handle new customers when the system recovers. Think about a workflow application. While your computer was down, another user might have taken the item you were working on from the to-do list, and finished it. You surely wouldn't want your workflow application to present you that finished work item again. Probably, a Session Bean is called for.
These are my thoughts on components. Do they make sense to you? What does it all mean? Maybe it's nonsense. However, I'd really like to read comments on my view of components, whether there are publications that share my views but I am not aware of, or whether what I'm writing is the meaningless babble of a semi-conscious, half-educated mind. --HaskoHeinecke
I must be massively missing the point. The one to many mappy from customers to accounts is a property of the domain, That relationship exists in the real world, and I assume still needs modelling in the software system you're constructing.
So, it's there somewhere. It's no longer represented by dependencies among instances of beans. What has that gained you? What has it cost in terms of complexity elsewhere? Why stop there - just have a single component called "The system"?
It seems to be you've swapped a system that reasonably directly represented the application domain for one that has fewer component instances, with the problem of managing the customer-account relationships swept under the carpet. This doesn't, at first sight, seem a good idea.
Later: it's just struck me you may be using the word "Component" in a special purpose way. In which case, a) I think this page should be renamed, since it doesn't really discuss what components are, more what they should represent, and b) perhaps you could explain what you mean by component?
Hasko's thoughts sound pretty reasonable to me. I think there's an enormous amount of confusion around what constitutes a component and how they should be used for modelling. Enterprise Java Beans, particularly Entity Beans help confusify things tremendously -- AlanKnight
wrote: 'Why stop there - just have a single component called "The system"?' I would say, why not start there? I know one thing for sure: "The system" will be a component in the larger computing infrastructure of my organization. Given the general confusion around components, I think that's a good start. I would then go on and try to isolate certain parts of the system into their own components, until I see fit. Most projects I see and hear of seem to go the other way round. Speaking overly simplistic, they just take every domain object in their model and make it a component. Essentially, they replace the concept of objects with the concept of components. This leads to the problems described in the WaldoPaper?
. And therefore I do not like this approach. --HaskoHeinecke
A good paper, by Colin Atkinson, ThomasKuehne
and Christian Bunse can be found at
A good book to chew on if this topic gets you going - Objects, Components and Frameworks by DesmondDeSouza
defines "software components" to be "binary units of independent production, acquisition, and deployment". While this test may apply to JavaBeans
, I don't think it applies to EnterpriseJavaBeans
. I've never heard of a case where someone acquired and deployed a single independent EJB - they're too fine-grained and they require too much surrounding support (e.g., databases with certain schemata, etc.) to be used for that purpose. Perhaps an entire .ear file could be considered a "component", but not a single EJB. --RandyStafford
Also gets into an OpenSource
distinction. With closed source, having clean interfaces and well-documented API is important. If your components are open source, they can function as their own documentation.