Fog Creek Software
Discussion Board




Is "business logic" by nature procedural?

In thinking about a new project, I've come to a (to me) surprising conclusion: not everything written in C++ should be object-oriented.  My thinking goes like this.

C++ was designed (obviously) to support object-oriented coding, but business logic is naturally procedural.  Low-level things, like UI code or database access, can and should be written in an object-oriented way; business logic, though, cannot, and so should not.  That is, these things should be maintained in separate "layers" of code.  Object-oriented things should be object-oriented; procedural things should be procedural. 

In my opinion, object-oriented code is easier to develop, but harder to maintain, than procedural code.  So, things that tend to change (the business logic) should be done in the easier-to-maintain procedural way; things that tend not to change (how the UI and the database interact, the metadata layer, etc.) can be done in an object-oriented way.  This also follows the rule-of-thumb to separate code that changes rapidly from code that changes slowly, to prevent artificial shearing layers from arising.

The implication is that since business logic is procedural by nature, there's little real advantage to code re-use.  So, if you have code that's used in several places, you should resist the urge to create a common function, and just cut-and-paste it.  Now, I know this is heresy and I will burn in hell for it, but for business logic I think it makes sense.  The problem that typically occurs is that a function is created to be called from two places, but soon the callers' needs diverge.  At that point, the function is hacked to make it work both ways, for example by passing in Boolean flags.  Soon more callers are added, each with slightly different needs.

After several iterations of this, over a long enough period of time, with multiple people involved, the function is a hopeless mess.  If the code lent itself to "object-oriented-ness", things like virtual functions and inheritance could be used to refactor the function.  But business logic is, in my experience, virtually impossible to treat that way (partly because of the "impedance mismatch" issue).  So, cut-and-pasting the code from the start would have resulted in easier-to-maintain code.

Opinions?  Also, give that original thought is like original sin, I'm sure entire books have been written on this subject... anyone know of any?

Grumpy Old-Timer
Friday, October 10, 2003

Yep, I quite agree. In my case it's manufacturing test software, which by definition is procedural: Apply stimulus to device under test, measure response, take action based on response, etc.

I use objects for the "supporting cast", such as instruments or devices on RS-232 or GPIB interfaces, but the core of the program is procedural.

The shoe fits, so wear it!

Mark Newman
Friday, October 10, 2003

There's 3 pages saying this in Coplien's _Advanced C++ programming styles and idioms_, in the section that the index calls "transactions, business"; I read this book because Meyers recommended it as mind-expanding.

As an example, the procedure for an airplane turning right is:

left_aileron.lower()
right_aileron.raise()
elevators.raise()
rudder.right()
throttle.increase()

A transaction is a procedure that operates on several objects: it isn't a member of any single object.

Still, I wouldn't take this as an argument for procedural instead of O-O ... it's for procedural as well as O-O. "Objects tht characterise system resources still tend to encapsulate change best in the long run" (although airplane.turn_right() is a procedure, it's still operating on object-oriented aileron, elevetors, etc.).

Christopher Wells
Friday, October 10, 2003

> ... cut-and-paste it.  Now, I know this is heresy ...

I love cut-and-paste; it's copy-and-paste that I avoid. For example if you have a procedure that does ABC and you want a procedure that does ADC, then assuming you don't want to pass in an extra boolean, nor a function pointer nor functor, nor use a virtual function, then at least refactor so that A and C are subroutines.

Christopher Wells
Friday, October 10, 2003

my turn to burn in hell.

I would argue that for all non-trivial business apps, the business logic should be placed in a rules/workflow engine.

You get to keep the o-o, and make it easy enough to change the business rules. Most can be broken into components. Most  of these can be reused. If your engine is able to handle exceptions, then you have these, but the basic rules exist.

Tapiwa
Friday, October 10, 2003

YES!

OOP is great for designing a lot of software.  I don't think it is as good for business logic.  Cobol shines at business logic, not because of its recent OO additions,  but because of its old school procedural nature.

Milton
Friday, October 10, 2003

Actually, business logic is more declarative than it is procedural or object-oriented.

We may write procedural or O-O code to implement it, because that's the nature of the programming languages we use. But most of the logic isn't really step-by-step and algorithmic by nature; business rules like "the account must have a balance of at least X in state YY to be eligible for the interest rate of Z%" would lend themselves more to languages or engines that do declarative processing.

T. Norman
Friday, October 10, 2003

Grumpy,

You're really making two points as I read it.  First, the programming of business logic doesn't fit (comfortably) into an OO approach.  Second, business logic resists code reuse.

I can see a case for your first point (thought I do agree with Tapiwa, in principle).

But I've benefitted so much from code reuse (independent from OO implementations) that I don't agree with the second point.    If I have a bit of code that is appropriate in different routines it becomes its own routine or function.  If the business requirements evolve to requires a different "flavor" that's when I decide to modify the routine for both or create a new approach for the caller that is changed.

My view is probably tainted by the fact our company (I'm in an I.S. shop) tries to keep business units aligned, so if the business changes for one there is a pretty good bet the code should change for all.

Rob H
Friday, October 10, 2003

There's a good presentation given by Bjarne Stroustrup at Technetcast[1] where he says pretty much the same thing.

http://technetcast.ddj.com/tnc_play_stream.html?stream_id=613

Ged Byrne
Friday, October 10, 2003

I agree with the others that claim that business logic is better modeled with rules than either an object-oriented or a procedural approach.  Rulebases are incredibly easy to maintain and map quite well onto the complicated scenarios that arise when modelling business processes.

Since most of us don't have rule engines available, though, my second choice is still objects.  I use an approach similar to the transaction approach described above.  You can get variations from such a scheme in a number of ways (inheritance, delegation, strategy pattern, etc), without having to duplicate complicated functions wholesale or introduce complicated systems of booleans.  The biggest problem I have with this approach is more about managing object relationships. Each such object may need to know about many other objects in order to coordinate their working together, so it can be painful to make sure they all tie together correctly.

As an aside, if you don't need super high throughput on your rules, it's pretty simple to build a basic, forward-chaining rule engine using a SQL database.  Each fact type is a table.  When a new fact is inserted, a trigger can fire to update derived tables representing the join nodes of a RETE.

The approach is described in enough detail for implementation in this book, by Patrick Henry Winston:

http://www.amazon.com/exec/obidos/asin/0201533774

I've used this approach in a couple projects and it works pretty well in practice.  The hard part is parsing everything.

rule maker
Friday, October 10, 2003

Copy and paste programming is incompetance.
We normalize code for the same reason we
normalize databases, to prevent anomolies.

You will never remember to update all copies.
You will not be able to take advantage of
new features in old code. A bug fix in one
copy won't be fixed and other copies.
Other people won't even know about
the copies.

The worst problems i have ever seen have
been because the lazy ass programmers
copying code from some idiot who didn't
know what they were doing in the first place.

It's a nightmare and it is without excuse.

If you had a clue how to parameterize your
code to take advantage of reuse then you wouldn't
need to resort to copy and paste. If something
has a variation then there is always a way to
handle it if, if you have the discipline and
professionalism to do so.

Every OO program is also procedural. What is
happening in a method but a procedure?

I agree that business programms are largely rule
based. If you cared you would probably do things
that way. But you are lazy and say just be
procedural and even then i can't manage
to think about my code, so i'll copy and paste.

Great heabilyjeebily.

god's sword
Friday, October 10, 2003

Wow, and I thought *I* was grumpy...

Thanks, everyone else, for the pointers...

Grumpy Old-Timer
Friday, October 10, 2003


"Business logic" is not necessarily procedural.  I see business logic as the conditionals... the prerequisite for determining a business response.

Business responses to those condigions... very procedural.

And I agree... object methods are procedural.  But of course I think "object orientation" is only an extension of modular programming - a method of packaging code.

Sorry, I'm not in the hype business.

Joe AA
Friday, October 10, 2003

"object methods are procedural..."

There is a subtlety here that sometimes gets missed.  It is true that individual methods are procedural.  What objects bring to the table, when they are done properly, is a more dynamic kind of interaction between the methods.

In traditional procedural code, one method calls another calls another.  The sequence of calls is static and can be determined at compile time.  What's more, each time a procedure makes a call on some other procedure, the other procedure is the *same* procedure every time.

With objects this call chain is dynamic; it depends on the runtime environment.  A method/procedure can call some other procedure, and while it's true that that other procedure will always have the same *name* it is not necessarily true that that other procedure will have the same implementation.

In traditional procedural code this kind of behavior was often implemented by using function pointers or another method to turn code into data.  Object languages make this a first class language characteristic.

I guess to sum up, even though statically procedural and object oriented approaches look basically identical, the dynamic picture is radically different.

hoover
Friday, October 10, 2003

<quote>
In my opinion, object-oriented code is easier to develop, but harder to maintain, than procedural code
</quote>

huh?

does not compute
Friday, October 10, 2003

I mean for the average programmer, not for you and I...  :)

Grumpy Old-Timer
Friday, October 10, 2003

Object-oriented code can be hard to maintain, and it can be easy. It depends:

I find browsing Java code in Eclipse, (given good JUnit code coverage) very easy to maintain. (It almost feels like an interpreted language.)

I find C++ in Visual Studio .Net (with some CppUnit coverage) absolute hell to maintain. (I can't quickly see the results of coding without pressing a "Big Build Button" and waiting...and then fixing obscure header and linking problems that are nothing to do with the problem I'm solving.)

About a year and a half ago, I did a little Java coding in JBuilder,  and it felt more like doing C++ in Visual Studio, than doing Java in Eclipse.

I learned C++ back in 1994, but although I haven't used it much, it has had a terrible influence on me. I wish I'd learned Smalltalk first. When everything in your system is an object, and everything can be inspected and debugged uniformly, and where code changes become live in your system as soon as you've typed them in you start to think differently. It's like experiencing the feelling you get when you realise that you don't have to manage memory in your application all over again.

I don't think you need procedural code for anything in a high-level business application, but I think most of us haven't learned object-orientation properly. I blame the popularity of C/C++, modelling techniques based on entity-relationship modelling that maskquerade as "object-orientation" and the dominance of the relational model.

If I were teaching today, I'd use Smalltalk or possibly Ruby as technology and elements of Extreme Programming and Responsibility Driven Design as techniques. (I'm seriously disappointed with most of the mainstream object-oriented languages and methods around.)

Recently, I started learning Smalltalk using Dolphin Smalltalk. I highlighted a piece of code and ran it. When it blew up, the debugger came up. I fixed the code in the debugger, and could restart the computation at the point of failure with the new code.

Procedural code is code I can't easily test or refactor. Making everything an object and knowing how to unit test, refactor and use design patterns makes life so much easier. Nowadays, I only use procedural code for little shell scripts.

You can use objects very well with business logic. For example, see what Joe Yoder is up to: http://www.joeyoder.com/

Dafydd Rees
Wednesday, October 15, 2003

*  Recent Topics

*  Fog Creek Home