Active Record vs Objects

Posted by Uncle Bob on 11/02/2007

Active Record is a well known data persistence pattern. It has been adopted by Rails, Hibernate, and many other ORM tools. It has proven it’s usefulness over and over again. And yet I have a philosophical problem with it.

The Active Record pattern is a way to map database rows to objects. For example, let’s say we have an Employee object with name and address fields:
public class Employee extends ActiveRecord {
private String name;
private String address;
...
}

We should be able to fetch a given employee from the database by using a call like:

Employee bob = Employee.findByName("Bob Martin");

We should also be able to modify that employee and save it as follows:

bob.setName("Robert C. Martin");
bob.save();
In short, every column of the Employee table becomes a field of the Employee class. There are static methods (or some magical reflection) on the ActiveRecord class that allow you to find instances. There are also methods that provide CRUD functions.

Even shorter: There is a 1:1 correspondence between tables and classes, columns and fields. (Or very nearly so).

It is this 1:1 correspondence that bothers me. Indeed, it bothers me about all ORM tools. Why? Because this mapping presumes that tables and objects are isomorphic.

The Difference between Objects and Data Structures

From the beginning of OO we learned that the data in an object should be hidden, and the public interface should be methods. In other words: objects export behavior, not data. An object has hidden data and exposed behavior.

Data structures, on the other hand, have exposed data, and no behavior. In languages like C++ and C# the struct keyword is used to describe a data structure with public fields. If there are any methods, they are typically navigational. They don’t contain business rules.

Thus, data structures and objects are diametrically opposed. They are virtual opposites. One exposes behavior and hides data, the other exposes data and has no behavior. But that’s not the only thing that is opposite about them.

Algorithms that deal with objects have the luxury of not needing to know the kind of object they are dealing with. The old example: shape.draw(); makes the point. The caller has no idea what kind of shape is being drawn. Indeed, if I add new types of shapes, the algorithms that call draw() are not aware of the change, and do not need to be rebuilt, retested, or redeployed. In short, algorithms that employ objects are immune to the addition of new types.

By the same token, if I add new methods to the shape class, then all derivatives of shape must be modified. So objects are not immune to the addition of new functions.

Now consider an algorithm that uses a data structure.

switch(s.type) {
case SQUARE: Shape.drawSquare((Square)s); break;
case CIRCLE: Shape.drawCircle((Circle)s); break;
}
We usually sneer at code like this because it is not OO. But that disparagement might be a bit over-confident. Consider what happens if we add a new set of functions, such as Shape.eraseXXX(). None of the existing code is effected. Indeed, it does not need to be recompiled, retested, or redeployed. Algorithms that use data structures are immune to the addition of new functions.

By the same token if I add a new type of shape, I must find every algorithm and add the new shape to the corresponding switch statement. So algorithms that employ data structures are not immune to the addition of new types.

Again, note the almost diametrical opposition. Objects and Data structures convey nearly opposite immunities and vulnerabilities.

Good designers uses this opposition to construct systems that are appropriately immune to the various forces that impinge upon them. Those portions of the system that are likely to be subject to new types, should be oriented around objects. On the other hand, any part of the system that is likely to need new functions ought to be oriented around data structures. Indeed, much of good design is about how to mix and match the different vulnerabilities and immunities of the different styles.

Active Record Confusion

The problem I have with Active Record is that it creates confusion about these two very different styles of programming. A database table is a data structure. It has exposed data and no behavior. But an Active Record appears to be an object. It has “hidden” data, and exposed behavior. I put the word “hidden” in quotes because the data is, in fact, not hidden. Almost all ActiveRecord derivatives export the database columns through accessors and mutators. Indeed, the Active Record is meant to be used like a data structure.

On the other hand, many people put business rule methods in their Active Record classes; which makes them appear to be objects. This leads to a dilemma. On which side of the line does the Active Record really fall? Is it an object? Or is it a data structure?

This dilemma is the basis for the oft-cited impedance mismatch between relational databases and object oriented languages. Tables are data structures, not classes. Objects are encapsulated behavior, not database rows.

At this point you might be saying: “So what Uncle Bob? Active Record works great. So what’s the problem if I mix data structures and objects?” Good question.

Missed Opportunity

The problem is that Active Records are data structures. Putting business rule methods in them doesn’t turn them into true objects. In the end, the algorithms that employ Active Records are vulnerable to changes in schema, and changes in type. They are not immune to changes in type, the way algorithms that use objects are.

You can prove this to yourself by realizing how difficult it is to implement an polymorphic hierarchy in a relational database. It’s not impossible of course, but every trick for doing it is a hack. The end result is that few database schemae, and therefore few uses of Active Record, employ the kind of polymorphism that conveys the immunity of changes to type.

So applications built around ActiveRecord are applications built around data structures. And applications that are built around data structures are procedural—they are not object oriented. The opportunity we miss when we structure our applications around Active Record is the opportunity to use object oriented design.

No, I haven’t gone off the deep end.

I am not recommending against the use of Active Record. As I said in the first part of this blog I think the pattern is very useful. What I am advocating is a separation between the application and Active Record.

Active Record belongs in the layer that separates the database from the application. It makes a very convenient halfway-house between the hard data structures of database tables, and the behavior exposing objects in the application.

Applications should be designed and structured around objects, not data structures. Those objects should expose business behaviors, and hide any vestige of the database. The fact that we have Employee tables in the database, does not mean that we must have Employee classes in the application proper. We may have Active Records that hold Employee rows in the database interface layer, but by the time that information gets to the application, it may be in very different kinds of objects.

Conclusion

So, in the end, I am not against the use of Active Record. I just don’t want Active Record to be the organizing principle of the application. It makes a fine transport mechanism between the database and the application; but I don’t want the application knowing about Active Records. I want the application oriented around objects that expose behavior and hide data. I generally want the application immune to type changes; and I want to structure the application so that new features can be added by adding new types. (See: The Open Closed Principle)

A Rational Plan to Start using SOA 51

Posted by Uncle Bob on 10/21/2007

Many companies are thinking about adopting SOA as a way to reduce the cost of enterprise development. The thought of diverse and reusable services, effortlessly communicating through an intelligent Enterprise Service Bus is a powerful siren song for executives who see their development and maintenance budgets spiraling upwards. What’s more, vendors are displaying savory looking wares that promise to ease the transition.

Caveat Emptor!

The reality is that cramming an old and rickety enterprise system into services that communicate over a complex buss, is not an easy job. The long and short of the problem can be seen in the following catch-22:

The benefit of SOA comes from the decoupled nature of the services. But in order to create an SOA you have to decouple your services.

Decoupling your services is the issue. Once you have decoupled them, then all the wonderful tools might be useful in facilitating an SOA. On the other hand, if you have decoupled your services, you probably don’t need all those wonderful tools.

I have a client that has implemented SOA to good effect. They avoided the vast majority of the tools. For example, they are not using a big expensive buss. They aren’t using a BPEL engine, or message translators, or routing services. About the only thing they have decided to use is SOAP.

They are creating their services from scratch, and wiring the system together manually. Each service knows where each of it’s client services is. There is no registry service, no common dictionary, no fancy routing.

The system is simple, elegant, and it works. It was designed to work from the start. It is not an old crufty system crammed under a soap layer and called a service provider. Rather it is a nicely arrayed suite of services that were designed to work together from the get-go.

And that’s really the moral of the story.





Comments

Leave a response

  1. Avatar
    Andy P 40 minutes later:

    I think this is exactly why I had difficulty when I got assigned to a RoR project. I had an idea of how the objects should work, test drove a nice (well, ok) design and then ran up against how to integrate it into AR.

    I would be very appreciative if you could post a follow up on how you would approach bringing AR in as a halfway point between the business object model and the database.

  2. Avatar
    Steve about 1 hour later:

    So, if I had a Order with OrderLines. Two active record classes.

    They should be wrapped in an ‘BusinessOrder’ class that uses Order/Orderlines as CRUD – the business logic for an order is in BusinessOrder, not in the Order/Orderlines objects.

    Am I understanding this correctly?

  3. Avatar
    Joe about 2 hours later:

    What about the large number (at least everywhere Ive been) of applications that are primarily CRUD with very little domain logic? Would you still split the ActiveRecord out?

  4. Avatar
    Scott Bellware about 2 hours later:

    “On which side of the line does the Active Record really fall? Is it an object? Or is it a data structure?”

    True. It is indeed a data structure or an object.

    “the algorithms that employ Active Records are vulnerable to changes in schema, and changes in type”

    When the schema changes in a data-centric app, the behaviors are necessarily going to change. In a data-centric app, the data is a large part of the domain’s identity. It makes sense that these changes happen.

    “Those objects should expose business behaviors, and hide any vestige of the database”

    Yeah, we can do that, but the cost of making the abstractions that leak-proof would often be prohibitive, unless you’re dealing with a domain with relatively high complexity where applying that much sealant might make the difference between success and failure.

    “it makes a fine transport mechanism between the database and the application; but I donÂ’t want the application knowing about Active Records.”

    Object-oriented approaches (DDD, for example) are good for tackling complexity. When you don’t have that much complexity to deal with, fall back and DTSTTCPW.

  5. Avatar
    Ian Cooper about 2 hours later:

    I’m yet to be convinced that Active Record is the simplest thing. How is it simpler than separating persistence concerns into an infrastructure service that we clothe in a repository, assuming that we have frameworks in both cases that do the heavy lifting for us around object-relational mapping. Aren’t we just changing where the implementation lives?

  6. Avatar
    Eric about 2 hours later:

    I’m working on a Rails app at the moment where I think this would come in handy with a few design issues I’m having, but I’m missing an implementation step ( I think).

    For example. Let’s assume I’ve got your typical Rails MVC setup for a people table. The Model is Person, the controller PeopleController, and the views all stored in the People directory. The controller has methods like person.save! and person.destroy. Now we want to introduce a new layer, so that the Controller deals with a true object, and removes any vestige of the database. What would I name the layer? After all it’s still a Person. You could argue that it’s more a Person than the active record Person, so maybe it should be the model Person with another class called PersonRecord. All the business logic is in Person, and all the database logic is in PersonRecord. Then who calls save? If the controller calls save on person, and person delegates it to PersonRecord, then we haven’t removed database concerns from the application. If the controller doesn’t call save, and Person hides that, then when do saves get called. On every change? This doesn’t even account for the fact that if I did this in my hypotehtical Rails app I’d likely lose a lot of help, as Rails relies on naming conventions to provide it.

    The fact is I agree with the ideas behind the essay, so I’m going to try and implement it anyway to solve the real world issue I’m having now, but I’m concerned I’ll be adding extra complexity to the app, and implementing it wrong. Like Steve I may need an example to fully get it.

  7. Avatar
    Sebastian Kübeck about 4 hours later:

    Bob! You’r perfectly right to have a problem with ARs.

    > It has proven it’s usefulness over and over again.

    Are you really serious about this? For me, one of the most important parts in your book “Agile Software Development” is the suggestion to start developing the logic before designing the database schema. I proved that for myself in three projects. The schemata turned out to be quite diffrent than we’d expected before, however, they have proven their value ever since.

    ARs are quite the opposite of that as they tightly couple the database to the code. Eventually, the database will take hostages. First the application, then each developer working with it. Finally, you spent your time arguing for weeks or even months with database people for even the tiniest change the now “sacret” schema.

    To Eric: Did you ever see a person “save” or “destroy” themselves? How many persons you know have business logic inside? What would a person controller look like or do? ;-)

  8. Avatar
    Daniel Cadenas about 11 hours later:

    I think Active Record’s problems come from implementing it from the beginning of your project which has the risk of biasing your design towards a weak domain model. You will tend to make design decisions that fit well with Active Record and it will be more difficult to realize you should be refactoring towards having a domain model.

    You can’t be sure whether your app will be really data-centric until it’s finished and the most flexible design to cope with this doubt is starting with the simplest domain model. If at the end it gets anemic and you don’t find it’s behaviour outside, possibly in a service layer, then you can substitute it with the data layer, which could be Active Record.

    So like Martin’s idea of considering the datalayer as an implementation detail. It may be an important detail, but details don’t belong to abstractions, and if you mix them you fix’em (sorry couldn’t avoid that).

    It’s easier to start flexible and then tighten than start tight and then get flexible.

    So I think it’s easier to add Active Records to your domain models than adding a domain model to your Active Records. And you’ll have the advantage that you are not tied with a particular Active Record implementation.

    I’d use a pure AR solution only if I’m very very sure that I’m dealing with a simple CRUD that won’t change in the future, and even then I’d feel uncomfortable. The application may be data centric now but you can’t be sure if it will keep being that way in the future. You don’t know that even if you are the only client of the app.

  9. Avatar
    Eric Smith about 11 hours later:

    Did you ever see a person “save” or “destroy” themselves? How many persons you know have business logic inside? What would a person controller look like or do? ;-)

    To Sebastian: No I sure haven’t – but I clearly at some point the data must get saved to the database. Try as I might to avoid that in the controller, and admittedly real life is more complicated than my contrived example, is not simple and causes me to do some things I’m not 100% comfortable with. I’m going to have to continue to work with this idea.

  10. Avatar
    Jaime Metcher about 12 hours later:

    Bob,

    I agree with your distinction between objects and data structures, although I don’t see a problem with objects being used as data structures with respect to some operations and objects with respect to others. The Visitor pattern is largely a way to get inside an object and treat it as a struct.

    However, wrt the notion that ARs should not be exposed to the application, I would assert that the application actually can’t know whether it’s dealing with ARs or “very different kinds of objects”. The two may be identical in interface. Therefore it’s entirely legitimate to start with a domain model of ARs, and evolve selected classes towards more sophisticated patterns as required. In fact, the decision to make a class persistable should be able to be deferred or changed without disruption to the domain model.

    The definition of AR seems to be entirely in terms of implementation – the under the hood fact that instances map to rows and properties map to columns. The existence of save(), findby…() methods etc. merely implies the existence of a shared global namespace, of which an RDBMS is only one example. The save() method may be trivially generating a SQL insert statement from the property list, or it may be an entry point into arbitrarily complex mapping code – makes no difference to the application.

    So, while it’s strictly true that algorithms that use AR’s are vulnerable to changes in schema, it’s trivial to decouple an AR from the schema – at which point it’s no longer an AR. Your point remains valid, but maybe it’s not so important to choose up front.

    Jaime Metcher

  11. Avatar
    Jaime Metcher 1 day later:

    Eric, Sebastian: can a person “save” or “destroy” themselves? Absolutely yes. This is not about philosophy, it’s about information. A person “saves” themselves into various domains when they register to vote, sign up for a mailing list, sign a petition, apply for citizenship. We could come up with all sorts of cute analogies where the immigration clerk is the DAO, etc., but the basic point is that these things are initiated by the person (and indeed some can only be initiated by the person themselves).

    What makes an object transient is not that it ceases to “exist”, but that it ceases to be addressable – a “transient” object may live on for decades in some paging file on a tape in a vault somewhere, but good luck finding it. Similarly, a person with no registration of birth, citizenship papers or bank accounts may live a long and full life, but they do not exist in a “persistent scope” and therefore can’t be found by anybody else.

  12. Avatar
    Torbjörn Kalin 1 day later:

    Bob,

    I’m not sure whether to agree with you or not as I see problems with both solutions.

    With your solution, assume that your database contains a table called Employee. Assume also that you want to have a business object called Employee. The result is duplication: you will have two classes containing the same fields. It exhibits the Fowler code smells “Parallel Class Hierarchy” and “Shotgun Surgery”.

    Besides, I thought it was generally agreed that the DTO pattern is an anti pattern.

  13. Bob,

    I think that Active Record as merely an entry point to the hey-i-have-to-save-that-thing concept is a good approach. Fowler’s definition is too tight and I advocate for an AR that is merely an opposite to the Data Mapper pattern (instead of having another class to do your ORM stuff do it on the class to be persisted).

    By the way, Hibernate does not imposes or even suggest ARs, it works with both mappers and ARs.

    Cheers

  14. Avatar
    Dagfinn Reiersøl 4 days later:

    May I point out that in Fowler’s terminology, an Active Record by definition contains domain logic. If there’s no domain logic, it’s a Row Data Gateway. It may be unfortunate that Rails (and some semi-clones such as a few PHP frameworks) has been based on Active Record. Working in PHP, I’ve always preferred Data Mapper and I think Fowler has confused everyone by claming it’s more complex than Active Record. Its inherent complexity is only marginally greater. Active Record violates the Single-Responsibility Principle for no good reason.

  15. Avatar
    Kevin Teague 6 days later:

    Yes, ActiveRecord bends my head trying to make it fit into a clean mental model of an application. Rails uses a MVC architecture, Views and Controllers are for dealing with creating the user interface, so that only leaves a Model component for everything else, which is why you often hear Rails developers say, “Fat models are good”.

    If you want to see an example of framework that cleanly makes the distinction between “data components” and components that are “purely behavioural but explicitly specify what types of data sets they can add behaviour too”, then take a look at Grok.

    Grok also gives you clean distinctions between objects that can create new objects and objects that are just there to hold data. Grok by default uses the Zope Object Database (ZODB), a transparent object store, so you can sub-class your Schema classes to your hearts content, organize your objects hierarchically, and not have to think twice about polymorhpic associations and single-table inheritance and ORMs and all that junk.

  16. Avatar
    Marc Vangrieken 6 days later:

    Bob,

    This is definitely an interesting article and I think you are very right to say that there’s a lot of confusion about this subject.

    “Stand alone” Active Record is very good for simple scenarios and a lot of ORM tools are doing a great job providing/enabling them. In other cases however, the active records should serve as a lower level layer for building a business layer on top of. But, as stated in some comments, developers tend to cling on the AR paradigm to much when starting the BL. Like Andy P, I’d also like to see so a follow up post on this.

  17. Avatar
    pete w 6 days later:

    There is certainly a lot of confusion on this aspect. I think the confusion comes from the fact that objects are somewhat married to their knowledge of persistence.

    You have persistence concerns, and object concerns, and you want to separate them away in as clean a fashion as possible.

    If you ever want to read about .NET specifics on this I wrote up a rough blog post here: http://www.acceptedeclectic.com/2007/11/architecture-confusion-with-orm.html

    just my take on it, though.

  18. Avatar
    Paul Beckford 7 days later:

    I agree with everything here except the conclusion. You want to make the application emune to data (type) changes, but what if he application itself is data centric?

    Immunity to polymorphic changes in behavior based on a common encapsulated data set is the OO way, but most CRUD applications have little behavior in my experience. They are all about the retrieval, presentation and storage of data (state). Beyond this there is no (or very little) behavior at all.

    LINQ is interesting. A relational database record is in fact an hashmap (set of name, value pairs), that has no behavior. Relational database applications are therefore data centric.

    Coming back to the open/closed principle, I cannot see how you could achieve immunity to data (type) changes in a data centric application. So why not forget objects and data encapsulation, and just use data records (hashmaps) instead? A CRUD application is all about data structures and different data representations (database records, UI models and views). Changing the data changes everything.

    Perhaps Objects just don’t fit here and a functional approach like LINQ is a more natural fit?

    (BTW. You’ve got yourself to blame for my “back to basics” thinking, I went on one of your OO Design courses many years ago, and the thing I took away is your idea of tying everything back to first principles. Thanks Uncle Bob :^))

    Paul.

  19. Avatar
    Jonathan Allen 11 days later:

    Can you think of a single object you have ever used that didn’t expose its fields, either directly or via properties?

    Likewise, can you think of any data structure that doesn’t have functions or methods that work against it?

  20. Avatar
    Hiram Chirino 12 days later:

    You say: “In languages like C++ and C# the struct keyword is used to describe a data structure with public fields. If there are any methods, they are typically navigational. They don’t contain business rules.”

    Actually, the only difference in C++ between a struct and a class is the default visibility of the members.

  21. Avatar
    unclebob 15 days later:

    and the default visibility of inheritance. Structs assume public inheritance, and classes assume private. (Some folks have argued that C++ classes should default to public inheritance and private variables, whereas C++ structs should default to private inheritance and public variables!)

  22. Avatar
    unclebob 15 days later:

    Can you think of a single object you have ever used that didn’t expose its fields, either directly or via properties?

    Sure. Take the example of a geometric line. The variables held by this line are P1 and P2, the two points that define the line. These points never appear at the interface other than in the constructor, because they are utterly irrelevant to the mathematics of the line. The kinds of questions we ask of a line never require an answer related to P1 or P2.

    Likewise, can you think of any data structure that doesn’t have functions or methods that work against it?

    Generally a data structure will have some functions that operate on it. However, in many systems you will find functions that operate on more than one data structure at a time. These are not easily translated into methods of one or another of the data structures.

  23. Avatar
    unclebob 15 days later:

    but what if he application itself is data centric?

    I’m not sure I know what a “data centric” application is. Applications always operate on data, and data is always operated upon by applications. Applications are collections of behaviors that operate on data.

    Perhaps you are thinking of CRUD applications. But CRUD is still a set of behaviors.

    In any case, I don’t want to make applications immune from type changes so much as I want to make application immune from the most likely kinds of changes. If functions are more likely to change than data types, then a procedural style may be more appropriate. If data types are more likely to change then an OO style may be more appropriate.

  24. Avatar
    Colin Jack 16 days later:

    To my eye the main (though far from only) reasons you want to expose state (even through properties) are for display or persistence.

    As you say using Active Record objects in a DB mapping layer allows flexibility in your object design. Having said that many ORMs allow mapping to fields anyway and I’ve found they map inheritance/composition quite nicely too so I can usually create the domain model I want without having the extra layer.

    Equally when displaying your domain model to the user you need some way of exposing the data. Some people handle this by exposing presentation DTO’s (or a proper Fowler Presentation Model). This does provide a lot of flexibility, especially if you use mapping, but ultimately your domain object still need to expose their state. The thruth is I’m not sure that there is much you can do about this unless you get your domain objects involved in their own presentation.

    Anyway I agree with some of the earlier comments, to me Active Record is somewhat unappealing and I usually prefer to go for a more DDD focussed approach.

  25. Avatar
    Joe Reddy 19 days later:

    In a nutshell, I see nearly every common business application as a combination of at least two separate functions: Business and Maintenance. Active Record is good for maintenance (e.g. I need to update a person’s name). Objects (more specifically. Business objects) are good for business (e.g. I need to calculate projected sales).

    I will also add that in my world I stress that business objects are immutable where active records clearly are not.

    I have blogged about this very topic, if you are interested:http://swcses.eponym.com/blog/_archives/2007/2/26/2766594.html

  26. Avatar
    Paul Beckford 24 days later:

    Hi Bob,

    In any case, I don’t want to make applications immune from type changes so much as I want to make application immune from the most likely kinds of changes.

    I agree. I think this is the point. So back to CRUD. Have you ever tried adding another column to a database table in a CRUD application? The change ripples all the way through to the html view. No immunity to type change here at all.

    It seems to me that the behavior is the immutable thing (CRUD) and the data types are the things that change all the time. Thats why making behavior (functions) the central abstractions is perhaps a better bet, and why I think LINQ is interesting.

    Perhaps with our current focus on ORM, we’ve been barking up the wrong tree?

    Paul.

  27. Avatar
    William Martine Pomares. 5 months later:

    Hello Bob. I found this blog from Paul Beckford’s blog. I posted a comment there since this is an interesting discussion.

    And, reading your blog, the first thing that draws my attention is your definition of Active Record, as a way to map Database Rows to Objects. Looking at it in that way, I may say AR fails since, as you mention, OO is closed.

    But I prefer to look at it with a change of direction: It may allow the objects to wrap behavior around data. Reading the other comments, I see people trying to work with a domain concept (call it person) as an object/record mix, and there the new and destroy and find methods don’t fit as a person behavior!. Of course! But those methods do fit as data behaviors!.

    Think of a record as a data object (an object modeling the record concept in the database domain), and the behavior would be actually methods like find and update. Think, that object IS NOT a person, but a record. Person and Record belong to very different domains, and should not be mixed.

    So, what is the solution? A person is an object that lives in the problem domain and is used to find a solution. That whole model may need persistence, a database. That is another model underneath, and totally “disconnected”. So, person should not be performing data processing behavior, not should it be confused with a record! Person should request information to an information provider object, and that one should be calling the database world to request data processing. Complete separation.

    Now, you can change the data model without impacting the business logic solution domain!.

    How do you process data? Stored procedures is one option. But if you want to have a solution in one language, then native queries may be the answer. And those include AR and LinQ, for instance.

    I will be blogging about this some more, it is very interesting,

    William Martinez Pomares.

    blog.acoscomp.com
  28. Avatar
    William Martine Pomares. 5 months later:

    Hello Bob. I found this blog from Paul Beckford’s blog. I posted a comment there since this is an interesting discussion.

    And, reading your blog, the first thing that draws my attention is your definition of Active Record, as a way to map Database Rows to Objects. Looking at it in that way, I may say AR fails since, as you mention, OO is closed.

    But I prefer to look at it with a change of direction: It may allow the objects to wrap behavior around data. Reading the other comments, I see people trying to work with a domain concept (call it person) as an object/record mix, and there the new and destroy and find methods don’t fit as a person behavior!. Of course! But those methods do fit as data behaviors.

    Think of a record as a data object (an object modeling the record concept in the database domain), and the behavior would be actually methods like find and update. Think, that object IS NOT a person, but a record. Person and Record belong to very different domains, and should not be mixed.

    So, what is the solution? A person is an object that lives in the problem domain and is used to find a solution. That whole model may need persistence, a database. That is another model underneath, and totally “disconnected”. So, person should not be performing data processing behavior, not should it be confused with a record! Person should request information to an information provider object, and that one should be calling the database world to request data processing. Complete separation.

    Now, you can change the data model without impacting the business logic solution domain!.

    How do you process data? Stored procedures is one option. But if you want to have a solution in one language, then native queries may be the answer. And those include AR and LinQ, for instance.

    I will be blogging about this some more, it is very interesting,

    William Martinez Pomares.

    blog.acoscomp.com
  29. Avatar
    Morten Lyhr 11 months later:

    You can read my view on Data Structures and Encapsulaed Objects here: http://morten.lyhr.dk/2008/10/data-structures-vs-encapsulation.html

  30. Avatar
    Eliot Sykes about 1 year later:

    Hi Bob,

    I’m enjoying reading Clean Code. I’m learning a lot from it – thank you for this fantastic resource.

    Would you be willing to take some time to provide an example to show a way on how to use Objects and Active Records together?

    This is the only part of the book I’m having trouble working out what an implementation might look like.

    Kindest regards,

    Eliot

  31. Avatar
    itzco about 1 year later:

    Hello Bob,

    Very interesting subject, I’m personally not a fan of frameworks using AR for many reason, I think these concepts become popular because: a) Many developers have come to consider an application a set of CRUD pages, b) Frameworks have as you mention messed up concepts and because they facilitate work and make programming faster (for simple apps at least) developers accepted it c) Not every developer have the knowledge and perspective

    Perhaps I’m lucky or unlucky but most applications we develop have hundreds to thousands of lines of pure business rules.

    I have myself made a PHP framework (MVC) and we currently use this concept:

    Model. This is an independent object (no inheritance forced), it can just facade a complex object model to expose the methods the controller and the view need, it can get/access any of the other objects that makes the model and any DAO’s to get data. For CRUD applications (generator makes them): You can make it child of CRUD_model and declare a DAO type (Crud_model will just pass the calls to DAO in this case but it makes the difference clear, new methods with BR are added to the Model, new methods for data access are placed in the DAO)

    DAO. The Data Access Object are in charge of all data operations, save, update, find, get, delete, exist, etc; it’s like the manager, person_DAO, then a person doesn’t destroy itself, even better doesn’t find itself!

    VO. Value Objects are simple data structures that represent a record, DAO gets and returns DAO’s for most actions $person_DAO->save($person_VO);

    VO properties normally match DB fieldnames, but they can be mapped in case of change, i.e. DB.I_NAME ~ VO->EmployeeName

    DAL. DAO runs on top of a DAL to access many DB’s

    Don’t know if this is better, but I think it keeps it clean in between an object with BR, the manager and the data structure/record

    Best regards,

    Itzco

  32. Avatar
    buurtnerd about 1 year later:

    Hi I crafted another ORM layer that uses the anemic domain model. As I see it the Anemic Domain Model is a perfect tool to communicate with the database. In a sense the Anemic Domain Model serves the world of OO by providing a robust and very uniform object centric interface to the database. I agree however that these objects should not (always) be used for the business layer (I mean the layer that contains classes that express specific behaviours). Personally I favour wrapping the beans in complex models that use these beans and other repository tools to facilitate database interaction. So in the end, classes that ‘talk’ to these models will have no awareness of the database structures.

    I think that this pattern is often poorly understood and educated, I find myself having trouble to detect the smell properly; if you look closely at projects the symptoms can be spotted but that’s hard. When I see helperEmployee, EmployeeController or EmployeeManager I see anemic traits. What do you think about this?

    And.. if you are using an MVC architecture; does this mean that all classes that are not part of the C or V layer are models? What about mediators, facades etc? How should one classify these structures. The exhibit behaviour; but no data? Are they also non-oo?

    Another frustrating issue is the single responsibility principle. Many Anemic Domain advocates (including me sometime ago… sorry uncle Bob ;) ) claim (and they are right about that I think) the Anemic Domain Model implements SRP very well. by the way my own ORM is RedBean:http://www.redbeanphp.com—its a virtual orm layer; meaning it designs its own database based on your code.

  33. Avatar
    jwm over 2 years later:

    I see no mention of opaque data objects – something you can do in C using typedef and struct, where in a header file (the API):

    typedef struct my_opaque_data my_opaque_data;

    and the you define the struct in the implementation. This is common practice, and the methods typically use a naming convention such as:

    my_opaque_data* my_opaque_data_new(void); void my_opaque_data_free(my_opaque_data*);

    Tell me which exposes more in the API, this or C++ classes?

  34. Avatar
    cheap vps over 3 years later:

    I see no mention of opaque data objects – something you can do in C using typedef and struct, where in a header file (the API):

    typedef struct my_opaque_data my_opaque_data;

    and the you define the struct in the implementation. This is common practice, and the methods typically use a naming convention such as: cheap VPSmy_opaque_data* my_opaque_data_new(void); void my_opaque_data_free(my_opaque_data*);

    Tell me which exposes more in the API, this or C++ classes?

Comments