Announcement Announcement Module
Collapse
No announcement yet.
Static Finders versus Repositories Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Static Finders versus Repositories

    Having done some experimentation with Roo, there's a lot to like, using push in refactoring to stop a method being managed in particular.

    However one thing I'm not comfortable with is the fact that finders are generated as static methods. There are lots of good reasons why developers have moved away from statics to container managed singletons and at face value it seems a bit of a retrograde step.

    Was this just an implementation convenience, or is there some other reason for this approach?

  • #2
    Hi Phil,

    Thanks for your comments.

    We have made a very concious decision about avoiding extra layers such as the repository layer as much as possible. In the past few years we found that burdening the developer with the architectural weight these layers incur while not adding much benefit is questionable. Our aim is to generate the most concise possible code. Looking at most 4th generation RAD frameworks (Grails, RoR, Django, etc), you will notice that such 'lighter' arhcitectures are, in fact, more of a trend rather than a 'retrograde step'.

    As for the use of statics, you would have noticed we only use them for 'read' operations which avoids side effects. We think Roo's approach removes the technical limitations associated with statics in the past. Can you elaborate further what specific problems you see with regards to the use of statics in Roo applications?

    Rod Johnson is currently planning to write a blog post which will provide more detail about the design decisions we have taken for Spring Roo generated applications.

    Regards,
    Stefan Schmidt

    Comment


    • #3
      Hi Stefan,

      The big reason for me for avoiding statics is mocking/test doubles. Yes there are some mocking frameworks which will allow you to mock out static methods, but it makes TDD more complicated and anything which does that is undesirable in my book. This applies to a lesser extent to blending persistence related features into the domain objects. Apologies if 'retrograde step' seemed a bit judgemental, but the biggest pay-off when we originally started working with Spring was how much easier it made TDD, so that's why I feel particularly nervous about a Spring project apparently making that less convenient.

      I've been working for years on a large application where we've taken DDD seriously and separating out repositories has shown value for us over the long term, so I'd be loathe to give it up. At the same time we are increasingly melding more smaller apps into our site and have built apps using Django and investigated some of the other frameworks you mention, but it's this kind of compromise that has made us nervous about using them for apps which don't have a short, fixed, life-span.

      I understand the desire not to over-complicate, but in my normal development the overhead of breaking out repositories is low and the benefit tangible. This isn't an equation which balances the same way for DTOs for instance. At the same time I recognise that the overheads for a tool providing a more generic approach may well not be comparable, though hopefully this will become clearer when there's a bit more info on extending Roo.

      Phil

      Comment


      • #4
        Hi Phil,

        As you know, we the SpringSource team strongly believe in TDD which has lead to the convenient integration between existing test frameworks and the SpringFramework itself.

        In Spring Roo we are following the same route by providing in-built support for mock-based unit testing of Roo-provided static methods in @Entities:

        Code:
        new mock test -entity the.entity.pacakge.and.Name
        This code was written by Rod Johnson and is available since Roo M2:
        http://jira.springframework.org/browse/ROO-92

        Please feel free to try it out and let us know if this addresses your concerns. We are always happy about feedback and will consider and incorporate any enhancement suggestions the community makes.

        Regards,
        Stefan Schmidt

        Comment


        • #5
          Hi Stefan, my problem with that is that not only does it introduce yet another mocking framework, but it ties me into using it. For instance, I'm a really big fan of Mockito largely because it ditches the record/playback approach which EasyMock and Rod's implementation for Roo take.

          I don't want to get religious about it, it just feels like it would be a compromise for me, which might be worth it for other benefits Roo is providing, but is never the less not ideal. The rest of Roo does a really nice job of not tying me in and providing an obvious route out of the framework should for any reason I so desire. Once you're using custom mocking technology, with no obvious migration path, it starts to feel like you're creeping towards lock in.

          Phil

          Comment


          • #6
            Hi Phil,

            The arguments you are making indeed valuable feedback for us. I guess the best route to follow would be to develop a Roo add-on for Mockito. This way, you get the mocking framework of your choice in Roo generated projects.

            We are planning to make some changes to the add-on API in the near future which is why we have held back on publishing any blog posts and documentation on it since we might break some of the APIs along the way (don't forget Roo is still in it's early stages). But as soon as we have completed these changes we will publish blogs and documentation for add-on developers. A Mockito add-on is indeed a good candidate.

            Stay tuned!

            Regards,
            Stefan

            Comment


            • #7
              Hi Phill,

              If you are a fan of Mockito, you could use PowerMock with Mockito (code.google.com/p/powermock/wiki/MockitoUsage) to mock static methods.

              Comment


              • #8
                I tried the approach with powermockito but it wasn't working for me.

                The point is that Roo promotes DDD. So I have been writing some nice business methods and have added them to the appropriate classes. I should be able to unit-test these easily. Note unit test != integration test.

                Obviously one could say that I can modify the signature of SalesOrder.createSalesOrder to accept a Product object, which would probably get me out of the woods for this particular issue. Still I have the feeling that at some point I will *have* to invoke a static finder which I will have to mock...

                Some of these methods have to lookup other data, in my case a SalesOrder.createSalesOrder(String productId, Integer quantity) has to look up a product using the Roo-provided static Product.findProduct(long id).

                This a huge pain to mock, even PowerMock is telling me that it cannot find the stub for this method, maybe this is caused by the intensive use of aspectj?

                Maybe I am missing some DDD concept here (I have been stuck in service/repository land for years).

                Hoping somebody will share their thoughts...

                Comment


                • #9
                  Hi Hans

                  If the static method mock supported offered as part of https://jira.springsource.org/browse/SPR-6274 is unsuitable one approach might be to adopt a similar strategy as that feature does in that it provides an around advice that essentially replaces the introduced functionality with alternate mocked functionality. For my money I'd just use the record/playback style as offered out of the box by SPR-6274 and skip the verify step.

                  Cheers
                  Ben

                  Comment


                  • #10
                    Thanks ben, this is clear.

                    Comment


                    • #11
                      I'm working on a controller unit test. I want to write the unit test without loading the Spring container. The entity manager will not get injected into y ROO-generated entities.

                      I would like to mock out the entity manager in a ROO-generated entity.

                      I've been working on writing an aspectj aspect that will return the mock entity manager instead of the one that would be there if the container had been allowed to manage the object.

                      I'm not finding this very easy. Any ideas? Any code examples anywhere?

                      The mocking of statics doesn't do exactly what I want because the persist() and other JPA methods are not static.

                      Comment


                      • #12
                        You might wish to vote for https://jira.springsource.org/browse/ROO-301 so there is more flexibility in persistence technology added to Roo. This will make mocking a lot easier.

                        Alternatively we did add some mock testing aspects for static methods to Spring Aspects under http://jira.springframework.org/browse/SPR-6274. This is the only approach presently supported.

                        We welcome suggestions or contributions to making this better.

                        Comment

                        Working...
                        X