måndag 29 februari 2016

Never use current.update in a Business Rule

The more I read about Business rules I notice that they are being used the wrong way by many people. Every rule has it's exceptions and I bet there is one here as well. But I can say that I haven't yet come up to a reason why you should use current.update in a Business Rule. I written a post about this and Business rules in general.

I guess I need to explain what I mean with my headline.

I like this picture from the wiki Business rules

Business rules query after before async display

It's pretty simple if you look at it. Let's go through what kind of business rules (BR) we have.


This type of BR is used to modify the queries that are send to the database and this is before any data is collected, which means you can't do things like "if (current.active)" since the BR have no idea what value current.active has. You pretty much use query BR to restrict what kind of data that the user is allowed to see.

Table: Incident
Condition: !gs.hasRole("admin") 
Script: current.addActiceQuery();

What will happen here is that if the user query the incident table and don't have the role admin, it will add "current.addActiveQuery(); to the query and the user will only get back records that are active.
Here we can see that we shouldn't use current.update to anything.


So what can we use the Display BR to? Well, if we know that we will need data to use in a client script, but the data isn't available in the form. The we can use the display BR to run server script and put the info in the g_scratchpad and then use it later in the client script. Just be careful, since it put the data in the scratchpad when the form is loading, that also means that if then the use don't do anything for like 10 min and the do something and the client script uses that data. It might be old and not correct. If you instead use a Ajax call, you will get "live" data for your client script.

So current.update shouldn't be used here either.


Now this BR hits before the data is saved into the database. But since the data hasn't been saved, we don't need to use the current.update here either since the record is about to be updated automatically. Here we can modify fields like current.u_no_idea = 'bad imagination'; 

We can also use a before BR to validate the information to check if it should be allowed to be saved. Doing this here instead having a client script doing it. If the data isn't correct, you can abort the action with current.setAbortAction(true); 

I know I'm repeating myself, but no use for current.update here either


Looking at the picture you can see that the BR runs after the data has been saved to the database. Now is a perfect place to update other records beside the current one. Yes, you have access to the current object, but that is more to be able to use this data to do conditions and for example IF-statements to decide what other records to update.

Which leads to that we don't use  current.update here. What will happen if we use current.update? All the "before" BR will run again, since we are trying to save/update something in the database... And again, is there anything in the current object we can't do in a before BR? that we need to do in a after? Right now I'm saying no until someone else corrects me.

Looking at all of the above, we are hitting user experience, making big BR of any kind of the above will affect the user experience. Even a after BR doesn't let the user do anything else until it's finished. That leaves us to the last one.


Async BR is something that I myself probably could use more instead of the after BR. I have a note on my desk to go through all my BR's when I got time over to see if I can move over some after to async. Async (Asynchronous) is simular to after BR but here it let's the user go and do other stuff and put this on the "let's do it when we got time" list. If the condition on the async BR hits true, it understands that there is work to do and creates a schedule job to handle all that work. it's schedule to run immediately, but it doesn't guarantee when it's finished. 
What's good to know that the BR isn't run within the user's own active session. When the schedule job is ready to go, it impersonate the user and a new session is created for this job. This will probably not have any affect, but can be good to know. So if you got things that needs to get updated after a record is saved and not in a extremely time critical way, async is the way to go.
But then again, it's only different from a after BR is that the user doesn't need to wait for it to finish.

And guess what... We don't do current.update here either :)

So, that all about Business rules and I have at least not found any way of having the need of current.update in a BR. If you do, please tell me so I can correct this post(or delete it :P )


1 kommentar: