Does it make sense to to separate data and logic?
In an application consisting in a lot of objects mapped to a relational database does it make any sense not to place any logic in the persisted objects and treat them as data and place all the logic in singletons and other kinds of objects that are not persisted (calling them APIs)?
The logic objects do not represent any object in particular just hold methods to do stuff , fetching some things from the database (the data objects) and creating new objects and saving them for example.
A typical "data object" would be customer, holding just the data (possibly gathered from a few tables) and references to other objects related (like the trading location) and a typical "Logic object" would be an object capable of taking an order object and saving a delivery object..
What is your view on this kidn of separation between logic and data? Isn't the OO paradigm teach puttign the data close to the logic that uses it? Isn't this approach going to be a mess when the data changes and all the logic has to be readapted?
[1052 byte] By [
fedetxf] at [2007-9-30 4:56:22]

The OO paradigm is to seperate the classes of objects.You should definitely seperate the data from the logic. If you do not, if you ever change databases, you will have to change your logic as well. This should not be the case.
The problem you are dealing with is often referred to as the object-relational boundary. Fundamentally, objects exist as a graph in memory that does not correspond one-to-one with relational database tables. The conundrum arises from the fact that the database and the Java middleware should be optimized for different tasks.
Relational databases are about storing data with the least possible duplication or redudant information. Concepts such as referential integrity and primary keys, while they may have allegories in Java objects, are really realized only in a database. Objects on the other hand have concepts such as encapsulation, polymorphism, inheritance and delgation, to name a few.
One may be tempted to simply create one table for every object and "map" the database to the object model. Inversely, you may already have a legacy data model and be tempted to make your Java class hierarchy and interactions mimic the existing data structures. Both of these approaches, while possible in a simple coding environment, make about as much sense as creating a separate, dedicated Java object for every view or web page in your application. Going down these paths should be viewed as a short-cut rather than a design.
So, we have arrived at the object-relational boundary. There has be code that maps Java objects to database relational concepts. The current paradigm for this is to have the domain model (Java business objects) use data access objects to retrieve data from and store data in the database.This allows the strengths of both object-orientation and relational databases to be used.
Fundamentally, objects should be encapsulated. This precept implies that data (instance variables) should be as close as possible to logic (methods). An object should maintain its own internal state and provide methods to change that state. Logically, this would include persistence logic as well. If you don't need to expose dozens of setter methods (even protected setter methods), you shouldn't.
This is the pure OO view of persistence logic in the domain model. However, as in all software development, the reason there are so many design "rules" is that there are always trade-offs. Faithfully observing encapsulation means that if your data model ever changes (more likely) or you switch databases (less likely), you will have to go into every model class and re-write its persistence logic.
The idea of introducing DAO's, and all the complexity associated with them, is that you can go and simply rewrite the applicable DAO's and leave the model classes unchanged. The DAO translates the relational-object boundary. It also cleans-up and shortens your model classes, since the persistence logic is moved elsewhere. The domain model classes now have only methods that change their internal state, in memory. If you want to transfer and object from memory to the persistent store, you use a DAO. There are other benefits of DAO's as well, such as enapsulating database operations that span multiple objects or whole graphs of objects into a single DAO object. Maintaining transactions or a logic unit of work is also easier to understand in a DAO of this type.
So, your intial question is right on the money. Encapsulation would push you towards having domain model and persistence code together. The object-relational boundary (and the general concept of having application tiers) pushes you to have persistence code separated from domain model code. To what extent you observe one design principle over another is a tradeoff that needs to be addressed in each application you write.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:17 >

Interesting. But my question is not so much about where to put the persistence code, but if all the objects that I persists should not have any logic, but all the logic be put in singletons and static methods that are not persisted.
Now I'm getting confused. If a given class has no instance variables, or only static final instance variables, then it is really simply a helper class. If nothing in the internal state of the object can change, that object would be a good candidate for a singleton.
Now, I personally cannot think of *any* situation where the reverse would be true: an object with instance variables but no methods. Unless you want to make all your instance variables public, you will need to expose at least a few getter methods for the object to have any use whatsover.
The happy medium is where most "normal" objects live. They have both instance variables and methods. These methods can simply be accessor/mutator methods to change the instance variables themselves (getSaleAmount(), etc.). In addition, you can have methods that perform more complex actions on the instance variables (calculateTotalDiscount(), etc.)
So I do not understand why you would want to have an object with "no logic". And I definitely am completely stumped by what you mean when you say, "all the logic be put in singletons and static methods that are not persisted." Methods are never persisted, only data is.
You can have a helper object that takes a domain model object and to perform persistence logic. This is exactly what a DAO is. Whether you want to make those methods static or normally instantiated is a design choice. But in a multi-threaded environment, it is much safer to have the domain model object create its own copy of a DAO, use it, and then let the DAO go out of scope.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:17 >

The objects without logic have public getters and setters and they also have collaborators. that is, the in memory graph exists. What the data objects don't have is logic.
Example:
I can ask a the a Product instance to give me the amount in stock, but I can't ask that object to send me a warning when the amount goes bellow some amount. I have some other object that I use like this:
StockMonitor.getInstance().checkStockFor(aProduct);
The StockMonitor asks the product the amount in stock (a data from the database that was stored by a DAO in that instance) and then performs the logic somebody decided was needed when we are runing out of that product in stock.
It's just an example. Poeple here think it's better to have many Managers that have all the logic and many simple objects with getters and setters that hold only the data from the DB viewed as objects.
DAO are a differetn question, and I agree with you about those, but im not interested in those for now.
You see my point now?
Gotcha.
In this case, I would add a method to Product called isRestockRequired() that returns a boolean. It presumably already has the quantity stocked, so it would be the "best" object to evaluate whether it needs to be re-ordered. The StockMonitor could iterate through each Product and call this method.
Of course, it can all get very complicated. I generally put aggregating or compound methods in something like StockMonitor, while querying for a given, single state should probably be done in an object like Product.
Lot's of ways to skin a digital cat. And the advice above may even be wrong if there are other design considerations in your application. But that's how I'd approach it given what you've said about the problem.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:17 >

The design gurus here don't want the "data objects" to have even that logic. All the Product knows is he has an amount in stock, and a ProductFamily and a descrition and so on. The desition on when is restock required is placed in another object created for that purpose and other purposes but that second object I called StockMonitor has no state: it's just methods.
Do you agree with this approach? Do you see any reason to do this separation? Any situation when this might be helpful?
> Do you agree with this approach? Do you see any reason
> to do this separation? Any situation when this might
> be helpful?
If you do not do this, then if you want to use Product in a different context where the business rules are different, you either have to create a new Product class that will have a lot of duplicated code, or you end up with a very complicated Object that has to be aware of it's surroundings.
The hardest thing about teaching people about design is getting them to understand why certain things are helpful. Usually you have to be bitten in the *** by not doing it to understand.
I will have to disagree. Okay, let's say that the Product class has business rules for determining whether a it is out of stock. Now, you have a new situation where the business rules will differ.
Java is rife with options to handle this without duplicating code:
> Create an abstract class for Product.Move everything *except* the re-stock logic to the abstract class. Make the restock method calculation an abstract method.
> Then create subclasses for all the variations in stocking logic that will implement the abstract method.
> Finally, create a Factory class that can determine which implementation to use.
And that's only one possible design refactoring. You could also do something similar to the Comparable interface, where instead of passing in an ordering interface, you pass in a stocking interface. Now, stocking logic is separate from product logic. There are many ways to separate the business logic from the data itself.
You would not make that separation initially, only once the design required it.Barring another design consideration, you should try to honor encapsulation. If an object has all the data it needs to evaluate a method, why move that method to another object?
Are there valid reasons why one would break encapsulation? Sure, all the time. But at least wait until those design considerations (or more likely, trade-offs) surface before you break encapsulation.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:17 >

Well, then I might ask, what's the advantage or instantiting a Product object? Why not a use dictionary for that?
Also, if you don't have any behaviour in it then reusing it does not ruse any actual code, just structure which is supposed to be hidden anyway.....
Also I can cope the changing business rules by using a strategy to calculate the restock need, and having that login in the Product object.. I still don't see the need to make sure all clients call the right "Stock Monitor" every time instead of the object to "just know" how it's calculated.
> Java is rife with options to handle this without
> duplicating code:
All of which require changing the existing code which you note in following comments.
> > Create an abstract class for Product.Move
> everything *except* the re-stock logic to the abstract
> class. Make the restock method calculation an
> abstract method.
There is no advantage to putting the data in the abstract base instead of using composition. You are still separating the data from the logic you are just shoehorning it into an inheritance heirarchy.
> > Then create subclasses for all the variations in
> stocking logic that will implement the abstract
> method.
This assumes every context will need the same methods i.e. actions. Often you will not even want some clients to know that certain actions exist let alone invoke them.
> And that's only one possible design refactoring. You
> could also do something similar to the Comparable
> interface, where instead of passing in an ordering
> interface, you pass in a stocking interface. Now,
> stocking logic is separate from product logic. There
> are many ways to separate the business logic from the
> data itself.
Yes. How is that an arguement against separating the data from the logic.
> You would not make that separation initially, only
> once the design required it.Barring another design
> consideration, you should try to honor encapsulation.
> If an object has all the data it needs to evaluate a
> method, why move that method to another object?
There's no downside to using composition. Why make refactoring hard on yourself when it's just as easy to build the design in a modular way?
> Are there valid reasons why one would break
> encapsulation?
This has nothing to do with breaking encapsulation. You are making an incorrect assumption.
> Well, then I might ask, what's the advantage or
> instantiting a Product object? Why not a use
> dictionary for that?
Space / time efficiency and type-safety. But, yes you can use a Map. Kills you on Serialization, though.
> Also, if you don't have any behaviour in it then
> reusing it does not ruse any actual code, just
> structure which is supposed to be hidden anyway.....
If you code the structure into 10 classes and the structure needs to change, how many classes' structures have to change?
> Also I can cope the changing business rules by using a
> strategy to calculate the restock need, and having
> that login in the Product object.. I still don't see
> the need to make sure all clients call the right
> "Stock Monitor" every time instead of the object to
> "just know" how it's calculated.
Again, incorrect assumption. As far as the users know, there is only one type that they can use and it contains data and logic. But really it's a composition of business and data objects.
> Again, incorrect assumption. As far as the users
> know, there is only one type that they can use and it
> contains data and logic. But really it's a
> composition of business and data objects.
No, because the way it's done user have to do
StupidStockMonitor.getInstance().isRestockNeeded(aProduct)
and not
IntelligentStockMonitor.getInstance().isRestockNeeded(aProduct)
> No, because the way it's done user have to do
> StupidStockMonitor.getInstance().isRestockNeeded(aProduct)
>
> and not
>
> IntelligentStockMonitor.getInstance().isRestockNeeded(aProduct)
I don't see the difference between these two statements other than the name of the Singleton.
I don't know anything about the design you are writing about. I don't know if it is good or bad but there is more than one way to separate business logic and data. Just because the desinng you are working with is one way doesn't mean it's the only way.
> I don't see the difference between these two
> statements other than the name of the Singleton.
>
> I don't know anything about the design you are writing
> about. I don't know if it is good or bad but there is
> more than one way to separate business logic and data.
> Just because the desinng you are working with is one
> way doesn't mean it's the only way.
OK.
So is it OK for clients or users to be aware of the separation? Or is it better to have the separation encapsulated in an object that looks like it's having all the data and logic inside?
I think "aProduct.isRestockNeeded() " it's better to "SomeSingleton.getInstance().isRestockNeeded(aProduct)"
> No, because the way it's done user have to do
At first glance this seems like a poor design, however.
The business logic should wrap the data. It appears as if the client, in this case, has access to the data to change it in anyway he/she sees fit. There's nothing forcing the client to use that or any other business logic component.
> OK.
> So is it OK for clients or users to be aware of the
> separation? Or is it better to have the separation
> encapsulated in an object that looks like it's having
> all the data and logic inside?
I could depend on what you are doing. But generally, it should be seemless.
> I think "aProduct.isRestockNeeded() " it's better to
> "SomeSingleton.getInstance().isRestockNeeded(aProduct)"
I agree. However, Product should be an interface and what is behind that could be a whole lot of things.
I've been playing around with the idea of having a data class that is basically a structure. The DAO other persistence layer object would be a factory that sets all the fields. Then that would be put inside one or more business layer Objects for use. Then the data can easily be passed from context to context without exposing it's guts to anyone.
It might seem like I'm opening it up for everyone but it really encourages protecting the data more becasue you don't always have to have a setter or even a getter for a particular field in a specific context. You can also make the data look like something else for retroftitting new data with old code.
Saish, I always enjoy reading your posts, but these are particularly good IMO. So well-written. Thanks for sending them.Sincerely, MOD
I have worked for months with a project and it evolved into seperating the data from the logic. In fact the data classes are actually multitons because I only want one way into database at a time.
What I have is database access objects which in fact are really only used to 'serialize' the data from the main model object. The database objects contain all the sql and whatnot to get info to and from the database. the sql package is NOT present anywhere but in the database access objects.
The model object contains a general presentation of the 'data' being used. It also fires events. also sometimes a model object may be made up of a couple different database access objects. i try to keep one database object per table, but sometimes the lines blur.
Then there is the logic object which deals with the model object. that is where the logic about how the program behaves lives. It does not really deal in 'data', but more in behavior. though behavior is directly the manipulation of data.
I found this seperation helped me a lot when I ported from MySQL to MS JET database for development. It also lets me use different facilities of each database. I have to admit that the model object and the database object both changed. but that is my choice. I could have kept the same model objects but some optimizations allowed me to use different set of tables.
Every layer should be seperated as much as possible. But not seperated for the heck of seperation as I learned the hard way and had to repackage my database access objects in the same package as my model objects again.
This is getting long but one last point. Occasionally a data access object actually is a model object, or rather implements the interface for a particular model object.
I was merely showing how with a few cut-and paste operations, you could achieve both encapsulation and re-use. This was in direct response to your assertion:
<quote>
If you do not do this, then if you want to use Product in a different context where the business rules are different, you either have to create a new Product class that will have a lot of duplicated code, or you end up with a very complicated Object that has to be aware of it's surroundings.
</quote>
So, while I agree with your general comments on composition versus inheritance, your assertion that "you will have to modify code anyway" is tautological. How would you effect a software change otherwise?
You changed the design assumptions (see above quote) positing that there were different environments to deploy the same object. Given those (different) requirements, the one method that now needs to be polymorphic was made polymorphic. Now, whether you want to do that with inheritance or composition/delegation, there are lots of posts on that already.
So, keep data and logic together, honoring encapsulation wherever possible. As soon as that rule becomes a straightjacket, you obviously need to look at other design possibilities.
And finally in response to the flavor of most of your objections, you *cannot* design software for all possible contingencies. I can only quote Fowler on this one:
"With any requirement I would wonder how that requirement would change during the life of the system. Because design changes were expensive, I would look to build a design that would stand up to the changes I could forsee. The problem with building a flexible solution is that flexibility costs. " - Refactoring, Martin Fowler, p. 67
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:20 >

> Now I'm getting confused. If a given class has no
> instance variables, or only static final instance
> variables, then it is really simply a helper class.
> If nothing in the internal state of the object can
> change, that object would be a good candidate for a
> singleton.
>
> Now, I personally cannot think of *any* situation
> where the reverse would be true: an object with
> instance variables but no methods. Unless you want to
> make all your instance variables public, you will need
> to expose at least a few getter methods for the object
> to have any use whatsover.
>
A DTO can be implemented exactly like that.
Myself I do not like to think of a DTO as an object in the OO sense. Just as a java.lang.Math is not an object either. A DTO is just a conveinent grouping of related attributes.
As a matter of practicality my DTOs always have simple behavior. But I still don't consider them first order objects.
The J2EE patterns provides the rational for the existence of these.
Thanks DuffyMo. I'm just happy to be here! :^)- Saish"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:20 >

> Interesting. But my question is not so much about
> where to put the persistence code, but if all the
> objects that I persists should not have any logic, but
> all the logic be put in singletons and static methods
> that are not persisted.
Sometimes data is presented in a different way than it is stored. For instance, I store points as 2 integers, but present them as the class Point. So my model objects deal in Points, and fire events with Points. The model objects are not actually persisted, but the point is always kept in synch with the two integers in the database.
So while I could make static methods that remake the point every time, I preferred to cache a local copy of a built Point and pass that around. Point is just a simple example, I have lots of other objects that are put together in this way.
I'm doing my own object relational mapping, if your not, then perhaps you can combine DAO with model objects. But you still have a seperate logic object.
I'd have to agree with you there JSchell. Again, because of the relational-object boundary. The fact that DAO/DTO objects are not "full-fledged" IMHO is because they "straddle" both worlds.
And no matter how dogmatic any poster wants to be on this subject (myself included), I think everyone will realize there are lots of ways to approach a given problem, especially object-relational issues. Most involve tradeoffs on one level or another, which is why debating those choices can get so interesting.
- Saish
"My karma ran over your dogma." -A non
Saish at 2007-7-1 15:31:20 >

> So, keep data and logic together, honoring
> encapsulation wherever possible. As soon as that rule
> becomes a straightjacket, you obviously need to look
> at other design possibilities.
>
Depends on how you define data. In my objects which are DAO, the data of concern is INTEGERs and LONGs, etc. So only the DAO deals with that particular data. There are SQL commands and such that deal with this data. So this data, and methods both are in the same class.
Then there is the model class that uses the DAO class. It uses the DAO to put together its own data members. So the model is essentially an adapter to the DAO class. It also adds an event architecture for changes on its own data.
On top of that is finally the so called 'business logic.' So we have 3 sets of data here, and 3 classes that deal with the data. Each has a type of data that he deals with, adapting and presenting it to another class in a form that it can digest.
> So, while I agree with your general comments on
> composition versus inheritance, your assertion that
> "you will have to modify code anyway" is tautological.
> How would you effect a software change otherwise?
I never wrote anything like "you will have to modify code anyway" in this thread. I can only assume you are referring to when I wrote "require changing the existing code" which is not always neccesary if you keep the data separate from the logic. You will be able to add new business logic classes without touching the data classes.
> You changed the design assumptions (see above quote)
> positing that there were different environments to
> deploy the same object. Given those (different)
> requirements, the one method that now needs to be
> polymorphic was made polymorphic. Now, whether you
> want to do that with inheritance or
> composition/delegation, there are lots of posts on
> that already.
I didn't change the design assumptions. I said "if" the data was later needed in different environments. I can't even count the number of times where the assumption that something was only to be used in one context caused a schedule to slip. In any event, the OP asked what was the benefit of separating data and business logic. That's the question I answered. Yes you can always refactor code. That's pretty obvious. The point is separating these things is a way of preemptively dealing with common maintenance issues.
> So, keep data and logic together, honoring
> encapsulation wherever possible. As soon as that rule
> becomes a straightjacket, you obviously need to look
> at other design possibilities.
Again, this has nothing to do with encapsulation I am not advocating eliminating encapsulation in any way. If you have read my later posts that should be obvious.
> And finally in response to the flavor of most of your
> objections, you *cannot* design software for all
> possible contingencies.
Are you arguing that no likely changes should be anticipated?
I can't even remember what any of this is about anymore. Best of luck to all involved.- Saish"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:20 >

>
> > And finally in response to the flavor of most of your
> > objections, you *cannot* design software for all
> > possible contingencies.
>
> Are you arguing that no likely changes should be
> anticipated?
Your intent is not clear, but in general I would argue against that.
It is always a bad idea to write code based on a guess as to where the code might go in the future. That is not the same as saying one should write it because one knows where it will go.
For instance I will not add support to the DAO layer because someday someone might want to use blobs. I would however do so if I knew that the users had already requested image support and for the next requirements will include it.
Of course that gets a little less clear when one suggests that one should use a DAO layer itself, because future maintenance would be easier. Perhaps it is that sort of general idea that you had in mind?
> Of course that gets a little less clear when one
> suggests that one should use a DAO layer itself,
> because future maintenance would be easier. Perhaps
> it is that sort of general idea that you had in mind?
All I am saying is that building simple Java classes that hold data and all business are hard to maintain and expand upon. I know this from personal experience. With very little effort, you can use composition and use a DTO (though, I don't think it necessarily has to be for transferring data) to represent the data and wrap the business logic around it.
It's kind of along the lines of how the original Atari game systems just came with built in games. Then someone thought up the idea of separating the games from the system. Now everyone who comes out with a game console separates the games from the system. They don't reinvent the wheel. It's a paradigm that not only works but dominates the original idea. Just like separating data from the logic.
And that doesn't mean breaking encapsulation. If you do it right, it will be completely unknown to the users of your classes whether you separated it or not. It's none of their business unless you want it to be.
Anyway, I digress. My point is, that I hope I never get another flat tire. If I don't, that's great. It doesn't mean having a spare tire in the trunk was a waste and I should have chucked it to save on gas. Separating the data from the business logic is a simple technique that costs very little but can pay-off big.
> I think "aProduct.isRestockNeeded() " it's better to
> "SomeSingleton.getInstance().isRestockNeeded(aProduct)"
I think it's a question of OO, that each object in the machine world should be a surragate for a thing (abstract or concrete) in the real world:Product walkersCrisps = ...
walkersCrisps. isRestockNeeded()
=> false if there are any packets of walkers crisps in stock anywhere on the planet
Whereas a simple OO mapping of the concepts would give something that reads like:
WareHouse myWarehouse = ...
if (myWarehouse.hasRunOutOf(walkersCrisps) ) {
DeliveryRequest request =
purchasingDept.deliveryRequest(
myWarehouse,
walkersCrisps,
stockMananger.getRestockQuantity(
myWarehouse,
walkersCrisps));
Delivery delivery;
if ((delivery ==
yourOrderingDept.accepts(request)) != null) {
myWarehouse.accept(delivery);
}
}
assert(!myWarehouse.hasRunOutOf(walkersCrisps));
Get a clear idea of the domain you're trying to represent before applying design patterns; separate the concerns of the objects. Then, if the warehouse may use different logic or data sources, provide an aggregate data object/strategy. Often the need to provide different logic in the same class indicates the responsibilities are wrong, not a limit of OO.
Pete
>
> Anyway, I digress. My point is, that I hope I never
> get another flat tire. If I don't, that's great. It
> doesn't mean having a spare tire in the trunk was a
> waste and I should have chucked it to save on gas.
> Separating the data from the business logic is a
> simple technique that costs very little but can
> pay-off big.
Yes but there is a difference in having one extra tire in your trunk vs 15.
Or having 15 different sizes because sometime in the future you might modify the structure of the car and thus be using a different wheel size so by "planning ahead" by buying 15 different sizes you can anticipate that.
Some developers write their code like that. And that is wrong.
And the mention of blobs was not out of the blue.
At one point I was asked to maintain a database layer that had blob support. At least some of the code look suspicious to me in that it seemed like it had never been tested. I was somewhat familar with the database and there were no blob fields in the database. I asked around. There had never been any blob fields in the database. Not one single person could come up with a reason that blobs would ever be needed, there was no need for the industry that it was written for.
Obviously someone had added code, code that was not being maintained, and might have never been tested, "just in case" someone might need it in the future.
This sort of thing is always wrong.
> Obviously someone had added code, code that was not
> being maintained, and might have never been tested,
> "just in case" someone might need it in the future.
I agree completely. It's not an objective issue, though. Its something that has to be pondered and exentually someone makes a call. In this case I'm not talking about wrting code that may never be used, I'm talking about how you design the code that will be used.
Right now my team is struggling because we did not separate our business logic and data. An there's no easy refactoring so there is likely never going to be time to fix it in the foreseeable future. The only thing we can hope for now is a new backwards compatible design that allows us to avoid compounding the problem. This greatly increases the cost of our new design work because it creates extra constraints that do not have anything to do with our future goals. If we had separated the business logic from the data, we wouldn't be in this position.
Given this experience I can't see why the simple step of using composition to separate data from business logic wouldn't make sense for all but the most trivial of projects. It would have had a negligible impact on our initial work and would be paying off in spades now. At the time we didn't see this. That's why I am offering my mistakes as a lesson to others who hopefully won't have to make them.
Okay, I'll jump back in.
I don't see how having the business logic and data together confuses your design. Rename the old objects by prefixing them with a common word (say, Legacy) or move them into a dedicated sub-package per package to be converted (say, .legacy.*). You may have to look out for dynamic class instantiation in the process.
Now, you have total freedom to operate your new design. Create a factory class that will broker both old and new requests, and you're done. You could even put all the legacy classes in their own JAR and deploy it only where needed. When the backward compatibility issue recedes, remove the JAR.
The one instance that I can see your method being worth the extra effort would be in a case where the algorithms underpinning the objects in use are constantly changing, whereas the actual data stored remains constant.
I have worked on systems like this. In the insurance industry, for example, they are constantly re-evaluating their risk and premium models. They rarely capture new data, but the algorithms used to evaluate claims and policies do change often.
However, the design above still would not deliver benefits until you have to retroactively calculate an old policy (say, for a legal claim or to make historical algorithm comparisons). So, unless you need "algorithm versioning", I don't see the need to perform the separation.
I'm not saying it's wrong or bad or inefficient. I'm just saying that given limited time and budgetary constraints, there may be better uses of your effort.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:23 >

> I don't see how having the business logic and data
> together confuses your design. Rename the old objects
> by prefixing them with a common word (say, Legacy) or
> move them into a dedicated sub-package per package to
> be converted (say, .legacy.*). You may have to look
> out for dynamic class instantiation in the process.
Sounds like a lot of **** that I wouldn't be neccesary if the data was separated in the first place.
> Now, you have total freedom to operate your new
> design. Create a factory class that will broker both
> old and new requests, and you're done. You could even
> put all the legacy classes in their own JAR and deploy
> it only where needed. When the backward compatibility
> issue recedes, remove the JAR.
Again these things all take more time than the correct initial implementation and complicate the design. These are great examples of how not separating the data from the business logic turns into extra work later.
> The one instance that I can see your method being
> worth the extra effort
What effort? It won't even affect the schedule.
would be in a case where the
> algorithms underpinning the objects in use are
> constantly changing, whereas the actual data stored
> remains constant.
>
> I have worked on systems like this. In the insurance
> industry, for example, they are constantly
> re-evaluating their risk and premium models. They
> rarely capture new data, but the algorithms used to
> evaluate claims and policies do change often.
>
> However, the design above still would not deliver
> benefits until you have to retroactively calculate an
> old policy (say, for a legal claim or to make
> historical algorithm comparisons). So, unless you
> need "algorithm versioning", I don't see the need to
> perform the separation.
>
> I'm not saying it's wrong or bad or inefficient. I'm
> just saying that given limited time and budgetary
> constraints, there may be better uses of your effort.
public class Example
{
private String data;
public String getData()
{
// do some business logic
return data;
}
}
becomes:
class DataCartridge
{
String data;
}
public class Example
{
private DataCartridge cartridge;
public String getData()
{
// do some business logic
return cartridge.data;
}
}
I don't see what's so difficult.
Okay, here's where you will eventually end up if you think long enough about this when the power goes out:
You are not adding any value with your data "objects".
Let's say I have the following:
class Product {
private int uid;
private double price;
private String description;
}
There is *no* difference between class Product and a new class called "OneIntADoubleAndAString". None. Zero, zip, nada.
Yes, the compiler may complain that is not an instance of "Product". But for what you are using this class for, there is *NO* difference between the two classes.
If you separate data and logic fully, and take it to its conclusion, then you end up with a series of classes like OneIntADoubleAndAString. (You could name them "Product" or "Widget" or whatever, but it won't mean anything). Each can be interchanged with any other instance. You are basically going *back* in time to earlier programming languages.
I see the utility of what you propose in some instances. But unless justified, ala Schell, don't bother.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:23 >

>
> Again these things all take more time than the correct
> initial implementation and complicate the design.
> These are great examples of how not separating the
> data from the business logic turns into extra work
> later.
>
I think we are in agreement.
But to make my point clear...
If the design was correct for the first release then the fact that it is not correct for the second release does not mean that the first design is now wrong.
Now perhaps the original design authors did know what was coming in the second release. In that case then the design probably is wrong. But if they didn't know then they should not have complicated their initial design by guessing about the future. They could have made a guess, but without real knowledge then in all likelyhood not only would their guesses have been wrong, but they might have not only increased their costs but increased costs for following releases as well.
Let me emphasize that there is a difference between guessing about future directions and having knowledge (even if it just came about through a conversation in hallway.) Guessing is always wrong.
> class Product {
>
> private int uid;
> private double price;
> private String description;
> }
>
> There is *no* difference between class Product and a
> new class called "OneIntADoubleAndAString". None.
> Zero, zip, nada.
>
>
> If you separate data and logic fully, and take it to
> its conclusion, then you end up with a series of
> classes like OneIntADoubleAndAString. (You could name
> them "Product" or "Widget" or whatever, but it won't
> mean anything). Each can be interchanged with any
> other instance. You are basically going *back* in
> time to earlier programming languages.
>
I have to agree, mainly because I never ran into the need to reuse objects with different logic. To me the logic defines the object more than the data, altough the data is needed for the logic to operate. Does anybody have any pattern or paper describing this problem and the logic separation solution? I read the DAO pattern (it's not the logic separation but more a layering between the persistent repository and the live objects) but I'd love to see a data / logic separation pattern or article or some real life actual useful use..
Tiering does not make sense in and of itself. It is *far* easier to have objects control all of their own state. It is definitely the fastest way to develop and honors encapsulation best.
Why tier then? Because, as in all software development, other considerations are also present.
Years of painful software development have taught most people that tiering is worth the extra effort in the medium to long term, especially if the system will be modified in the future, as most systems are. Scaling becomes easier. Specialization becomes more apparent (he's the persistence guy, she does UI, he does business logic, etc.) The actual business tier can concentrate on what makes the software different, etc.
People tier because in most implementations, the benefits outweight the initial costs. The same would hold true for the separation of data and logic. Are there cases where it is useful? Definitely. Would I write every object that way? No. Barring a demonstrable, viable need, I don't code for coding's sake.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:23 >

A quick google search for"Separating business logic and data" and "logic and data separation"yields papers and articles about separating logic from presentation and from data access.
> If you separate data and logic fully, and take it to
> its conclusion, then you end up with a series of
> classes like OneIntADoubleAndAString. (You could name
> them "Product" or "Widget" or whatever, but it won't
> mean anything). Each can be interchanged with any
> other instance. You are basically going *back* in
> time to earlier programming languages.
I don't see how this is the logical conclusion of what I am proposing. I am not saying that all data classes should be generic. I'm saying that the data should stand alone and access to that data should be controlled by business objects.
>They
> could have made a guess, but without real knowledge
> then in all likelyhood not only would their guesses
> have been wrong, but they might have not only
> increased their costs but increased costs for
> following releases as well.
And I agree with you on this. However, I don't think it applies to what I am saying. The design I am proposing should not increase costs. I am open to arguments that show it will.
In addition, I see this as something that (barring the decease of the system) will almost always provide benefits down the road and often provide benfits immediately.
I've been around long enough to know that if a man goes out to bars and strip clubs and comes how wasted with lipstick on his collar every night, his wife will most likely take issue wit hhis activities. If you do that and are surprised that your wife is divorcing you, it'd be a little odd. You should have seen it coming.
That's how I see this. Even if I don't neccesarily need this for the first version of a system, I know it will more than likely be a great thing to have in my back pocket for later. Maybe my view is skewed by the work I have been doing. Maybe it's true that this is wholly uneccesary for many systems. It's just hard for me to imagine at this moment.
I will admit that making good use of interfaces and factories can mitigate the difficulty of refactoring in this solution or another solution later. However, I think you could make the argument that these are also guesses about the future needs and I would argue they cause more cost and complication that the technique I have proposed.
>
> In addition, I see this as something that (barring the
> decease of the system) will almost always provide
> benefits down the road and often provide benfits
> immediately.
>
You are mixing two different things.
If the present system would benefit then there is no doubt that it should be used.
If the present system would not benefit or even cost more (for example due to complexity) and there is no known future reason to do it that way, then it should not be done that way.
Consider this case...
You are creating a small demonstration J2EE system for the first time. The current implementation does not need entity beans. If the demonstration system works then it will be expanded, and the the second release from the current one, but not the next one will need entity beans.
In the above why would one use entity beans?
1. Because a follow up release will need them.
2. Because as a demonstration system the learning experience from figuring out entity beans will help.
Consider this case....
You are creating a small J2EE system on a contract basis. You are an experienced J2EE developer. The current implementation does not need entity beans. There is a strong reason to believe that this system will not be expanded and it might not even be deployed (politics.) At the very least you have no idea what future direction the system might take.
In this case you do NOT use entity beans. The best design, with the knowledge you have, is that entity beans should not be used - so you don't use them.
You could of course use entity beans because you want to be "nice" to future developers. Of course that ignores the fact that there is at least some people, with demonstrated cases, that believe that entity beans are not always the correct solution in all J2EE implementations. And so, instead of helping those future developers, you have instead hindered them because they must now rework all of entity bean code that you put in. (And note that three years ago everyone thought that entity beans was the only solution.)
It is the above sort of "guessing" that developers love to do, and yet are invariably wrong.
> It is the above sort of "guessing" that developers
> love to do, and yet are invariably wrong.
It's a great example and I agree with you. I guess my question is do you think this applies to the suggestion I have made? Are there many cases where such a design doesn't provide any benefit now and is not known to be useful in the future? If it is included in a (wrong) guess, how could it negatively impact the future system?
Hi.This might help answer the question: http://www.martinfowler.com/bliki/AnemicDomainModel.htmlRegards,Lance
> > It is the above sort of "guessing" that developers
> > love to do, and yet are invariably wrong.
>
> It's a great example and I agree with you. I guess my
> question is do you think this applies to the
> suggestion I have made? Are there many cases where
> such a design doesn't provide any benefit now and is
> not known to be useful in the future? If it is
> included in a (wrong) guess, how could it negatively
> impact the future system?
Made me think - hate when that happens.
I don't know what I think now.
I know for certain that I have seen a number of developers who make small enhancements to almost everything that they touch. And insist that this is "good" because someone might need that in the future. And looking back I am rather certain that at least some of these people, although well intention, either did not know or just ignored the known future path of the product - because their enhancements would not be used by the known future path either.
I have also seen projects that were over designed. But at the time, although some of them made me uneasy, I could not have said for certain at the time why I thought they were over designed. And I could say the same for technology choices. I couldn't say why the choices were wrong, but neither could anyone else tell me why they were right. And in hindsight some of them were wrong.
I think it comes down to that a minimal choice whether in technology, design or implementation can never be wrong for what you are currently working on. And one should only choose to do more when one is sure that the choice will (not might) enhance the future of the product.
Lance, you have made my week. Love the Fowler reference!- Saish"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:28 >

> This might help answer the question:
> http://www.martinfowler.com/bliki/AnemicDomainModel.htm
Interesting article. However, I don't think that's what I am doing. It's hard to know exactly because there is no UML or anything (at least I didn't see any.)
Outside of the infrastructure (RMI handlers, DAOs, Assmblers,) the design I am proposing doesn't look any different that just including the data in the business object. It's really just a subtle indirection. Instead of "this.name", you are using "data.name" (you could make it a bean if public variables bother you). Classes using the business Object should not know that this indirection exists, nor should they care. In it's most basic form, it really isn't special at all. Also it's important to note that the business classes are inherently tied to the data classes. The business object is as coupled to the data as it would be to itself if it were just 'normal'.
But what it allows you to do some very powerful things with very little effort though I'll admit it does require some extra effort to protect your data Objects. Well, effort isn't exactly the word. You have to be rigourous in your design and implementation. The data class should be package-protected, for example.
I can only refer you again to Fowler:
The basic symptom of an Anemic Domain Model is that at first blush it looks like the real thing. There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models have. The catch comes when you look at the behavior, and you realize that there is very little behavior on these objects. Indeed often these models come with design rules that say that you are not to put any domain logic in the the domain objects. Instead there are a set of service objects which capture all the domain logic. These services live on top of the domain model and use the domain model for data.
It cannot be any more explicit. Listen, I have no philosophical problems with what you are doing. And there are cases where I see its utility. However, if you will not defer to one of the most eminent pattern experts on what he actually calls an *ANTI-PATTERN*, then there is not much point continuing debate.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:28 >

> Lance, you have made my week. Love the Fowler> reference!> > - Saish> > "My karma ran over your dogma." - AnonI aim to please :-)Lance
> It cannot be any more explicit. Listen, I have no
> philosophical problems with what you are doing. And
> there are cases where I see its utility. However, if
> you will not defer to one of the most eminent pattern
> experts on what he actually calls an *ANTI-PATTERN*,
> then there is not much point continuing debate.
I don't agree that this applies to what I am proposing as I already said. From outside the package my design proposal looks no different from what you are proposing. If my design were an anti-pattern yours would also be an anti-pattern.
i.e. there are no service objects in my design.
In fact, the if I used your design (the standard POJO design) our current work would require the addition of aservice objects. My proposal eliminates the need for Objects that "live on top of the domain model and use the domain model for data."
You're up to some antics again (sorry, coudn't resist the pun).
Read Fowler's English. Re-read your own posts. You may have the idea in your head as conceptually different, but you are, in fact, implementing an anti-pattern. You can say, "it's just another indirection." That statement is not mutually exclusive with the fact that you have implemented an anti-pattern.
He's not infallible. I definitely am not. Are there cases when an anti-pattern may, in fact, be the best solution? Sure. We have gone over this many times. But please don't recommend an anti-pattern as best practice.
Now, I don't want this to degenerate into what will basically be an argument. You are entitled to your own opinions. I'm entitled to mine. Fowler's entitled to his. He gets paid the big bucks for a reason though. It should at *least* give you pause.
Dozens of ways to skin a digital cat. I'm done with this one. I'm off to separate my leisure from my work responsibilities.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:28 >

> I can only refer you again to Fowler:
>
> The basic symptom of an Anemic Domain Model is that at
> first blush it looks like the real thing. There are
> objects, many named after the nouns in the domain
> space, and these objects are connected with the rich
> relationships and structure that true domain models
> have. The catch comes when you look at the behavior,
> and you realize that there is very little behavior on
> these objects. Indeed often these models come with
> design rules that say that you are not to put any
> domain logic in the the domain objects. Instead there
> are a set of service objects which capture all the
> domain logic. These services live on top of the domain
> model and use the domain model for data.
>
> It cannot be any more explicit. Listen, I have no
> philosophical problems with what you are doing. And
> there are cases where I see its utility. However, if
> you will not defer to one of the most eminent pattern
> experts on what he actually calls an *ANTI-PATTERN*,
> then there is not much point continuing debate.
>
I have seen a number of published anti-patterns. The one posted in the link lacks a significant amount of detail that I have seen in other more formal anti-patterns.
And you failed to quote the section where Fowler mentions that this anti-pattern reflects procedural programming. The "Anti-Patterns" book provides the anti-pattern called "Functional Decomposition" (which represents procedural programming) with specific things to look for. And none of those symptoms seem to be evident in any of the posts in this thread. Could you point to the specific reply or replies that suggested this?
Just wondering how this:
> The catch comes when you look at the behavior,
> and you realize that there is very little behavior on
> these objects. Indeed often these models come with
> design rules that say that you are not to put any
> domain logic in the the domain objects. Instead there
> are a set of service objects which capture all the
> domain logic. These services live on top of the domain
> model and use the domain model for data.
differs from the "separation of data and logic". Don't get hung-up on the word "services", think "classes". So if I re-translate that sentence:
These classes live on top of the domain model and use the domain model for data.
Now, I'm going to change "live on top of" to "encapsulate":
These classes encapsulate the domain model and use the domain model for data.
Now, I'm going to get rid of the parallel construction in the sentence and use more of your own wording:
These classes encapsulate the domain model, using indirection to access the data.
Unless I need to start taking better drugs, is this not exactly what you have been proposing?
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:28 >

Hi.
Much of the problem with this thread stems from the fact that many of the terms (some not explicitly used but implied - or maybe I inferred them incorrectly) are ill-defined and/or vaguely used:
1. What is 'business logic'?
2. What is an 'object model'?
3. What is a 'domain model'
4. What is 'data'?
5. What is an object.
6. What is a class?
7. What is a 'service layer' and how does the logic in that relate to 'business logic' if at all?
8. What is the meaning of life?
etc
I know answers to all of these questions except the last one which I don't really care about. I suspect all of you have answers too. Do we have the same answers? *That*, I don't know, and from the nature of this discussion, I suspect not.
Putting all that aside, taking something simple and concrete as an example: suppose we wanted to implement a collection. We decide that we want to be able to 'add' and 'remove' items from a collection and that items that are logically equal cannot coexist (attempts to add a logicailly equal item will not change the collection). Nice and easy.
Now how should we distribute the data and operations when implementing this collection? Should we
a) encapsulate both in a single class. We would do this if we believed in POJOs or if we believed in the 'separate data from business logic' notion but that the operations I've described were not implementing 'business logic'.
b) put the data in one class with no operations (except maybe accessors and dumb mutators) and the operations in another class. We would do this if we believed that the operations should be considered to implement 'business logic' and that this should be separated from the data.
c) Give up and go and learn a functional programming language to avoid the issue. Maybe.
Regards,
Lance
> Unless I need to start taking better drugs, is this
> not exactly what you have been proposing?
I'm not sre how significantly altering the statement Fowler wrote proves that my design is an example of what he is describing. My understanding of what he is talking about is specifically not encapsulation. So changing his statment to use encapsulates is completely misrepresenting what he is talking about.
Martin Fowler is not involved in this conversation and I don't feel that you speak for him. He is not here to confirm or deny your interpretation of this short and rather vague article. In addition I am unable to defend my idea to him.
Okay. I've done all I can. If you won't believe a bone-fide design guru or other posters here on this site, there's not much I can do.
As Schell has alluded to and explained better than I, if you don't *need* to develop code, your time will be far better spent on the code you do need to develop.
The fact that Lance is suggesting a procedural/functional language to overcome this issue points to how alien it is to normal, OO concepts.
Best of luck with your idea. When I come acrross a system where the algorithm changes frequently while the data remains constant, I will keep this anti-pattern in mind.
- Saish
"My karma ran over your dogma." - Anon
Saish at 2007-7-1 15:31:28 >

As you have quoted sections that you claim show he is speaking of the design I am proposing, I now will provide a quote that shows he is not speaking of what I am proposing:
"There are objects, many named after the nouns in the domain space, and these objects are connected with the rich relationships and structure that true domain models havep."
In my proposed design technique, there are no relationships in data classes. I know that I haven't made this clear so i will now. Specifically, references to any non-primitive-esque Objects is strictly forbidden. For example, if your model contained a Parent and Child classes, the ParentData class and the ChildData class would not have any associations to each other. Nor would a ParentData instance have references to the Child instances. These objects do not have "rich relationships" or "rich ... structure." They really should exist in a sub-Object domain.
> Okay. I've done all I can. If you won't believe a
> bone-fide design guru or other posters here on this
> site, there's not much I can do.
You continue to press your fallcious belief that you speak for Fowler. You have also ignored jschell's doubts that your interpretation is correct. I think it may be that you really don't understand what I am describing which is most likely my fault.
Your thinly veiled personal attacks are very unwelcome. Unless we can discuss the merits of our arguments and you can address the questions I have a about your interepretations of Fowler's article, there's not much for me to do.
> a) encapsulate both in a single class. We would do
> this if we believed in POJOs or if we believed in the
> 'separate data from business logic' notion but that
> the operations I've described were not implementing
> 'business logic'.
> b) put the data in one class with no operations
> (except maybe accessors and dumb mutators) and the
> operations in another class. We would do this if we
> believed that the operations should be considered to
> implement 'business logic' and that this should be
> separated from the data.
> c) Give up and go and learn a functional programming
> language to avoid the issue. Maybe.
Lance, these choices that you have proposed show me that indeed you are misunderstanding what I am saying. Maybe it would be more clear if I said that instead of separating the data from the business logic, I am suggesting encapsulating the data inside the business logic.
Similar to your hypothetical, let's take the ArrayList class (even though a Collection example is really not pertinent to this thread.) Inside the ArrayList you have a bunch of methods. Where is the data stored? The data is actually stored in a separate Object that the ArrayList instance encapsulates; an array. This is not a great example because arrays are special type of Object. The point is that this pattern of encapsulation is used all the time and I'm a little incredulous that it is being dscribed as procedural and an anti-pattern.
> Okay. I've done all I can. If you won't believe a
> bone-fide design guru or other posters here on this
> site, there's not much I can do.
>
> As Schell has alluded to and explained better than I,
> if you don't *need* to develop code, your time will be
> far better spent on the code you do need to develop.
We were talking about the same thing? I don't believe I was commenting on a type of design but rather how one should approach design and implementation in general.
And I wish someone would point out the reply or replies that specify a type of design to which the Fowler link would apply.
>
> The fact that Lance is suggesting a
> procedural/functional language to overcome this issue
> points to how alien it is to normal, OO concepts.
>
I don't see this point at all.
>
> Similar to your hypothetical, let's take the ArrayList
> class (even though a Collection example is really not
> pertinent to this thread.) Inside the ArrayList you
> have a bunch of methods. Where is the data stored?
> The data is actually stored in a separate Object that
> the ArrayList instance encapsulates; an array. This
> is not a great example because arrays are special
> type of Object. The point is that this pattern of
> encapsulation is used all the time and I'm a little
> incredulous that it is being dscribed as procedural
> and an anti-pattern.
I second that.
I'm going to post some code that will hopefully clear things up. Note that the code isn't meant to be great code but to show an example of the general design principle:
package employee;
public interface Employee {
int getId();
void setId(int id);
String getFirstName();
void setFirstName(String firstName);
String getLastName();
void setLastName(String lastName);
}
// -
import java.util.HashMap;
public final class EmployeeSupplier {
private static HashMap employees = new HashMap();
static
{
EmployeeData john = getData();
employees.put(new Integer(john.id), john);
}
public static final void main(String[] args)
{
Employee employee = getEmployee(1);
System.out.println(employee.getFirstName() + " " + employee.getLastName());
getWritable(employee).setFirstName("Jack");
System.out.println(employee.getFirstName() + " " + employee.getLastName());
}
public static Employee getEmployee(int id)
{
return new ReadOnlyEmployee((EmployeeData) employees.get(new Integer(id)));
}
public static Employee getWritable(final Employee employee)
{
if (getAccessLevel() <= 0) throw new SecurityException(); // just example
if (employee instanceof ReadOnlyEmployee)
{
return new ReadWriteEmployee(((ReadOnlyEmployee) employee).data);
}
else
{
return employee;
}
}
private static int getAccessLevel()
{
return 1;
}
private static EmployeeData getData()
{
EmployeeData data = new EmployeeData();
data.socialSecurityNumber = "000-00-0000";
data.id = 1;
data.firstName = "John";
data.lastName = "Smith";
return data;
}
}
// -
class ReadOnlyEmployee implements Employee {
EmployeeData data;
ReadOnlyEmployee(final EmployeeData data)
{
this.data = data;
}
public int getId() {
return data.id;
}
public void setId(int id) {
throw new UnsupportedOperationException();
}
public String getFirstName() {
return data.firstName;
}
public void setFirstName(String firstName) {
throw new UnsupportedOperationException();
}
public String getLastName() {
return data.lastName;
}
public void setLastName(String lastName) {
throw new UnsupportedOperationException();
}
}
// -
class ReadWriteEmployee implements Employee {
EmployeeData data;
ReadWriteEmployee(final EmployeeData data)
{
this.data = data;
}
public int getId() {
return data.id;
}
public void setId(final int id) {
data.id = id;
}
public String getFirstName() {
return data.firstName;
}
public void setFirstName(final String firstName) {
data.firstName = firstName;
}
public String getLastName() {
return data.lastName;
}
public void setLastName(final String lastName) {
data.lastName = lastName;
}
}
// -
class EmployeeData {
int id;
String socialSecurityNumber;
String firstName;
String lastName;
}
Actually a good example of something similar to this is in the StringBuffer.toString() method.
I think I'll conceed that this may be more work than I implied previously before someone else points it out. Point taken on 'over-designing' for some systems.
> Lance, these choices that you have proposed show me
> that indeed you are misunderstanding what I am saying.
Excellent. That's probably a sign that something significant might happen soon...
> Maybe it would be more clear if I said that instead
> of separating the data from the business logic, I am
> suggesting encapsulating the data inside the business
> logic.
Is the important point for you that you achieve this by extracting the fields into a class that behaves somewhat like a C style struct?
>
> Similar to your hypothetical, let's take the ArrayList
> class (even though a Collection example is really not
> pertinent to this thread.)
Why not?
> Inside the ArrayList you
> have a bunch of methods. Where is the data stored?
> The data is actually stored in a separate Object that
> the ArrayList instance encapsulates; an array. This
> is not a great example because arrays are special
> type of Object.
Yes, the ArrayList forwards certain messages to the array and provides additional logic to yield the ArrayList semantics.
> The point is that this pattern of
> encapsulation is used all the time and I'm a little
> incredulous that it is being dscribed as procedural
> and an anti-pattern.
I don't think I described it that way. If I did, I didn't intend to. I do have an opinion about this whole question but I'm trying to present the alternatives in an even and concrete way so that we're not talking across each other.
But I don't think the forwarding of messages is what you're talking about. This is classic OO. Am I correct in thinking that what you are proposing is essentially the use of C style structs, the access to which is controlled by some kind of wrapper/proxy and the references within which are only to wrappers/proxies of other structs?
Regards,
Lance
> Is the important point for you that you achieve this
> by extracting the fields into a class that behaves
> somewhat like a C style struct?
Possibly. It doesn't have to be a struct. The data Object could have non-business funtionality and not use public members. I'm not sure the public members is a good idea. I'm playing around with it.
> Why not?
I just don't think a Collection fits into a discussion about business objects but it's not a big deal.
> I don't think I described it that way. If I did, I
> didn't intend to. I do have an opinion about this
> whole question but I'm trying to present the
> alternatives in an even and concrete way so that we're
> not talking across each other.
The option c seemed to be a slight. If it wasn't, I'm sorry for interpreting it as such.
> But I don't think the forwarding of messages is what
> you're talking about. This is classic OO. Am I correct
> in thinking that what you are proposing is essentially
> the use of C style structs, the access to which is
> controlled by some kind of wrapper/proxy and the
> references within which are only to wrappers/proxies
> of other structs?
I'm not sure how this is not forwarding. Can you explain the disctintion you are making?
I don't follow "and the references within which are only to wrappers/proxies of other structs?" Are you saying the structs refer to other structs? The answer to that would be no. Relationships are not held in these data fields (at least not directly.)
> > Is the important point for you that you achieve this
> > by extracting the fields into a class that behaves
> > somewhat like a C style struct?
>
> Possibly. It doesn't have to be a struct. The data
> Object could have non-business funtionality and not
> use public members. I'm not sure the public members
> is a good idea. I'm playing around with it.
Experimentation is good.
>
> > Why not?
>
> I just don't think a Collection fits into a discussion
> about business objects but it's not a big deal.
OK. I lost track of the OPs question somewhere in the morass. I guess the question would be 'at what point do we draw the line between business objects and other kinds of objects?' Is this really a question about persistent objects and not about the rigourous separation of data and logic throughout a system.
>
> > I don't think I described it that way. If I did, I
> > didn't intend to. I do have an opinion about this
> > whole question but I'm trying to present the
> > alternatives in an even and concrete way so that
> we're
> > not talking across each other.
>
> The option c seemed to be a slight. If it wasn't, I'm
> sorry for interpreting it as such.
No slight intended. I think many problems could be solved more easily by switching paradigms to FP (LISP, Haskell, ML, etc). If we did that, then a whole different set of patterns come into play and makes this question go way completely. It would bring other questions, I'm sure. Together with this thought, I'm also finding my romance with statically typed languages is coming to an end. But that's just me.
>
> > But I don't think the forwarding of messages is what
> > you're talking about. This is classic OO. Am I
> correct
> > in thinking that what you are proposing is
> essentially
> > the use of C style structs, the access to which is
> > controlled by some kind of wrapper/proxy and the
> > references within which are only to wrappers/proxies
> > of other structs?
>
> I'm not sure how this is not forwarding. Can you
> explain the disctintion you are making?
Because of your earlier answers, I see that you are talking about something a bit richer than C style structs, so my paragraph above is not correct.
>
> I don't follow "and the references within which are
> only to wrappers/proxies of other structs?" Are you
> saying the structs refer to other structs? The answer
> to that would be no. Relationships are not held in
> these data fields (at least not directly.)
I was trying to make sure I understood your position by describing it back to you. What I meant was that the fields of structs may only be references to the wrappers/proxies of other structs, and may not directly reference other structs (i.e. you always have to go through the logic layer). Presumably though, from your earlier paragrpah, you're happy for the structs to refer to collections and other such things?
If this is all true, then isn't this discussion mainly about where we draw the line between the 'business logic' and the 'service layer' logic?
Regards,
Lance
> I was trying to make sure I understood your position
> by describing it back to you. What I meant was that
> the fields of structs may only be references to the
> wrappers/proxies of other structs, and may not
> directly reference other structs (i.e. you always have
> to go through the logic layer). Presumably though,
> from your earlier paragrpah, you're happy for the
> structs to refer to collections and other such things?
Well let me clarify. The structs should not refer to other 'business' objects directly or indirectly. For example if you have Parent, Child, ParentData, and ChildData, Parent encapsulates ParentData but ParentData does not refer to Child or ChildData. Parent would hold the reference to Child which would hold encapsulate ChildData.
> If this is all true, then isn't this discussion mainly
> about where we draw the line between the 'business
> logic' and the 'service layer' logic?
I don't really see that this has much to do with the Service layer. A service layer may be needed but these business Objects are not service layer components. Most of the system will not have any knowledge of the data Objects. Indeed my intent is for anything outside of the package in which they are declared to be forbidden from referring to them in any way.
> > If this is all true, then isn't this discussion
> mainly
> > about where we draw the line between the 'business
> > logic' and the 'service layer' logic?
>
> I don't really see that this has much to do with the
> Service layer. A service layer may be needed but
> these business Objects are not service layer
> components. Most of the system will not have any
> knowledge of the data Objects. Indeed my intent is
> for anything outside of the package in which they are
> declared to be forbidden from referring to them in any
> way.
OK. So s far as the rest of the system is concerned, each (XXX,XXXData) combination acts just like an XXX would be expected to, and there is no knowledge of the existence of the XXXData. The implementation has been successfully hidden. That's all fine and dandy.
Is there are one-to-one correspondence between XXX instances and XXXData instances? Also, is the XXXData instance the only thing that the XXX instance is allowed to hold a reference to?
Regards,
Lance
> >
> > Similar to your hypothetical, let's take the
> ArrayList
> > class (even though a Collection example is really
> not
> > pertinent to this thread.) Inside the ArrayList you
> > have a bunch of methods. Where is the data stored?
> > The data is actually stored in a separate Object
> that
> > the ArrayList instance encapsulates; an array. This
> > is not a great example because arrays are special
> > type of Object. The point is that this pattern of
> > encapsulation is used all the time and I'm a little
> > incredulous that it is being dscribed as procedural
> > and an anti-pattern.
>
> I second that.
And a third. All in favor?
> OK. So s far as the rest of the system is concerned,
> each (XXX,XXXData) combination acts just like an XXX
> would be expected to, and there is no knowledge of the
> existence of the XXXData.
Exactly.The only other classes aware of the Datas are various Assemblers and DAOs etc.
> Is there are one-to-one correspondence between XXX
> instances and XXXData instances?
Yes.
> Also, is the XXXData
> instance the only thing that the XXX instance is
> allowed to hold a reference to?
No. Like in the Parent Child example. The Parent would hold a reference to the Child class. You can *almost* think of the Datas as mapping to persistence but there is not neccesarily a one-to-one correlation and there may not even be persistence.
> > Also, is the XXXData
> > instance the only thing that the XXX instance is
> > allowed to hold a reference to?
>
> No. Like in the Parent Child example. The Parent
> would hold a reference to the Child class. You can
> *almost* think of the Datas as mapping to persistence
> but there is not neccesarily a one-to-one correlation
> and there may not even be persistence.
OK. But does a Parent have any fields other than a Child or are all of the 'would-be' fields of Parent pushed into Child?
i.e. would this be acceptable:
public class Parent {
private Child child;
private int something;
private Set someStuff;
...
}
Or would 'something' and 'someStuff' be moved into Child?
Regards,
Lance
> OK. But does a Parent have any fields other than a
> Child or are all of the 'would-be' fields of Parent
> pushed into Child?
I'm confused. Child is not the data class for Parent so I don't why you would move things to it unless there were some design reason. I think maybe you thought I meant Child was the ParentData class.
Maybe I should put it this way. Instances in a class are either attributes or associations for the purpose of this discussion.
That is, an instane either represents some sort of relationship to another business Object or it represents the properties of this Object. I'm taking anything that is a property and putting it in XXXData instance.
so in your example:
> public class Parent {
>private Child child;
>private int something;
>private Set someStuff;
>
>...
> }
child would be a relationship to an other business Object. Generally it would be a Collection because most of the time Parents can have more than one Child. Int something is probably going to go in ParentData becuase it's a property of the Parent. Where someStuff goes depends on whether it's holding associations or properties.
Saish said
>
> I don't see how having the business logic and data
> together confuses your design.
Since no one ever answered me I am guessing here, but is the above where this started?
If so, there is a reason that DTOs (and Value Patterns before that) exist.
And having spent years doing database layers using both relational and OO databases, the advantages of seperating the 'data' from the 'logic' is more than apparent to me. And when I first started I very definitely started with the 'data belongs to the object' view. And over the long term it just does not work.
> > OK. But does a Parent have any fields other than a
> > Child or are all of the 'would-be' fields of Parent
> > pushed into Child?
>
> I'm confused. Child is not the data class for Parent
> so I don't why you would move things to it unless
> there were some design reason. I think maybe you
> thought I meant Child was the ParentData class.
Yes, sorry. I misunderstood.
>
> Maybe I should put it this way. Instances in a class
> are either attributes or associations for the purpose
> of this discussion.
>
> That is, an instane either represents some sort of
> relationship to another business Object or it
> represents the properties of this Object. I'm taking
> anything that is a property and putting it in XXXData
> instance.
>
> so in your example:
>
> > public class Parent {
> >private Child child;
> >private int something;
> >private Set someStuff;
> >
> >...
> > }
>
> child would be a relationship to an other business
> Object. Generally it would be a Collection because
> most of the time Parents can have more than one Child.
> Int something is probably going to go in ParentData
> becuase it's a property of the Parent. Where
> someStuff goes depends on whether it's holding
> associations or properties.
OK.
Regards,
Lance
> Since no one ever answered me I am guessing here, but> is the above where this started?basically.
I couldn't help but notice the argument against using procedural methods to separate the data from the logic
Which reminds of my days as a video editor and the introduction of Non-Linear editing...
Even though you can edit together segments of video in a non-linear fashion, somebody has to make sure it makes sense from the beginning to end. I wish I had a better analogy.
How about... whether your using object oriented methodology, or resorting to the old fashioned procedural style of brute force... your still going to reach the same conclusion in the end.
The more organized you are, the more you understand how all of your individual shots relate to each other, the more likely your going to see the subtle interactions between each piece and how they can be shuffled around to create more impact. The more likely your going to see "The Big Picture".
Choosing to cut a film in a non-linear fashion will still have you creating the story in a procedural fashion. Otherwise, the story isn't going to make any sense in the end.
I know... Go watch, "Massacre Up North" if you think I don't know what I'm talking about.
Take a look at how useless half of the database abstraction layers are that are floating around out there.
It's either On or Off. 1 or 0. Organization/Separation makes it easier in the end.
Just my two crazy cents...
> Just my two crazy cents...After two-and-a-half years of interest, compounded annually. ;o)~