Business Logic Definition Discussion Two

(Continued from BusinessLogicDefinitionDiscussion)

This is a description of a sample sales lead tracking system for a hypothetical civil engineering firm. It's a "composite character" of some apps I've worked on. The organization hears about potential projects (customers with needs) and the marketing team contacts them to ask questions and butter them up.

Draft schema:

 projects (table)
 -------
 projID
 orgRef  // foreign key to Orgs, "ref" means FK
 title
 descript
 status    // open, proposal, accepted, rejected, other, cancelled
 whenDiscovered // date
 notes

orgs (table) ----------- orgID title orgType contact // see PartyPattern for fancier address/contact notes

persons (table) --------- personID orgRef name position contact notes

meetups (table) // AKA "encounters" ---------- meetID meetType // phone, restaurant, our-place, their-place, etc. statusRate // status (planned, etc.) or ranking: A to F of "feeling" of meeting when // date/time where duration // in hours or portion of notes

meetupAssoc (table) // Meetup assocatiations (many-to-many) ---------------- meetRef personRef notes

Yes, most of such would be run-of-the-mill CRUD and reporting, but usually various "business rules" creep in over time, such as: send email notices for open projects that have had no contact for more than 4 months.

--Mr. Top

This is classic data entry and reporting. There's good coin to be made churning these out, and building them successfully requires extensive general business and domain knowledge and analysis skills, but they're almost entirely presentation logic: The essence is that data goes in at one end and is reported at the other. Business logic -- which computes and records costs, taxes, schedules, timetables, bills, routes, plans, payrolls, etc. -- is generally absent.

But "computing taxes" affects output also. If nobody sees the computation results then it doesn't need to be done. Just about any app is like that: the user only ultimately cares about the output because they don't "consume" the internal workings. I see no useful reason to make a distinction between logic that adds two numbers together versus logic that uses the value of one number to determine if the second one is displayed under a given circumstance, for example. Again, you are giving Boolean computations a lower-class (or different class?) status than numeric computations. Partitioning by calculation result value type on a large scale is utterly silly and arbitrary; of no discernible economic value. Would you partition the app in two parts, one by integer calculations and one by real/double computations???

Further, reports often do sum and average information. True, it usually doesn't "save" such, but you guys have previously said that "persistence" is not the difference maker (plus, it's continuous also). You need to formulate more concise rules beyond "I know it when I see it because I'm [allegedly] smart and experienced". -t

Perhaps I can illustrate (or not -- it depends on your answer) via the simplest possible example. Which is the better code? This...

   writeln(a + b)
...or this?
   r = a + b
   writeln(r)
Be sure to explain why you answer the way you do.

ItDepends. Remember, I use estimated maintenance patterns along with frequency times costs to make most of such decisions. I would need to know more about the context to make such estimates.

And, let's try to separate definition issues from "good design" issues, if possible.

I have no further explanations that can help. Those who argue that the latter example is better code will appreciate the distinction between business logic and presentation logic, and why it exists. Those who argue that ItDepends, will not.

That's not very helpful text for those of us who allegedly "don't get it". Is WesternReductionism dead?

No, but I've got better things to do than debate this.

All else being equal, less code is better than more code, and the second one is more code. However, the WetWare of most humans works better when big processes are sub-divided into smaller sub-processes to some extent: too fine a ratio can be just as bad as no division. (See DivideAndConquer) Finding the right balance (division ratio) comes from experience and from estimating how maintainer WetWare will likely work, and likely future ChangePatterns of the domain requests. (In other words, how likely is a domain need going to come along to make use of a smaller sub-division.) In summary, we have two concerns: "Readability" of the code as-is, and second, will division make future changes easier to make.

A third concern is that the second is probably easier to debug using most existing debuggers. But it may not be practical to write every block/section under the assumption that every one will need to be debugged in the debugger; only a small fraction will. If the chance is large, then it's crappy code and should be inspected more closely before testing via a run.

In short, the second example is better code, unconditionally. It's better code because the first line -- which exemplifies the essence of business logic -- is separate from the second line, which exemplifies presentation logic. We can thus change business logic independently of presentation logic, and change presentation logic independently of business logic. Being able to change components independently is always good.

Obviously, this is a trivial example, but the underlying concept applies to arbitrarily-complex systems. Conflating business logic with presentation logic -- exemplified by the first example -- complicates maintenance, development, testing and debugging regardless of WetWare.

ChangePatterns often don't fit our ideal pre-conceived notions or classifications. Over time one gets a "feel" for what kind of changes are likely, but often they vary on a wide variety of aspects/dimensions. Thus, "change independently" is a somewhat elusive target. In general I agree with designing/partitioning around ChangePattern's. I just disagree that "presentation" versus "business logic" is sufficiently clear and a good (change-fitting) separation criteria.

For example, a given "aspect" of business may have a presentation and non-presentation aspect to it (assuming there is such a thing for the sake of argument). The change is on the aspect itself, not the presentation side or the non-presentation side. Let's say it's an activation of a feature. If the feature is activated, then it affects both the presentation side and the non-presentation-side. To make it make it easier to switch on and off, we partition by the feature, NOT it's presentation-ness:

      // feature X
      if (feature_X_IsOn) then
        event foo(...)  // register an event handler
           presentationStuff(...)
        end event
        event bar(...)
           nonPresentationStuff(...)
        end event
      end if

   r = a + b
   writeln(r)

   r = a + b
   document.write(r)

    function writeln(x)
      document.write(x)  
    end function

        bldgp = big.long.dotty.giant.path;  // (but find a better name than shown here)
        ...
        bldgp.write(...);
        // Instead of:
        big.long.dotty.giant.path.write(...);
.
   r = a + b
   writeln(colouredRed(r))
   // is changed for the Web version to:
   r = a + b
   document.write(cssRed(r))

If you split by presentation-ness, then the condition has to be duplicated in two places: the presentation side and the non-presentation side, making two spots that would need changing under activation logic change requests instead of one. (Note: I use a VB-like syntax because it's easier to recover from TabMunging, not because I'm promoting a syntax style.)

Maybe if I saw some sample semi-realistic code and we went though typical changes together we can see such directly and compare and contrast alternatives. It may be what you feel is "common" differs from my experience. That happens, for each brain tends to remember different kinds of events over time.

There is rarely any ideal partitioning factor/dimension/aspect. Most apps involve a good many cross-cutting aspects and grouping on Factor A de-groups on Factor B, hurting Aspect B change costs. And it also may vary per app or per domain such that there is no universal "best" partitioning, only least-evil compromises. Any general or "always partition by X" rule is highly suspect. SimulationOfTheFuture by comparing each candidate grouping is my favorite technique for choosing division aspects for reasons given in the topic.


See BusinessLogicDefinition


MayThirteen


EditText of this page (last edited June 4, 2013) or FindPage with title or text search