Set Processing vs Complexity

There was a time when I was a fervent member of the Church of Set-Based Processing. I preached %InsertSelect and TAO tables, and I would brook no dissent. At the time I was writing app engines to bring data into Projects, and it's probably a fair bet to say that PROJ_RESOURCE is one of the largest tables in the Financials database.

On a recent project I had a requirement to allocate available quantity against incoming orders. I dutifully built an app engine that handled most of the work in a set, only dropping to a row-by-row loop at the end. It took a little debugging, I got turned around once or twice, but in the end it was fast and—if you don't mind me saying—somewhat clever.

But here's the thing: while the business analyst was congratulating me on how fast the process ran, he mentioned some of the rules he'd like to add in the future. (I know, new requirements. Who would have guessed?) I had architected for some flexibility, but had no room for the complexity he wanted to add. I could twist the clever knife a little deeper, but then woe be the developer that had to debug or add functionality down the road.

I wondered then if another tool might have served me better. Rather than temp tables and recursive DoSelect's, what if I had built logic with app classes? It's much clearer to write rules in PeopleCode than in recursive app engine steps with state records. And by their nature app classes are easier to extend.

When a similar requirement came up later in the project I did a little testing. I wrote some test code that created a set of objects in a PeopleCode event. They were very simple, bean-like objects that held keys and a few additional fields. I created 5,000. Then 10,000. Then 50,000. It took only seconds. The tests to update the table behind the objects performed similarly.

Writing business rules in PeopleCode is an order of magnitude easier. You can encapsulate complexity in classes and methods in a way that app engine sections just cannot approach. The process is easier to maintain, easier to test, and much, much easier to extend.

Now let's be clear, I'm not saying I'm leaving the Church of Set-Based Processing. (I still resolved my run control criteria with an InsertSelect into a temp table in the first step, then worked from there.) But I did learn that implementing complex business rule need not be complex. Sometimes PeopleCode and app classes are the right tool for the job.



Comments:

For my own education, can you provide an example? Even if it's just psuedocode of how you would do this using app classes. I am trying to start writing app classes and your example will go a long way in helping me understand their usefulness.

Posted by Javier on October 13, 2009 at 03:27 PM PDT #

Hi Javier- Here's a small example of how you might create a list of orders. Each order contains one or more lines, and the lines have an item and a quantity. The properties are straightforward, you can reverse-engineer the Order class. /* list of orders */ local Order &current = Create Order(); local array of Object/Any &orders = CreateArrayRept(&current, 0); Local string &bu; Local string &id; Local string &item; Local integer &qty; Local SQL &getOrders = CreateSQL("SELECT BUSINESS_UNIT, ORDER_NO, INV_ITEM_ID, SUM(QTY) FROM ..."); /* fetch and populate list of orders */ While &getOrders.Fetch(&bu, &id, &item, &qty) /* on first item in an order, create a new order object */ If Not(&current.busUnit = &bu And &current.id = &id) Then &current = Create Order(); &current.busUnit = &bu; &current.id = &id; &orders.push(&current); End-If; /* add item to order */ &current.items.push(CreateArrayAny(&bu | &item, &qty)); End-While; Now that you've got a list of orders, you can run them through any business logic you'd like. You might isolate the orders that contain a specific item, you might check the orders against available quantity, you might sort by priority. Let's say I wanted to sort by customer priority. Except that if any customers on the West coast order a specific item, that needs to be top priority. This type of logic is easy to implement in PeopleCode, and if you encapsulate it in an app class. It's also easy to update when sales comes back next week with new rules for prioritizing orders.

Posted by Todd Kummer on October 14, 2009 at 09:56 AM PDT #

That's not very legible. Let me try to figure out what happened to my line breaks.

Posted by Todd Kummer on October 14, 2009 at 09:59 AM PDT #

Thank you, Todd, for taking the time to answer. I think I understand what you mean now. My only concern now is performance, but I guess that's a matter of trial and error to determine what works best. And yes, writing this in app engines is painful. Thanks again Javier

Posted by Javier on October 15, 2009 at 10:34 AM PDT #

Here's the thing about performance. It doesn't necessarily matter which one is faster. If the difference is insignificant, then performance shouldn't dictate how we build. A quick google found the following quote on Wikipedia: "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil."

Posted by Todd Kummer on October 15, 2009 at 11:22 AM PDT #

Post a Comment:
Comments are closed for this entry.