From: Robert Martin on
On 2007-01-23 13:25:22 -0600, frebe73(a)gmail.com said:
>>
>> The payroll system in the book is partitioned into code that knows
>> about the DB schema, and code that does not. The dividing line is a
>> set of interfaces that translate high level concepts like "GetEmployee"
>> into appropriate SQL. To the left of the interfaces the code deals
>> with Employees. To the right the code deals with SQL, tables, rows,
>> and columns.
>
> How many getEmployeeBySomeCriteria methods do you think you will end up
> with in a normal payroll application?

I imagine it will be quite a few, though fewer than the number of
embedded SQL statements that would exist if I did not put them behind
an interface.

> Why do you want to hide predicate
> logic and set operations behind a procedural interface?

I don't. I want to give the operations meaningful names. For example:

findEmployeesEligibleForRetirement()

is more evocative than a long SQL statement that doesn't mention
retirement at all. Think of the functions as compilable comments that
describe what the SQL beneath them is intended to do.

This has the additional benefit that when the eligibility rules change,
the callers of findEmployeeEligibleForRetirement() will be unaffected.

>
>> In any application, OO or not, this translation must take place.
>
> Absolutely not.

The data is on the disk. It must be translated into some kind of
TableRow structure or similar. Then it must be unpacked from that
structure into something convenient for the application to use.

Now it is entirely possible that the application will simply index into
the TableRow structure every time it wants to access the data; but even
that is an *implicit* translation into a more convenient form.

>> There is no duplication. There is no waste.
>
> If you have a table employee and a class employee, you obviously have
> duplication.

You have the same "duplication" if you have a table "employee", and a
set of convenient variables used to hold parts of one of the rows from
time to time. You even have it if you have a TableRow structure that
holds the employee row.

> If you have five variants of getEmployeeBySomeCriteria,
> you obviously have duplication.

I don't see that at all. The five functions may simply call a more
general function passing in specific parameters.

--
Robert C. Martin (Uncle Bob)��| email: unclebob(a)objectmentor.com
Object Mentor Inc.� � � � � ��| blog:��www.butunclebob.com
The Agile Transition Experts��| web:���www.objectmentor.com
800-338-6716� � � � � � � � ��|



From: topmind on


On Jan 23, 2:38 pm, Robert Martin <uncle...(a)objectmentor.com> wrote:
> On 2007-01-23 11:30:27 -0600, "topmind" <topm...(a)technologist.com> said:
>
> > Robert Martin wrote:
>
> >> In any application, OO or not, this translation must take place. All
> >> we have done with the code in the book is to assign a place for that
> >> translation.
>
> > First off, this could be done without OOP. We could have functions that
> > wrap the SQL. Thus, it is not really an OO-specific thing.I quite agree. OO is just one of many potential technologies for
> separating concerns. It happens to be one that is both popular an
> effective.

I have not seen actual example code of "effective".

>
> >> There is no duplication. There is no waste. There is simply a
> >> separation of concerns. Those concerns would exist regardless of
> >> whether they were separated or not.
>
> > It is additional code and likely additional work.Very little "additional" code. Indeed, it might even be less code
> since all the SQL is concentrated in one place rather than spread out
> and duplicated.

Where have I proposed duplicating SQL? One can put it into shared
functions, or perhaps use DB views. I still claim a p/r version would
be significantly less code. I suppose I'll have to code it up to prove
it to you.

> We can argue about whether the net work is greater or
> less. From my point of view it is significantly less since I can
> forget about the SQL and Schema while dealing with the business rules
> and interface.

SQL = biz logic.

That request is like me asking to wrap the OO so that I can forget
about the OO and deal with the "business logic". You can claim that SQL
and RDBMS are "low level" all you want. But repetition of claim does
not make it true. Those who know how to use SQL and RDBMS effective can
shorten and simplify code because OO is crappy and inconsistent at
collection handling and meta-tizing attribute management.

>
> > The more beurocracy
> > you put between the RDBMS and the app code, the more places you will
> > often have to change.So let's not have bureaucracy. Let's have a well defined interface
> that acts as a partition rather than a mediator.

Its a Bloatiator in my book.

>
> The partitioning of the code in the Payroll example is just that, a
> partitioning. There is no vast bulk of "extra code". The database
> code in the example is primarily concerned with generating and
> executing SQL. That code would have to be SOMEWHERE in the application
> irrespective of whether you use OO or not.

Yes, but you create *unnecessary* extra cubbie holes for it, which
creates cubbie hole maintenance busy-work.

Plus, your instantiation adds code. Even if we did wrap the SQL,
procedural would be shorter in most cases.

// procedural
doSomething(foo);

// OOP
somethingDoer sd = new SomethingDoer()
sd.do(foo)

These add up to a fair amount of code in your app. It is anti-KISS. (It
could potentially be blamed partly on the spefic OO language.)

>
> > For example, if a new attribute or table is
> > needed for a given calculation, then likely there will be two 2 units
> > that need changing: the SQL along with the SQL wrapper's interface, and
> > the app code that uses it. However, if the SQL was together, then only
> > one unit needs changing.Let me translate this into procedural-speak. If a new attribute or
> table is needed for a given calculation, then likely there will be two
> places in the code that need changing. The SQL, along with the code
> that moves the query results into convenient variables, and the app
> code that uses those variables.

Please clearify. What kind of change are you thinking about?

>
> We can make sure that only one unit is changed by cramming all our code
> into a single unit. Clearly that's not ideal.

As a general rule of thumb, units should be divided mostly to avoid
repetition, not for the sake of dividing stuff because each choppage
results in interface overhead (parameter lists, etc.). It wastes time
and code on martialling stuff thru and back to and from the interfaces.
Some languages have nice features to reduce these, such as nested
functions. But that is another issue.

> We have to have some
> kind of partitioning scheme. The scheme I chose in the book was to
> separate code that knows about database implementation details from
> business rules.
>
> > Thus, wrapping is more effort: one has to make
> > 2 hops instead of one.
>
> Wrapping is not more effort because it always needs to be done one way
> or another. Either we pull the data out of queries an into objects, or
> we pull the data into convenient variables.
>
> > Swapping DB vendors is fairly rare.
>
> Swapping DB vendors is a TEST, not a goal. You know you have isolated
> the business rules from the DB implementation details if you can swap
> the DB.

One can test the module that calls the query.

>
> We can argue about whether or not it is wise to separate business rules
> from the DB implementation. In many applications this might not be the
> right choice. For many applications it is. There are many reasons why
> such a separation might be beneficial.

You have not showed your economic decision-making process. What are
your assumptions? What are your assumed frequencies of given change
scenarios, etc? I am not dismissing your factors, only saying they have
small weights compared to others in most cases.

>
> 1. Unit tests don't need the DB. This is actually a very big deal for
> some applications.
>
> 2. DB code makes business rule code hard to read. This may or may not
> be true depending on the language and platform you are using.

It does? This may be a subjective issue. It can make it easier to read
in my opinion.

>
> 3. Changes to the database and schema need to be isolated from the
> business rules. For example, the business rule code need not be
> affected by a change from embedded SQL to stored procedures.

Only if the cost-benefit weighings favor it. It depends on a lot of
issues.

>
> 4. Different Expertise. The folks doing dataase queries may not be the
> same folks who are writing the business rules. It would be nice if
> they could play in different sandboxes.

If more time was spent learning SQL and relational *instead* of OOP and
GOF patterns, then one perhaps would not need such a split. SQL can
express business logic quite concise at times.

>
> 5. Database tools sometimes require preprocessing or postprocessing of
> the code. It would be nice if the business rule code were not involved
> in such machinations.
>
> etc. etc.

Most of the time such *is* related to biz rules. I suppose we would
have to explore a scenario.

>
> > I like to spend my time on real work, not red tape.
>
> I agree. If maintaining the separation between Business Rules and
> Database turns into a lot of red tape, then it should be eliminated. I
> have certainly seen such red-tape implementations, and have gotten rid
> of them for that reason. Most of the time that red-tape has more to do
> with convoluted layering schemes and "clever" code generation
> techniques, than with simple partitioning. The amount of red-tape in a
> simple partitioning model is very limited.
>
> > I also would like to see your comments on taxonomy issues.
>
> I thought your comments were very intresting. There is indeed an
> argument to be made for allowing every employee to enjoy every payment
> scheme. Why shouldn't salaried employees be able to get commissions,
> or submit overtime hours? If that were a requirement, then some
> reworking of the payroll example would be in order.

My point is that removal of mutually-exclusive choices is a fairly
common change pattern. Polymorphism makes such more difficult than p/r.

>
> What would we need to do? We'd simply put a collection of
> PayClassification objects into each employee,

"Collection of"? Bit by bit you turn your app into a roll-your-own
database. And when auditors want a print-out of a given employee's
classifications? Do you reinvent report writers? Or you want to search
all employees with such and such conditions? Do you reinvent a little
query language for your classification collection? Sorting? Searching?
Printing?

OO tends to result in repetition of concepts like this:

class A {
method add;
method change;
method delete;
method search;
method sort;
method find;
method collectionVerbEtc;
}
class B {
method add;
method change;
method delete;
method search;
method sort;
method find;
method collectionVerbEtc;
}
class C {
method add;
method change;
method delete;
method search;
method sort;
method find;
method collectionVerbEtc;
}
class D {
method add;
method change;
method delete;
method search;
method sort;
method find;
method collectionVerbEtc;
}


> and use the Composite
> pattern to treat them as a single PayClassification. Within the
> business rules themselves this would require no changes to any of the
> existing modules. The CompositePayClassification would need to be
> added. The individual transaction objects would then create and modify
> employees with the Composite object instead of with the individuals.
>
> This is simple, and keeps the code nicely partitioned. Changes to
> salary policy do not affect changes to hourly policy, etc.
>
> So, in fact, the "taxonomy" does not get in the way, and actually
> facilitates the new mode of operation while keeping the code nicely
> separated.
>
> --
> Robert C. Martin (Uncle Bob) | email: uncle...(a)objectmentor.com

(Note: Google recently added some bugs to their message browser, and it
sometimes messes up the quote nesting and jams text together.)

-t-

From: Robert Martin on
On 2007-01-22 08:31:46 -0600, lilburne <lilburne(a)godzilla.nospam.net> said:

> Hasn't Payroll been solved? I thought getting paid was one of the first
> things that Software Engineers and Consultants, irrespective of
> methodology, had got bug free.

Spoken like someone who has never run a business.

Question: How do you get paid when the company you provided services
to goes out of business without warning?

You might think the risk of this is low, especially when the companies
are well-estabblished and well-known. Alas, that would be a
misaprehension.
--
Robert C. Martin (Uncle Bob)��| email: unclebob(a)objectmentor.com
Object Mentor Inc.� � � � � ��| blog:��www.butunclebob.com
The Agile Transition Experts��| web:���www.objectmentor.com
800-338-6716� � � � � � � � ��|



From: Robert Martin on
On 2007-01-22 10:25:52 -0600, JXStern <JXSternChangeX2R(a)gte.net> said:

> My point being that one is not at all forced to use behavior as a
> criteria, there are other frameworks. And I see nothing in iterative
> or the portmanteau as RCM would have it of Agile, that necessitates
> behavior as a key.

The coat-rack of Agile doesn't care about the dichotomy of
behavior/data. The bifold-trunk of Agile is about very short
iterations, collaboration and teamwork, incremental testing, and many
other behaviors and techniques. The catmandu of Agile should really be
left out of this particular argument.

A computer is a device that turns data into behavior. Programs are
data that describe the behaviors that the computer will perform.
Software is about behavior.

This doesn't mean that data is unimportant or irrelevant; clearly data
is very important. Indeed, there are whole programs written to provide
behaviors that keep data safe and provide access to data (they are
called databases).

However, despite the deep importance of data, programs are still
descriptions of behavior.
--
Robert C. Martin (Uncle Bob)��| email: unclebob(a)objectmentor.com
Object Mentor Inc.� � � � � ��| blog:��www.butunclebob.com
The Agile Transition Experts��| web:���www.objectmentor.com
800-338-6716� � � � � � � � ��|



From: Robert Martin on
On 2007-01-23 10:04:38 -0600, frebe73(a)gmail.com said:

>>> Payroll behavior is producing a payment file to the bank, using data
>>> supplied by employees and adminstrators. The data is the important
>>> thing. Behavior is only the method of transforming data. Like many
>>> other business applications, it is all about providing information or
>>> data to different actors. The behavior of the application is low-level
>>> stuff that is not important on higher abstractation levels.
>>
>> I suggest you test your hypothesis by creating a personnel database for
>> IBM and then writing the paychecks by hand. You will be allowed to
>> type SQL commands at the terminal to access the database. You will
>> also have the tax code for all the states and the federal government,
>> as well as all the insurance codes, union contracts, etc. You should
>> be able to write the paychecks easily with all that information since
>> there is not much behavior in the system.
>
> The paychecks are a data structure. How they are produced and how they
> are communicated to the receiver is just a low-level issue.

Known as a program.

> As you
> describe above, a payroll system may be implemented without use of
> computers.

If we choose to use a computer, then we will need a program.

> On a very hight abstractation level we can describe the requirements of
> the system by defining the data model for the input data and the output
> data, and data derivation rules. If we choose to use computer software
> to implement it, is an implementation issue.

That particular implementation issue contains an entire engineering
discipline and science.

--
Robert C. Martin (Uncle Bob)��| email: unclebob(a)objectmentor.com
Object Mentor Inc.� � � � � ��| blog:��www.butunclebob.com
The Agile Transition Experts��| web:���www.objectmentor.com
800-338-6716� � � � � � � � ��|