Re: Haven't done anything real with OOP yet.
From: H. S. Lahman (h.lahman_at_verizon.net)
Date: 11/06/04
- Next message: H. S. Lahman: "Re: class diag associations & polymorphism"
- Previous message: Daniel T.: "Re: class diag associations & polymorphism"
- In reply to: Gregory L. Hansen: "Re: Haven't done anything real with OOP yet."
- Next in thread: Gregory L. Hansen: "Re: Haven't done anything real with OOP yet."
- Reply: Gregory L. Hansen: "Re: Haven't done anything real with OOP yet."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Sat, 06 Nov 2004 17:48:26 GMT
Responding to Hansen...
>>>The main loop in the data acquisition software looks something like:
>>>
>>> get TickCount
>>> if TickCount > NextVoltages
>>> calculate NextVoltages
>>> read voltages
>>> compute V and V^2 sums
>>> if TickCount > NextShutter
>>> calculate NextShutter
>>> move shutter
>>> if TickCount > NextHeater
>>> calculate NextHeater
>>> control heater
>>> if TickCount > NextHeatsink
>>> calculate NextHeatsink
>>>' control heatsink
>>> if TickCount > NextCounter
>>> calculate NextCounter
>>> read counters
>>> if TickCount > NextUpdate
>>> calculate NextUpdate
>>> compute and save voltage averages and standard deviations
>>> update screen
>>
>>This is a fine algorithm description and it is at a useful level of
>>abstraction for addressing issues like encapsulation, allocation of
>>responsibilities, etc. But it is an algorithm description and,
>>consequently, it is very much focused on procedural Do This, then Do
>>This, then Do This, etc.. So...
>
>
> Well, that wasn't a proposal or anything... the DAQ sofware is written,
> that's what the loop does. I was hoping it would clear up how timing
> issues are handled.
I realize that. But it /is/ the starting point for perceiving the
simulation needs. That view needs no conversion to a procedural
application but it does need a conversion (of sorts) to an OO application.
>
>
>>><snip>
>>>
>>>A salient point is that the loop isn't triggered every 60th of a second.
>>>It runs through the loop continuously, as fast as it can. But the
>>>scheduling of events occurs at a 60th second resolution.
>>
>>We get to here with a single continuous polling loop that is running the
>>whole show. At this point I am jumping up and down screaming things
>>like, "Delegate the responsibilities! Collaborate! Six timers! ..."
>>However, six timers compared to a single tick count generator doesn't
>>make sense unless the six basic responsibilities are owned by six
>>different objects and those objects collaborate directly with one
>>another on a peer-to-peer basis and the proper sequencing is enforced by
>>daisy-chaining flow of control between those responsibilities via DbC.
>
>
> I've been wondering whether that's really a good application of OOP. A
> standard example of OOD is the ATM machine. Someone sticks their card in
> the machine, that tells the machine to do something. The machine sends a
> request to Bank of America, and BoA responds whenever it's good and ready
> to. BankUSA, TCF, Wells Fargo, and other banks don't know and don't care
> that this is happening. But a simulation has such unyielding demands of
> every part moving one step at a time. It's not physically meaningful to
> have the target warming in response to heat that will be applied three
> minutes from now. That makes the main loop more attractive as the
> sole administrator of time steps.
Alas, it amazes me how many text books, whose authors should know
better, get the ATM controller wrong. They will have it littered with
classes like Account and it will be talking directly to a DB. In fact,
as a subsystem subject matter, the banking business and persistence are
completely irrelevant because they live on the other end of the network
port. All the ATM controller does is re-dispatch messages from/to the
hardware to/from the network port.
[When the user sticks a card in, the Card Reader hardware generates a
message with a bunch of data values. The ATM Controller software
recognizes the message ID and formats a new message that it dispatches
to the network port. The data in the new message's data packet is the
same as that in the message from the Card Reader. To do that
re-dispatch the ATM Controller software doesn't need to understand the
semantics of the data (e.g., account number) at all; it just needs to
understand it as a set of values encoded in data packets. Eventually
the bank responds with a message from the Network Port whose ID the ATM
Controller interprets to either eat the card or request a PIN. And so
on... When properly abstracted the ATM controller software is actually
pretty dumb but, as you point out, highly reusable across banks. That
reuse is achieved because it doesn't incorporate specific banking notions.]
Now if OO authors can't extract invariants properly and ensure good
cohesion when abstracting from a single problem space, what is an OO
newbie going to do when starting out with a very procedural view of the
simulation to guide abstracting the hardware? B-) This is actually a
good example, by analogy, of my concerns with your problem. The OO
authors go awry because the concerns of banking -- which, after all, is
really why one is doing the ATM Controller in the first place -- are
driving the abstraction of a rather specialized chunk of hardware. It
becomes difficult in that situation to separate the concerns properly.
In your situation it becomes especially difficult to separate the
algorithmic structure concerns because the individual computations
within that structure still have to be accounted for pretty much as-is
in the OO structure.
>
> You mentioned worries about things like propagation delays, but then take
> the computer and electronics out of there entirely. Arrange some initial
> condition, apply heat to one part, and run a simulation to see how the
> heat spreads from one part to another. That's still a worthy type of
> simulation. It might be silly, but you could do an OOA of heat flow in a
> peice of metal with a complicated geometry where each small, discretized
> element is treated as an object that has a temperature, and receives and
> transmits heat to its nearest neighbors. Like a metal bar with an initial
> temperature, then heat is applied to one end, and we want to know T(x,t).
One could, but I am skeptical. A simpler example is the Quicksort
algorithm. One can abstract objects like Pivot and Partition, but no
one is going to encode a Quicksort solution as an OO solution. OO would
be overkill for two reasons. One is that the problem is naturally
computational, so an OO solution is less intuitive (e.g., the OO notion
of Partition is an identifiable entity, which implies well defined
boundaries and some degree of rigidity, while a partition in the
computation is highly fluid in terms of both end points and contained
elements). More important, the OO solution will be more complicated
because it is providing <largely static> infrastructures to support
maintainability. But the value of that is wasted because the Quicksort
algorithm will never change. By extension, a finite differences heat
flow computation may be more complicated, but it is still a
mathematically defined algorithm that doesn't change with time so the OO
benefits are largely lost.
OTOH, a finite differences solution does have some OO appeal because it
/is/ intuitive to think of it in terms of a gaggle of distinct,
identifiable (by location) cells that each do their own thing rather
than having a single, monolithic computation. One can regard that view
as an invariant one extracts from a more complex computation and OO
abstraction happens to be quite effective at extracting invariants. In
addition, there are really two independent algorithms at work: the heat
flow computations at the cell level the control algorithm for
propagating the flows from cell to cell. Those two algorithms need to
be glued together properly, and providing glue is another thing that OO
is good at.
So color me Ambivalent.
>
>
>>I think that has been reflected in some of our discussions. My
>>misunderstandings aside, a number of our differences have been at a more
>>fundamental level. Me: "Model the hardware this way." You: "But in the
>>simulation I could compute it that way." (E.g., real-time vs. relative
>>simulation.) The way the simulation computation is abstracted is
>>driving your view of what needs to be modeled for the hardware (e.g.,
>>the relative time simulation is attractive because it is essentially
>>identical to the single polling loop model of the algorithm description
>>above).
>>
>>IOW, you are starting with the level of algorithmic detail where you
>>want to be and you are looking for a way to distribute that down to
>>objects. That is almost universally common for people converting from
>>procedural development to OO development. I push back by advising you
>>to model the hardware as it is in an OO fashion and then simplifying
>>that view to get to the simulation level of abstraction. In effect the
>>algorithmic stuff gets done almost as an afterthought by connecting the
>>behavior responsibility dots properly.
>
>
> I thought it was more the nature of the simulation. An ATM can wait
> indefinitely for a card to be inserted and a transaction begun. Bank of
> America doesn't have to halt all operations and wait for a single ATM user
> to send a particular request. It's meaningful for the ATM to operate
> without Bank of America, and process transactions with other banks. It's
> meaningful for the ATM to disappear and Bank of America to keep doing
> business without it.
>
> But advancing a complicated system of objects by one and only one time
> step in a pure OO fashion, seems like a mess.
The ATM interactions with customers and the bank are inherently
asynchronous. But they are only asynchronous in terms of interarrival
time; among the interactions there is a fixed sequencing that serializes
them. (That's from the ATM Controller's view; the bank has to deal with
multiple ATMs in parallel.) In contrast, all of your computations are
triggered at fixed intervals, they occur in parallel, and they need to
be synchronized at fixed points in those time streams. Those are quite
different simulation problems.
However, both are easily accommodated in an OOA/D view because the
sequencing issues are always separated from the behavior
responsibilities. That's because message and method are separated and
one connects the behavior dots at a different level of abstraction than
where individual behaviors are defined. It's also because once one has
separated those concerns one can rigorously employ DbC in exactly the
same way for connecting the dots in both situations. But that only
works if one has modeled the hardware as it actually works rather than
the simulation view.
>
>
>>Unfortunately, regardless of how clearly I see the pitfalls, I can't
>>convey that to you because I need a common reference point in the
>>problem space and every time I try to do that we get side-tracked
>>because my understanding of the problem space is ka-ka. So all I can do
>>now is to reverse myself and suggest you look for a simpler problem
>>space, like a garage door opener, as a first OO project.
>
>
> In my model, I think about the only thing remaining that's algorithmic is
> triggering a bunch of objects in sequence to do something. But then they
> decide for themselves what that something is, what data they need, and
> where to get it from. I don't know if that really qualifies as OOP, or
> quasi-OOP, but it seems like a much cleaner and more satisfying design
> than running through a loop that explicitly determines which calculations
> must be done and which data must be handled.
Interestingly, I pretty much agree with this paragraph. The tricky
part, though, is how the triggering is done. So I'll take one more shot
at our single vs. multiple timers discussion...
The hardware system probably has a single clock broadcasting ticks to
all components and each component counts clicks in an accumulator to
determine if it should trigger its activities. As far as it goes, that
lines up exactly with your original proposal where each object
determines whether it should compute or not. However, I argue one has
to go a bit further. The accumulator in each hardware component is
exactly the same except for the threshold value. In fact, the hardware
designer will either use the same discrete part or will cut & paste the
same "canned" gate design in each hardware component. IOW, the
accumulator is the hardware equivalent of a software object instance
that encapsulates the trigger mechanism. In addition, the hardware
designer will not be at all confused about that chunk of PCB or ASIC
real estate being conceptually an entirely different functionality from
whatever the hardware component does once the threshold is met.
So when I argue that the triggering should be done in the same manner as
it is done in the hardware, I mean that quite literally. One should
abstract the accumulator as a unique module that encapsulates a
particular functionality and reuse it by parameterizing the threshold.
I just call that abstraction a Timer. (Note that each instance of Timer
is carnally tied to a specific hardware component via a relationship
just like connecting it to circuit nodes in the hardware component.)
If one does that, then one can accommodate simulation at almost any
level because synchronization will tend to have obvious solutions. For
example, in a simple simulation all that may be needed is to enforce
proper ratios between the trigger thresholds among the Timer instances.
For a more detailed simulation one can introduce delays through data
histories in the collaborations between hardware elements. And for a
really nit-picky simulation one can decompose the hardware components
and subdivide the main trigger frequency within those components. IOW,
once one separates out the individual triggering mechanisms into a
single class abstraction with multiple instances, everything tends to be
fairly scalable as far as the level of simulation is concerned.
*************
There is nothing wrong with me that could
not be cured by a capful of Drano.
H. S. Lahman
hsl@pathfindermda.com
Pathfinder Solutions -- Put MDA to Work
http://www.pathfindermda.com
blog (under constr): http://pathfinderpeople.blogs.com/hslahman
(888)-OOA-PATH
- Next message: H. S. Lahman: "Re: class diag associations & polymorphism"
- Previous message: Daniel T.: "Re: class diag associations & polymorphism"
- In reply to: Gregory L. Hansen: "Re: Haven't done anything real with OOP yet."
- Next in thread: Gregory L. Hansen: "Re: Haven't done anything real with OOP yet."
- Reply: Gregory L. Hansen: "Re: Haven't done anything real with OOP yet."
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|