Business Pattern Irregularity

Over the years I keep encountering new or revisited "nifty tricks" to manage variations-on-a-theme, such as OOP inheritance, ADT's, and HOF's. However, when I try to apply them to the domain of custom business applications, my primary era of experience, I cannot make them "fit nice", and repeated requests for realistic code samples that do from others are so far elusive. Exceptions to the rule (pattern) keep mucking things up. I've concluded that business is generally different than other domains where such ideas work better.

Mathematicians and engineers like to build things that have regularity and modularity. They usually strive to "keep the system clean" such that the parts follow orderly conventions and rules.

However, business decision makers don't value regularity nearly as much as mathematicians and engineers. Business rules are generally shaped by give-and-take negotiation between customers, vendors, politicians, etc. I.E. social interactions. All things being equal, they'd probably settle for regularity if given a choice, but the social bonds and deal-making take priority because that's what they see as their bread-and-butter. (Whether it "should" be this way is wider matter, but probably beyond most IT workers' ability to change.)

The result is patterns with a lot of mucky exceptions. Invariants are either too broad to engineer for, or non-existent. At best one can assign probabilities of change somewhere between 0 and 1. Whereas inheritance, ADT's, and HOF's require true invariants of "rules" in order to be more effective than the less integrated alternatives.

I've thus learned to keep my abstractions optional and of small granularity. I make my biz apps "date abstractions, not marry them". Maybe someday somebody can demonstrate how to use such "higher order" gizmos in typical biz apps with inspectable source code so that we can see how to do it right. Until that day, I will use the lighter-footprint abstractions.

--top

I agree that the domains you describe have high and dynamical irregularities. And imagining regularies where there are none and thus over-engineering with lots of inheritance (where there really is none) or other complex rule building will not help. But I wonder what your 'small footprint' abstraction are. If-then-else chains? Relational modelling mania can cause the same amount of spaghetti code (or should I say -tangle?) than inheritance monsters can.

I generally use a lot of function/method calls with optional named parameters. Complex functions are often composed out of smaller simpler functions such that if a situation can't use the main "big" function, then it can still use at least most of the existing smaller ones. I then only have to reinvent half the wheel. There's an illustration of this under HelpersInsteadOfWrappers near "Dealing with Deviations from Framework".

As far as relational messes, I'd like to see specifics. Also, I'd like to see DynamicRelational in action, which could provide more flexibility than the current "static" RDBMS. -t


Top, I think you have an interesting point, but perhaps the issue is that you aren't familiar enough with these abstractions to know how to best apply them. You mentioned that you generally use a lot of function/method calls with optional named parameters; this, in turn, reminded me of one of PaulGraham's essays (I don't remember which one, but it probably wasn't BeatingTheAverages) where he explained that he considered optional named parameters to be "hacks", but later on discovered that they were very useful, and he wished he had used a lot more of them in earlier code. If you haven't read that essay, I would encourage you to do so, because this is a good example of how Paul used CommonLisp to implement flexible business logic to run circles around his competition.

(In other words, PaulGraham thought that named optional parameters were a useless abstraction that would just complicate things, until he learned how to use them...)

I think knowing how to apply higher abstractions would help you better handle the rough-and-tumble of complex business logic, exceptions and all. But you have to understand how those abstractions work--aye, there's the rub!--because these abstractions can be difficult to learn (particularly if you're like me, and don't have nearly as much time to learn such things as you'd like!). I, for one, have been trying to wrap my head around these things for several months, and I still haven't succeeded, in part, because my study has only occurred in fits and starts. The thing I i find fascinating about languages like CommonLisp and SchemeLanguage, though, is the fact that they have a reputation of being difficult to learn languages, but the reality is that they are amazingly simple to learn--far simpler than popular languages like C or Python--but because they allow you to explore difficult topics in ways that most other languages cannot, they have a reputation of being difficult... --Alpheus

I'd like to see specific examples of such higher abstractions in use or in realistic scenarios. Trial and error can leave behind lots of errors. Plus, other developers may not be able to figure out your abstractions. Ideally, code should be for multiple eyes, not just yours. Readability by team often trumps "elegant" or concise code. Businesses often value predictability over efficiency. While highly abstract code can potentially save lots of labor, stopping a project outright because a follow-on developer cannot follow the code is seen as a black eye. It's the McDonald?'s-on-the-road principle: it's not gourmet, but at least you know you are getting. If you gamble with a no-name restaurant, you may have a great meal, but also risk being sick as a dog. Business owners generally prefer the lower-risk route to software maintenance, and thus wish to avoid alleged "gourmet abstractions". Related: EconomicsOfAdvancedProgramming.

{See HofPattern, and ArrayDeletionExample from "It's not about me" onward, for examples of and discussion about the utility of higher abstractions in business application development.}

Sigh. It's my opinion that JavaScripts?' timer would be better served with an OOP interface. -t

{How would that work?}

You mean from the programmer's perspective, or machine-level implementation?

{From the programmer's perspective. Machine-level implementation is trivial.}

 class timer {    // pseudo-code
    preferedFrequency: Double // in seconds (type = Double Precision)
    maxFrequency: Double // maximum allowed before trigger if cpu busy
    method tick() {
      // handler for timer "clock tick"     
    }
    method maxExceeded(actualDuration: Double) {
      // handler if exceeds maxFrequency
    }
 }
{So you use a FunctorObject? Not unreasonable, though in many cases a HigherOrderFunction is functionally equivalent but syntactically sweeter, especially as it can close over its calling scope without having to explicitly define member elements in whatever is inherited from timer. What is maxExceeded() for? What's a "Double Public"? What language is your example written in?}

"maxExceeded" is used if the timer is unable to trigger the event within the specified time range, such as if the CPU or thread manager is bogged down. I suppose we could pass "actualDuration" to "tick" and let it calculate and determine if it wants to do something different for "long" cycles. Anyhow, if you feel HOF's are "better" in practical and common scenarios, please illustrate.

{Wouldn't it be better to dispense with maxExceeded and simply let the code invoked by tick() determine when it was last called? Most systems provide a system clock -- usually with millisecond resolution -- that can be used to trivially determine this. I've already demonstrated examples of practical and common scenarios on HofPattern and related pages. Again, what language is your example written in?}

I've disagreed with your assessment in those. For one, it would also be harder to attach attributes or more methods to a HOF if later needed. My example is probably not a very good illustration so far, but flexibility is nice. One possibility is a title so that we can monitor or log multiple events with further API calls to a timer or event system. Objects make it easier to extend such; HOF's are just undecorated functions. A pointer to an object gives us much more options and future expansion ability than a pointer to a mere function without changing existing calls. Objects are better future proofing. HOF's are too blunt of an instrument, objects give us an indirection "joint".

{FunctorObjects and HOFs are conceptually and functionally equivalent, but HOFs close over their calling environment, which means you can include any attributes you like from the calling environment by referencing them in the HOF. Objects require that you explicitly define attributes. In HOFs, they can be implicit and/or ad hoc. What's a "Double Public", by the way?}

They are not attributes of the calling environment, but of the timer instance.

{Yes, but they don't have to be. The ability to include arbitrary attributes that vary depending on the calling environment gives considerable flexibility without syntactic overhead.}

Sometimes clearer or explicit attributes and scope is better interface management in a team environment. Related: GreatLispWar.

{The calling environment is almost invariably unambiguous. However, if the limitations of fellow developers in a team are likely to be a problem, then it's best to stick to using ANS COBOL.}

Mastering COBOL for legacy shops is not easy. It has a lot of historical baggage and lots of little gotcha's. Plus, it's not so well-suited for modern databases and interactive IO. And if you have to use JCL, holy moly!

{Stick with VB6 and VBA, then.}

Both are deprecated. (The industry loved VB6 for non-enterprise apps from a developer resource perspective. Quick to learn, quick to get "good enough" up and running. However, it was a PITA as far as deployment. Microsoft left a niche open when they decided to "enterprise-atize" VB.)

{Yup, so if COBOL, VB6 and VBA are out, that means languages that support higher-order constructs are in, like C# and Javascript, right?}

Clipper (ExBase dialect) had HOF's, and it still withered. I don't see widespread use of HOF's in MS-language custom apps I encounter. I see it more in JavaScript, but I also hear grumbling about how it makes for confusing code and debugging. There's a fairly big lynch-mod who would like to burn JS and related coding patterns at the stake, but are stuck with it because of QwertySyndrome.

If this is degenerating into yet another HOF Fight, then we should take it somewhere else.


NodeJsAndHofDiscussionTwo explores a possible OOP-based timer interface.


See Also: AreBusinessAppsBoring, EightyTwentyRule, ChangePattern, GenericBusinessFrameworkUnobtainable


CategoryBusinessDomain, CategoryAbstraction


EditText of this page (last edited September 10, 2014) or FindPage with title or text search