General logic placement - Calling Dataportal directly

General logic placement - Calling Dataportal directly

Old forum URL: forums.lhotka.net/forums/t/5399.aspx


vdhant posted on Monday, September 15, 2008

Hi guys
I have a quick question about general logic placement and I coming to the wisdom of the ether.

This has come about via an example that I have recently seen which calls dataportal methods directly without going via the actual business objects factory methods. So the example went something like the following "DataPortal.Create<T>();", as you can see, if one was to call this directly you are cutting the business object right out of the picture.

Now when i saw this, the alarm bells went off in the back of my mind as there could be scenarios where by calling the dataportal directly you could be bypassing logic that is on the client side of the dataportal which is implemented by the business object.

I can't really think off the top of my head what this logic may be - because validation and security are handled data manipulation would go on the server side of the portal, you would use a command object for command operations, calculations would be performed via properties of maybe a command/normal object - but I always had in the back of my mind that if I needed to place logic on the client side of the portal I would do so by doing something like the following:

    public static Resource GetResource(int id)
    {
      Resource resource = DataPortal.Fetch<Resource>(new SingleCriteria<Resource, int>(id));
      resource.SomeRandomClientSideLogic();
      return resource;
    }

    public void SomeRandomClientSideLogic()
    {
        ...
    }

So what I was wondering is where people put logic that they want to execute on the client side and falls outside the scope of the areas mentioned above (i.e. validation, etc). Because if it becomes more common place that people call the dataportal directly this could become an issue... or maybe I have just missed something about where to place this sort of logic which makes calling the dataportal directly ok.

Cheers
Anthony

triplea replied on Monday, September 15, 2008

If you implement your busines rules as usual then you can call ValidationRules.CheckRules(); when Fetch or Create is completed (done automatically since CSLA 3.5 I believe). Not sure that's what you are asking but it might help.

JoeFallon1 replied on Monday, September 15, 2008

I would never call DataPortal.Fetch directly.

I always use the factory methods.

Joe

 

vdhant replied on Monday, September 15, 2008

@triplea
No this is not really what i was talking about... "I can't really think off the top of my head what this logic may be - because validation and security are handled data manipulation would go on the server side of the portal, you would use a command object for command operations, calculations would be performed via properties of maybe a command/normal object - but I always had in the back of my mind that if I needed to place logic on the client side of the portal I would do so by doing something like the following:"

@Joe
This was my thoughts but it is something that I seem to be seeing a bit more of these days particularly around csla and tdd. Specifically where I have seen it is in the ProjectTracker sample that nermin from magenic is working on. It would seem (and note this is a work in progress so he may be changing this) that in an effort to make the business object more testable. The way he is doing it is that you create an instance of the ReadOnlyListFactory which then calls the dataportal directly...

using Csla;

namespace ExtJsCslaDemo.Web.Factories
{
    public class ReadOnlyListFactory<T, C> : AbstractBusinessFactory<T>
        where T : ReadOnlyListBase<T, C>
    {
        public override T CreateNew()
        {
            return DataPortal.Create<T>();
        }

        public override T RetreiveAll()
        {
            return DataPortal.Fetch<T>();
        }

        public override T RetreiveBy(CriteriaBase criteria)
        {
            return DataPortal.Fetch<T>(criteria);
        }
    }
}



namespace ExtJsCslaDemo.Web.Controllers
{
    public class OrderController : Controller
    {
        private readonly AbstractBusinessFactory<OrderList> orderListFactory;
        private readonly AbstractBusinessFactory<OrderDetailList> orderDetailListFactory;

        //Called by MVC
        public OrderController() :
            this(new ReadOnlyListFactory<OrderList, OrderInfo>(), new ReadOnlyListFactory<OrderDetailList, OrderDetailInfo>())
        {
        }

        //Used for testing
        public OrderController(AbstractBusinessFactory<OrderList> orderListFactory, AbstractBusinessFactory<OrderDetailList> orderDetailListFactory)
        {
            this.orderListFactory = orderListFactory;
            this.orderDetailListFactory = orderDetailListFactory;
        }

        public ExtJsJsonReaderResult List(string customerId)
        {
            var orders = orderListFactory.RetreiveBy(new OrderList.CustomerFKCriteria(customerId));

            return new ExtJsJsonReaderResult("orders", orders);
        }

        public ExtJsJsonReaderResult ListOrderDetails(int orderId)
        {
            var orderDetails = orderDetailListFactory.RetreiveBy(new OrderDetailList.OrderFKCriteria(orderId));

            return new ExtJsJsonReaderResult("orderDetails", orderDetails);
        }
    }
}

JoeFallon1 replied on Tuesday, September 16, 2008

Oh - I see what you mean now.

A factory class is a different animal. It is OK there.

I thought you wee talking about arbitrary calls in other locations of the BO or the UI.

Joe

 

RockfordLhotka replied on Tuesday, September 16, 2008

There are really three ways to call the data portal

  1. From a static/Shared factory method like I show in the book. I like this model because I think it makes the factory methods easy to find (they are right on the business type).
  2. From a separate factory object (typically instance methods of that object). I find this model to be awkward and less discoverable, but it works just fine. The only thing to remember is that your criteria classes must implement ICriteria or subclass CriteriaBase - you can't use nested criteria classes in this case.
  3. Directly from the UI - there is nothing stopping UI code from directly using the data portal to create/get an object. I think this is a bad approach, because it puts too much knowledge into the UI, and removes control from the object, so I really recommend against it.

 

vdhant replied on Tuesday, September 16, 2008

Hi Rocky
Thanks for the reply. But i am still wondering about my original question - where to place client side logic:

"as there could be scenarios where by calling the dataportal directly you could be bypassing logic that is on the client side of the dataportal which is implemented by the business object."

"I can't really think off the top of my head what this logic may be - because validation and security are handled data manipulation would go on the server side of the portal, you would use a command object for command operations, calculations would be performed via properties of maybe a command/normal object - but I always had in the back of my mind that if I needed to place logic on the client side of the portal I would do so by doing something like the following:"

If you end up bypassing the actual object and going to the data portal (with either method 2 or 3 that you described) you lose the ability to encapsulate this logic...



Also whilst we are on the topic of logic placement if I have a scenario where would the logic go. When the user saves a given record, if the system detects that the value of a given property has changed, where would I place the logic if I need to trigger an update to a different entity or insert a series of series of related record. Note these objects aren't properties of the root object being saved.

Cheers
Anthony


RockfordLhotka replied on Tuesday, September 16, 2008

It isn’t complex, assuming you call the data portal normally.

 

All code outside the DataPortal_XYZ and Child_XYZ methods is client code.

 

All code inside the DataPortal_XYZ and Child_XYZ methods is server code.

 

The only exception to this, is that the server code can call “client code”, in which case that code will run on the server. This is the whole point of mobile objects!

 

So a better way to phrase this might be:

 

All code outside the DataPortal_XYZ and Child_XYZ methods is mobile code (available to client and server).

 

All code inside the DataPortal_XYZ and Child_XYZ methods is server code (only available to the server).

 

If you REALLY want some bit of code to only run on the client, you can use Csla.ApplicationContext.ExecutionLocation to prevent that code from running if the location is Server. It is hard to imagine such a scenario though.

 

Rocky

 

Copyright (c) Marimer LLC