ColdFusion Domain Objects, Static Methods & a Common API

I decided before Christmas break that I really want to learn a couple new languages. I decided on picking up Groovy/Grails & Python. Now obviously I am not going to pick this up in a week but over the next year I want to get good with both of these languages. This has nothing to do with ColdFusion, in fact my passion for CF is really driving this. It’s important to understand how other languages tackle problems in case you find yourself stuck in a similar situation.

I have been doing a lot of work lately with Hibernate in ColdFusion 9. As I write more and more code I realized that I was writing the same functionality over and over for each of my domain objects. For the purpose of this article lets use an e-commerce application. When your working with anytime of application you must identify the domain specific objects in your system. In our e-commerce application we could have (but not limited to) the following objects.

  • Product
  • Category
  • Order
  • Invoice
  • Customer

Now we have an idea of what is going to make up my system I am going to start building out my domain objects and views. To keep it very simple I started out without incorporating any type of framework. For each of my domain objects I found out that there was common functionality between them. Here is a list of (but not limited to) some of the methods I need to perform on each object.

  • New – I will create a new instance of the domain object.
  • Load – I will load an existing object from a database based on the primary key.
  • List – I will give you back a query of all the rows for this domain object.
  • ListBy – I am a dynamic search that allows you to search by fields.
  • Find – I will find rows based on hql
  • FindBy – I am a dynamic finder that allows you to find exact matches dynamically (findByFirstAndLast(“Dan”,”Vega”))
  • Save – I will persist an object to the database.
  • Delete – I will delete a row(s) from the database.

So now I have a list of methods that each domain object will use. On my first attempt I create a Service level component for each domain object.

The real problem with this approach is that if an implementation of a method changes you need to change it in every domain object. Thanking along those lines my next stab at it was to create an abstract service level object that contained all of these methods that each of these domain objects would extend. Based on the entity attribute of the class my abstract service level would know which entity we would are working with. The great thing about this approach is our product service can now focus on the business logic that it needs to perform.

So that really started to work out well until I started looking at some other languages and really taking a like to how they approach it. My problem now is that I understand I need a place for this common functionality but I am not really sure on where it should go. Right now I store a static instance of the service level component in the application scope and then I can perform method calls like this. The

Lost in all of this is what a traditional service level object is used for. Typically a service level is used in an MVC framework to delegate common functionality. This helps us practice DRY (Don’t Repeat Yourself) and cut down on controller bloat. In our e-commerce application we have an example of where this would fit. Say we need to email a invoice to both the customer and the store owner. We could create that functionality in 2 different places but that really does not make sense. The better solution would be to create an invoice service. This service component would have a send invoice method that accepts an invoice id and email address. Now we have common functionality in one place and we could pull that service level object into both our Store and Customer controllers. So typically that is what we use a service level for and I think that is what is causing some confusion for me.

There have been some suggestions that this functionality belongs on the domain level. While that approach works for methods like save and delete it really does not work for the others. I want to look at example of why that is. I have a product entity with a save and delete method that knows how to save/delete itself.

Now when I create a new product and set some attributes I can just call save on itself.

As we can see that works out great but if we sprinkle some of the other methods I talked about earlier in our domain object. Now I am going to add a new method list that will give me back an array of objects.

Do you see the real problem with this? To get a list of products we need to create an instance of our product entity. We don’t need an instance here because we are not working with a single instance object. The question I threw out there is what if ColdFusion had a static method?

We then could call our list method on our domain object like this without ever needing to instantiate the product domain object.

I would like to conclude this article by emphasizing that this is not a why does one language do this and this one does not. ColdFusion certainly does some amazing things very well and other languages to take notes. I just find myself asking these types of questions when learning other languages. And with all of that said this was a very selfish article. I need to find out from all the smart developers out there on how I can solve my problem. I know I have common functionality that all my domain objects need and I know that each business object will have its own business logic. So where does it go?

Categories: Uncategorized

About The Author

My name is Dan Vega and I am a Software Developer based out of Cleveland OH. I love to play with new technologies and write about my experiences here. When I am not busy being a full time geek I love to lift heavy weights and hang out with friends and family. If you have any questions please don't hesitate to contact me.

Follow me on:
  • http://cfrant.blogspot.com Adam Haskell

    I’m not sure I care for the whole, hide hibernate in a DAO approach. The whole idea of Hibernate (ORM really) is to liberate an application from worrying about persistence, pushing everything into a DAO just smacks you right back into the Database paradigm.

    @Brian K. I’d be interested to see where you think Statics make sense (in ColdFusion specifically). I am at a loss as to where it would ever make sense. I think they would rank right up there with interfaces for me. The typical use case is solved by putting a utility in the application scope, the secondary use cases I have come across are solved by mixins.

  • http://www.briankotek.com/blog Brian Kotek

    Might be a good time to look at ColdSpring then? That way, you can supply references to your services and DAOs to each other without having to dig into the application scope like this.

  • http://www.briankotek.com/blog Brian Kotek

    @Adam – I’m really referring to statics in general, not specifically in CF. That said, there are cases where just calling a static method would be easier than creating singletons and injecting them all over the place. But it would be more of a short cut than a necessity, since there are other ways this can be handled.

  • http://bears-eat-beets.blogspot.com/ Tony Nelson

    Mixing static methods and the Active Record pattern makes you really question the value of the service layer. Yeah it’s still important (I think), but its role is greatly reduced.

    If you wanted the Product.list() syntax, here’s one thought.

    index.cfm:
    <cfinclude template="mixin.cfm" />

    <cfset products = Product.list() />

    <cfdump var="#products#" />

    mixin.cfm:
    <cfif not structKeyExists(application,"domainClasses")>

    <cfset entityName = "" />

    <cfloop collection="#ormGetSessionFactory().getAllClassMetadata()#" item="entityName">
    <cfset application.domainClasses[entityName] = new DomainClass() />
    <cfset application.domainClasses[entityName].entityName = entityName />
    </cfloop>

    <cfset structDelete(variables, "entityName") />

    </cfif>

    <cfset structAppend(variables, application.domainClasses) />

    DomainClass.cfc:
    component {

    public any function new() {
    return entityNew(this.entityName);
    }

    public any function load(id) {
    return entityLoadByPK(this.entityName, id);
    }

    public array function list() {
    return entityLoad(this.entityName);
    }

    public any function onMissingMethod(missingMethodName, missingMethodArguments) {
    // dynamic finders
    }

    }

    You could probably hide it even more by putting the logic inside onRequest() or using a ColdSpring post processor to automatically inject the classes into your controllers. Not sure if I recommend doing anything like this though.

  • http://www.briankotek.com/blog Brian Kotek

    Also @Adam – well you can’t completely liberate the application from persistence. SOMETHING has to know about the ORM so that you can do something with it. To me, it makes the most sense to do that in a DAO. First, then it’s encapsulated. And second, the ORM *is* a database-level concern, which is exactly what DAOs are meant for. If not in a DAO, then where would you handle this that makes sense and maintains separation of concerns?

  • http://mickydionisio.blogspot.com/ Micky Dionisio

    @Brian Kotek

    "A domain object should not have anything to do with database interaction like saving, loading, listing, etc."

    Agreed if you are talking strictly about implementation of crud being in the domain object, but that doesn’t mean you still cannot have crud methods in the domain so long as you are using delegation. If you are creating a composite relationship between a Product(domain object) and ProductDAO, so Product has-a DAO, your crud methods on Product simply delegate to the DAO’s. This way domain objects are still properly encapsulated and concerns stay separate. The responsibility is still on the composite DAO. Domain objects don’t care how list(), save() etc is actually being performed, it just trusts that the proper composition and delegation is taking place.

    So instead of having to create the domain object, then creating the dao, then pasing the domain object into the dao, simply call Product.save(). Which will under the hood be delegating to getProductDAO.save().

    When thinking DDD, Martin Fowler put it best:

    "In general, the more behavior you find in the services, the more likely you are to be robbing yourself of the benefits of a domain model. If all your logic is in services, you’ve robbed yourself blind."

  • Marc Esher

    So Dan, what you want is the behavior of an application-scoped object without the inconvenience of typing it out, injecting it, or the lameness of having components reaching outside of themselves into the application scope? Does that about sum it up?

  • http://therealdanvega.com Dan Vega

    @Brian – Great link

    @Marc – Its not that I want that. It’s kind of what I have been doing but I wanted to hear from smart people like you on what others are doing :)

  • http://cfrant.blogspot.com Adam Haskell

    Fair question Brian a direct answer to your question is my service layer would know about hibernate. It is at first glance not much different than a DAO really, just instead of having 1 more object to instantiate and deal with I just have a Domain and ColdFusion functionality. Why encapsulate what the language offers (yes an argument could be made about different engine implementation but it’s a language feature and I plan to treat it as such. Hibernate replaces DAOs why create an additional layer of indirection when we don’t need to. Doa.save(myDomain) and entitySave(myDomain) is pretty much the same. One might argue testability but to that I would contend that if you are testing a service then you should be ready to test REAL database interaction not a mocked database. Service level tests should no longer be concerned with Domain/Business logic and it should be test integrations and full use case functionality, a database should be involved not mocked.

    All that being said, I think I made a misstep in my previous comment though and my true intent was not really relayed. What I was getting at was that ORMs liberate application from persistence details: how to persist and what to persist, not what persists the details. Before ORMs we used DAOs to encapsulate and insulate a potentially brittle interaction (our application and the database). The short coming was typically with DAOs we still have a the 1:1 object (sometimes 2:1 DAO and gateway, blarg). Our database design/implementation was still leaking into our applications. If we were smart it was at least not leaking into our Domain but we still had this type of code in our DAOs:
    transaction{
    for(detail in order.details)
    {
    detailDao.save(detail);
    }
    saveOrderStuffHere;
    }

    We had no choice it had to be done somewhere. The DAO provided a great place to put this type of code and it helped save us from a brittle Domain. Enter ORM, now we annotate our domains to say what is related, and how they are related. Putting everything into a DAO pattern does not evolve application development it just uses hibernate to write less code. That’s not a bad thing mind you I just feel like it sells ORM short.

  • http://www.briankotek.com/blog Brian Kotek

    @Micky: I think you may be missing the point of what Fowler is saying. Yes, business logic should indeed be implemented by domain objects. To do otherwise, is to adopt an Anemic Domain Model. But he’s talking about *business logic*, not persistence logic. In concrete terms, he means, for example, if you have an Invoice with LineItems, it would be bad to have logic in a service that gets the LineItems from the Invoice, loops over them, and adds them up to calculate a total Invoice amount. That is business logic, and it should be handled by the Invoice, not a service.

    If one does choose to implement Active Record, then yes, having the object delegate to a DAO would be the only acceptable way I would attempt it. At least then the actual database-specific logic, or the use or lack of an ORM, is hidden.

    The heart of the issue, for me, is that to even ask a domain object to "save itself" or "get a list of objects like itself" doesn’t make sense. This isn’t business logic. I would argue that, from the perspective of a domain object, that fact that it is ever "loaded" or "saved" or "listed" should not arise. For all the domain object knows, it is created in RAM and it exists forever. It should only concern itself with doing its job. Since RAM is not infinite and computers turn off, it is necessary for something in the system to know how to move data from RAM to something more permanent. This is where things like DAOs come into play. But in my opinion, the domain object shouldn’t concern itself with any of this.

  • http://mickydionisio.blogspot.com/ Micky Dionisio

    The point is not missed. Persistence has nothing to do with the Anemic Model as Fowler says it himself, "There are cases when you make an argument for putting data source or presentation logic in a domain object, but that’s orthogonal to my view of anemia.".

    The very definition of the DAO pattern is to provide a technique for separating object persistence and data access logic from any particular persistence mechanism or API. Not about cleaning up objects when an application shuts down. Leave that to a shutdown process coupled with perhaps a UnitOfWork design pattern.

  • http://www.briankotek.com/blog Brian Kotek

    @Adam: I understand what you’re saying, but there are several reasons why I disagree. First, Hibernate doesn’t replace DAOs. There are many cases where the ORM won’t fill a need, such as running complex SQL for reporting or data aggregation. I prefer to have one place where "database stuff" happens. That means that SQL and CRUD/ORM logic goes into my DAOs. I don’t want to "sometimes" have ORM logic in my services, and "sometimes" have my services call on my DAOs. I see value in the consistency of having a DAO handle these things.

    Second, I would indeed point to testability. I want to unit test things in isolation. For me, testing the whole stack is the realm of integration tests, not unit tests.

    Third, having this in a DAO means it is easily swapable. If different CFML engines implement ORM differently, the presence of a DAO makes this easier. It also means that turning on or off ORM reliance is easier (if I want it to run on CF8 and CF9, for example, or if I want to be able to leave the choice to use ORM open).

    There’s not much to gain from having a 1 to 1 correlation between domain objects and DAOs though. My DAOs are rarely have 1 to 1 correlations to domain objects, but they may have 1 to 1 correlations with services.

    Yes, it is an additional object or set of object to deal with, but since much of this can be abstracted into a base DAO, there need not be duplicate code. Encapsulating this stuff into DAOs is not difficult and doesn’t require much work, and I feel the payoff in encapsulation is worth that effort.

    As you said, the difference between EntitySave( foo ) and dao.save( foo ) is virtually nothing, so I don’t see how this fails to "evolve application development" (which, to be honest, I’m not sure what that means, can you clairfy?), or sells ORM short. I’m still reaping all of the benefits. I’m just choosing to keep it encapsulated.

  • http://mxunit.org marc esher

    Well Dan, I’ll say this: The discussion here seems to indicate that your first question:

    "What if ColdFusion had a static method?"

    Does not help in answering the second question: "Where does this Base stuff go?"

    What do you think?

    I’m thinking "static" and "commonality" don’t have much to do with each other.

  • http://therealdanvega.com Dan Vega

    I tend to agree that a common place for persistent functionality should exist. Take this example – For all of my domain objects product,category,order etc… I want to perform a list action. When I think of list to me I just want a query back of all the rows for that record. I could do the following in my view template

    <cfset arrayOfProducts = entityLoad("Product")>
    <cfset products = entityToQuery(arrayOfProducts)>

    OR I could have a persistence layer that I always communite with.

    <cfset list = application.productObj.list()>

    There are so many things I rely on persistence for

    list
    dynamic finders
    searching
    paging
    loading
    new
    save
    delete
    etc…

    I like have them all in 1 place! If I am going to have them all in one place why duplicate functionality. All of these methods perform the same functionality when using hibernate so why not create a generic one that others can extend.

    ** On that note I don’t think anyone is wrong here. Sometimes its a personal preference but either way you guys have come up with some really great responses!

  • http://therealdanvega.com Dan Vega

    @Marc – I would agree with that. The reason it got brought up was because that was where my head was at the time.

  • http://www.briankotek.com/blog Brian Kotek

    @Dan: I would caution strongly against doing that sort of thing in a view. That should all be handled by the model.

    If by:

    list = application.productObj.list();

    You mean:

    list = application.productDAO.list();

    Then I would agree (though I’d supply the DAO to a service at creation time rather than digging into the application scope).

  • http://cfrant.blogspot.com Adam Haskell

    @Brian K.

    "Hibernate doesn’t replace DAOs."

    Yeah I completely agree, all honesty I prefer DAO over hibernate. If I find myself in a situation where I have to use DAOs I tend to not use Hibernate at all (this is Java based comment though I have not done this in CF yet). I get the consistency, I don’t mind difference too much though since it is all happening in the same spot which to me is more important than the syntax taking place. Definitely personal opinion there though.

    I still disagree on testing my point is that you should not have anything interesting enough to unit test in a service, so really services should just be needed in integration tests. Now if the service is actually interest I could see some issues but I would ask what’s up with the service first ;)

    The third one is just too many what ifs and speculation for me. I can respect a person that wants to isolate/encapsulate the hibernate integration but again like I said it is a language feature and I will treat it as such.

    Well if I knew where it would evolve to I would be a very smart individual, in fact I am not. In actuality I am an idiot, I screw up constantly. I just adapt when I screw up and people then tend to think I am smart thanks to my ability to adapt and learn. I do feel like there are better ways yet to be discovered over DAOs. Just hiding in a DAO though I will not discover it. It remdinds me of a TNG episode that was on last night actually. A genetically engineered race of humans were for lack of a better term perfect. They were a great society ultra intelligent and had fascinating technology. Their planet however was not perfect, they were unable to fix an issue they ran into. It took technology that was created for Geordi (the imperfect human that would never exist in their world) to save their planet. My point being is if there is a better way constantly using the building blocks I have I will not find it.

    As for selling ORM short, if I do decide to encapsulate into a DAO I either have to create a robust API(PITA) to take care of all the different ORM options, and combination therein or I still have to make ORM calls in my service. I really want to stress though that I am not saying DAO is wrong, its just not my style. I know Brian gets it but I want to stress it for anyone else reading both approaches work its just what feel good to you.

  • http://therealdanvega.com Dan Vega

    @Brian – That is exactly what I meant… sorry for the confusion.

  • http://www.brianmeloche.com Brian Meloche

    For common data elements that seldom change, I store them in the application scope, which is called in the service with a getSavedList method or by calling the application variable directly.

  • http://therealdanvega.com Dan Vega

    @Brian – Calling other scopes (application,session,request) from a component is a big flaw in architecture in my opinion.

  • Brian Carr

    Dan, great post – it’s good to see you branching out into other languages. I’ve learned a lot from other languages that have only helped to improve how I approach and implement my CF apps.

    I would absolutely love to see CF support the concept of static in the same sense and context that Java does for exactly the reason you’ve detailed above, although the pessimist in me thinks that may never come to pass for CF.

    Lastly, it appears as though there are a handful of techniques / best practices / patterns being touched on here. I prefer more of a domain-driven approach whenever possible which can in many cases reduce the need for a Service type layer (or at least reduce the logical dependency on such constructs). Take your invoice example – for example :-) A very valid and common approach is the one you’ve detailed above – the implementation of a Service to determine how (e.g., where) an invoice gets sent. From a DDD perspective, having the invoice send itself would be beneficial; invoice.send(); We could then implement the strategy pattern in order to provide the invoice with the correct send behavior during instantiation or construction (which may be accomplished by an InvoiceFactory) – the invoice itself could be considered "sendable" expressed possibly by a "Sendable" interface – which would expose a contract such as send() which in the implementation would delegate to its composite implementation of SendBehavior to perform the actual business logic. Emails, orders, probably a handful of other objects could implement that – each with a very flexible, loosely coupled and highly interchangeable set of behaviors.

    Needless to say, your post got me thinking..Thanks!

  • http://therealdanvega.com Dan Vega

    @Brian – Thanks for the feedback. First off this needs to be reiterated, this is not a please Adobe implement this. I just believe I found a real world example of where it could be used. The info on the service level stuff is right on but I was using it as more of an example of what service levels are usually used for. Still a little confused on where my common functionality for business objects goes.

  • http://www.mickydionisio.blogspot.com/ Micky Dionisio

    Dan –

    Great thought provoking post. I think both your service layer and domain driven approaches are valid.

    I’ve used both approaches but lean more towards the DDD approach. I find that it keeps the API extremely simple and clean which ultimately leads to more understandable code. If you need a list of products, simply ask the Product object. This minimizes the
    need for instantiating service objects for each business object for the general crud requests – save, delete, load and search.

    However for any advanced level/complicated searching, I’d put that into a proper service object.

    Also for creational methods like new() I stick to the Single Responsibility Principle (SRP). I throw creational methods like those into
    factory objects instead of service objects. These factories objects can be switched out at runtime with little, if any, impact to other code.

    Ultimately I think there is no right or wrong answer in both those approaches you described as the solutions are good albeit subjective. For me at the end of the day, the less objects I have to instantiate to consume the API the better so long as the API under the hood is well encapsulated, DRY’d and flexible.

  • http://cfrant.blogspot.com Adam Haskell

    Couple of points I’ll make, hopefully they make sense if not let me know and I can try to elaborate on my blog. Before doing so… Domain modeling is filled with "what if’s", "it depends" and a whole lot of personal opinion. What I am saying is based off years of work in multiple languages and it works for me on my projects.

    "The great thing about this approach is our product service can now focus on the business logic that it needs to perform."

    I tend to disagree with this and the attached example of emailing. This is Domain logic. The service should exist to coordinate domains/objects that do not have a natural correspondence. Typically this turns into Business domains (actual tangible objects that have deep domains like invoice) and Application Domains (things your application needs to function but are typically not directly related to the Business). In the invoice example for instance I would have a message type object that implements a sendMessage(msg) method and then my domain would have a send() on it which would take a messaging object. This would all be coordinated by the service’ sendEmail method:
    function sendEmail(invoiceId, emailAddresses)
    {
    messaging = new EmailMessage(emailAddresses);
    invoice = getMyInvoiceSomehow(invoiceId);
    invoice.send(messaging);
    }

    "As we can see that works out great but if we sprinkle some of the other methods I talked about earlier in our domain object. Now I am going to add a new method list…"

    Domain objects are not factories, I get the whole limit the object explosion, this is true in any language but in CF there are additional reason (mitigate much in CF9) to avoid object explosion. In the case of factories I think separate objects are good. Really a Domain object should focus on the domain and the domain is certainly not how it persists or creates multiple representations of itself.

    One final note, if ColdFusion if you have something that you truely would like to be static Putting it in an Application level most likely will work. The other thing you can consider is leveraging mixins. In the case of all your methods like save/delete/list. Thos could all be put into a persistable.cfm and in the definition of your component you can just <cfinclude template="/mixins/persistable.cfm" /> and viola. In your exact case like I said the factories should exist elsewhere and really all you are doing is putting a thin wrapper around something that is essentially static in ColdFusion, EntityLoad.

  • http://blog.mxunit.org Marc Esher

    Dan,
    In the end, does your "man, I wish CF had statics right about now" boil down to syntax?

    i.e. you would rather do this:

    products = Product.list();

    rather than

    products = new Product().list();

    in CFML tags, you "essentially" get statics with CFInvoke:

    <cfinvoke component="Product" method="list">

    I put that in quotes because it’s certainly not static in the Java sense (single class in the JVM) but behaviorally it’s pretty similar.

    I’m not suggesting that saving a few characters of typing isn’t a noble goal… it can be …. I just wonder in this case if it’s really worth it. Perhaps what you want is less "static", and more "runtime intelligence", i.e. if you type Product.list() it’s smart enough to know that you don’t have a variable in scope named Product with a List method, so let’s see if you have a component named Product with a list method, and if so, invoke it.

    One problem I’ve had in the past with statics in Java has been just how much harder they make unit testing, particularly since you can’t mock statics. So while they may impart some convenience whilest typing source code, they usually end up causing me more pain than they’re worth. Just something to think about is all.

  • http://therealdanvega.com Dan Vega

    @Adam – Thanks for the awesome feedback! I understand what you are saying about the service level. This was more of a here are things you do at the service level (the example may not be the greatest) as apposed to what I was doing at the service level with my persistent methods.

    I like your thoughts on the domain model and I tend to agree with you there. I think what grails does is they create a Static object named after the domain, I don’t think its actually the domain object that contains all of the persistence methods (list,findby,search etc…).

    Finally – I am not sure how i feel about the mixin approach. I will have to play around with that a little bit more.

  • http://therealdanvega.com Dan Vega

    @Mark – I think your missing the point with the following.

    products = Product.list();

    rather than

    products = new Product().list();

    Its not a matter of syntax in my opinion. Its the fact that in the second example your creating an instance of a domain object to get back a list of domain objects. Something about that just screams "What are you doing boy" ha! When I create an instance of a domain object I feel that I should be only working with a single object.

    Good point about unit testing and static methods!

    ** Keep the good info coming guys!

  • Henry Ho

    Having static methods would be neat I think. UDFs would be much easier to organize.

  • http://blog.mxunit.org Marc Esher

    Ok Dan, I can see that. In my head, it’s a bit hair-splitty, but I can see it.

    I mean, technically, if you have true statics, you are indeed "creating an instance of a domain object to get back a list of domain objects". The difference is that you’re only creating that "instance" one time in the JVM (since that’s how statics work).

  • http://www.briankotek.com/blog Brian Kotek

    Static methods have their place, but I don’t agree that this is one of them. I’ve always thought that calling a static Product.list() method is a bad idea. This shortcut that is available in Grails and Rails is tightly bound to the Active Record approach, which I have always disliked. A domain object should not have anything to do with database interaction like saving, loading, listing, etc.

    The way I have done this, in CF and in Groovy, is to let the domain objects be just that, and handle database logic in DAOs. A lot of things like dynamic finder methods can be handled using a base generic DAO (Joe Rinehart posted on this topic as well: http://www.firemoss.com/index.cfm/2009/10/7/coldfusion-9-orm-generic-dao-wrapper ). This offers similar results, but greatly increases the cohesion of the domain objects because the database logic is moved into its own class (where I would strongly argue that it belongs).

  • http://blog.mxunit.org Marc Esher

    Dan, you said what you didn’t like was the notion of a domain object returning a list of itself. So what if you had new ProductDAO().list() …. is that still odious to you? Do you still want just ProductDAO.list()?

    It seems to me there’s two things at work here: "static" and the old debate about "where to put things". They are mutually exclusive.

  • http://therealdanvega.com Dan Vega

    I am doing something very similar now Brian, I was just calling it a service object because I was looking at it as an "API" to my domain. I think I had the right idea, just wrong place. It makes sense on a DAO level, thanks!

  • http://therealdanvega.com Dan Vega

    @Mark – If I store my ProductDAO in the application scope I am fine with calling application.ProductDAO.list(). It is what I am doing now, I just didn’t like calling it a service.

  • Brian Carr
  • http://therealdanvega.com Dan Vega

    In case you missed it I threw some code together last night. You can download a very simple example of my base persistence layer.

    http://www.danvega.org/blog/index.cfm/2010/1/6/My-Abstract-Persistence-Layer-Take-1