Re: patterns for getting system status...




H. S. Lahman wrote:


OK, if I understand this you have a service hierarchy something like:

{Client}
|
|
V
{Controller}
|
|
V
{Devices}

Yes, that is correct.

Are the devices the status providers and the client needs the status so
it is a pass-through? (Below I am still confused about who needs and
provides status and the role of your <intermedate> subsystem in status
processing.)

In some cases the Controllers state is influenced by some
of the devices. The status is not merely a pass-through to
the Strategic Decision Maker (client), the controller does
look at most aspects of it, as the status is relevant to the
control. Why the <Client> needs the same status data,
is probably because there is a GUI somewhere that requires
this data, but I think its merely for the purpose of visual
reflection. There may be one or two decisions that are
influenced by this status, but the responsibility of control
lies with the <Controller>, therefore it evaluates the status
mostly. Some of the status is relevant to state of the
controller, and this is influenced by discretes. Other status
are relevant to the embedded devices that are being controlled.
It may seem strange that the controller is necessary (as the
embedded devices are controllers in their own right), but the
controller is necessary because it has the bigger picture. In
"this" case it is aware of inventory of each embedded device,
and it runs programs that use the embedded devices
collaboratively. It is also bound to safety devices that it
uses to make its own decisions. The safety devices are
actually bound to the {Embedded Devices} as well for safety
reasons, so as far as safety is concerned, we don't perform
control, but it influences the collaborative action. A mouth
full, that is.

Actually putting names to the devices would make it very clear (but
I'm
afraid I can't).

If both the Client and the Devices are legacy systems, I think you may
be in trouble if your Controller really has to make control decisions
(as opposed to simply resolving syntactic mismatches between
interfaces).

Yes, they are, and yes, we have to.

For example, the Client "giving" Controller the Device to
control leads to the obvious question: if the Client knows what Device
is relevant, why doesn't it talk to it directly?

I know that the client has too many other things to take
care of. I think the reporting of status to the client is merely,
and mostly for display purposes. I also think the client has some kind
of fault tree analysis that it performs on a system level. I actually
don't
think the providing of status data to the client in its current form
is that
beneficial. There is some real coupling there, IMO.

[I've worked on a previous system where we only provided the client
with
enumerated code/status pairs. Each code represented a sub-system.

The codes were fed into a hierarchy (we used the Composite pattern for
this) to determine the status. If lower level systems were faulty, it
was
immediately reflected due to their parent-child relationship with
higher
level sub-systems. We also had codes that could represent links,
and if a link were fault, status of all the children to which that
link
was bound was ignored. We also had something similar to the Black
Board pattern as a layer prior to the data (or code stream) going
being
fed into the hierarchy. This recursively identified codes that were
related to each other, and was used to identify more complex
faults. For example, if all the antennas are faulty, then perhaps
it is the feed to the antennas, and not the antennas themselves.
We never had errors that complex that we had to recurse more
than twice. One recursion generates a new error, and the next
causes the new error to bind to another that generates a third (the
real cause). The result then gets reflected on a GUI. The hierarchy
could be build with a simple configuration file]

In such a context the
Client should provide context information from its perspective that the
Controller can properly interpret to map to a specific Device. IOW, the
Client should have no clue specific Devices exist.

I don't think it does. We have a database with programs that
collaborate
the control of the devices. The Strategic system only knows which
programs to execute under which circumstances. We interpret the
programs and execute these in terms of the devices.

Unfortunately, that means that all my sage advice is pretty useless. B-(
I see the problem you are having as being a fundamental one for
application partitioning, but you don't have any choice about the
subsystem subject matters or interfaces...

No, the read was really good.

In application partitioning the hierarchy is usually determined by flows
of requirements that form a directed, acyclic graph. The higher level
(more abstract) subsystems/layers define requirements for lower level
subsystems/layers. However, that is orthogonal to communication flows.

Yes, agreed. Requirements are driven by higher level sub-systems and
the
bulk of data flows in the opposite direction (in layman's terms?)

For example, in a complex application that employs a GUI to communicate
with the user, the problem solution defines what needs to be
communicated with the user. IOW, the problem solution defines the
interface for the GUI subsystem and, consequently, indirectly defines
the GUI design. However, the GUI subsystem is likely to initiate the
vast majority of messages as the user clicks stuff.

Yes, I've experienced this too.

So I think push vs. pull is somewhat irrelevant.

It may be irrelevant at sub-system level, but I was thinking more in
terms of data flow in my own application (Data-flow between the
surrogates and the "Local status model"). After the discussion I might
actually
attempt to pass Status data from the "Devices" through to the "Local
Status
Model" as much as possible without touching it. Only data required for
control will be viewed by the surrogates. The reason I think push vs.
pull is an important decision within the boundaries of one software
entity
or application, is that pulling often requires data sharing, and
causes
contention in a multi-threaded system, whereas pushing does not
cause any contention at all. Pushing causes more data to be copied,
especially if one has the case where many observers (or views) are
interested in the same data. This is only a problem if memory is very
constrained. I would usually always prefer pushing within the confines
of one application, if given the choice.

Ah, good. So you are using surrogate objects to represent the devices
that are actually external to your subject matter. In effect, they
provide an output Facade interface that subsystem implementation objects
talk to when they need to send messages to the outside world.

Exactly as you describe, yes. Facades are interfaces (or ABCs), and
their
implementation is sometimes a realization of a couple of interfaces.

That is, one can provide a
much more generic interface for the internal objects to talk to and let
the surrogate re-dispatch based on context information within its
implementation.

Agreed.

I don't think so. You have described passing copies of objects that are
part of the implementation of one subsystem to another subsystem that
interacts with those objects. That completely trashes subsystem
encapsulation by exposing the implementation of the source subsystem.

No, I think you misunderstood me. We only pass data between sub-
systems.
Nevertheless, I agree that we cannot be to dependent on this data. We
have to isolate (or dictate) what we need from this data in terms of
our
own requirements only, so the requirements of our neighbors don't
influence
us too much. Unfortunately the format of the data could change, yes,
if
requirements of any of the other sub-systems change. It is inevitable,
I
think that we would then change. All we can control is how much, and
how
easy (or how isolated). If this data change influences our own
requirements,
well then change is obvious.

The fact that the objects are copies does not change that. If
requirements on the originating subsystem change so that the object must
change, then that subsystem will generate a copy of the new object. (It
has to do that because it shouldn't know why the copy is needed, so it
must produce an exact copy.) That means that the implementation of the
receiving subsystem may have to change to process the new object
definition properly.

Therefore changes in the originating subsystem implementation are
directly triggering changes in the receiving implementation even though
the original requirements changes are not relevant to the receiver
subject matter. That is severe implementation coupling.

You may not have a choice with the legacy interfaces. However, you seem
to be isolating that stuff in surrogate objects within the subsystem.

I agree with all this, and it is a good read, because emphasis is good
(reinforcing).
Yes, we do have those surrogates in other sub-systems. This one is
still a baby -
i.e. I'm only starting with it.

That at least decouples the rest of the subsystem form "seeing" those
exposed implementation details. Nonetheless, the implementation of those
surrogate object is still within the scope of your subsystem so if the
passed objects change you still have to "touch" your subsystem
implementation. What you are doing is just isolating that potential
change /within/ your subsystem.

Yes, I cannot see how I cannot touch my implementation when changes
occur with this one. I think I'm going to spend some time with your
blog
and your ideas in future. I would like to implement systems where
change
in interface specification between sub-systems causes no touching of
implementation. Of course, when requirements are influenced locally,
this is impossible.

Describe exactly what I should not do.

For the first sentence: Don't pass objects or copies of <problem space>
objects that implement one subsystem to another subsystem that interacts
with them. Just pass the data that the client subsystem needs in a
by-value data packet.

OK, I think we are currently doing this. I must admit I'm not exactly
sure
what you mean by "by-value data packet", but using my imagination,
I would say its a data-packet containing either various related, or
one
value. This could be identifiable by ID. This is more or less what we
do.

With respect to the rest of the paragraph, I am still confused about who
the status providers are, who needs the status, and what (if anything)
your software does to the status. Modifying my diagram above:

Your diagram is correct. I hope my description at the top clarified it
for you. I also described that we do indeed use the status.

I assume the ultimate source of status are the Devices and the Strategic
Subsystem wants to know about status. The big question (triggered by
"more or less" in your description) is then how much massaging your
subsystem does to the status...

Yes, status involves our state as well, and in some cases faults
detected
in communication links to devices, etc. So we don't only get status
from
devices, but derive some status ourselves. We also give status
concerning
discretes (is the weight off the aircrafts wheels? for instance).

For example, for the moment let's assume the status is a pure
pass-through.

Not, but in the cases where it is I'll consider the example given. I
could
perhaps mention that there are many devices that have similar types
functionally, but have different message interfaces. From this
perspective
we are (perhaps luckily) forced to provide facades to surrogates
during
control of them(using the bridge pattern). Does this make sense?

The key, though, I think is to design your subsystem around the subject
matter functionality of the requirements first and then worry about how
to convert from the interfaces your subsystem would ideally like to see
and those that are provided by the legacy code. (If you got the subject
matter semantics right, there /must/ be a way to convert between the
interface syntaxes.)

Yes, isolate what we require... Our requirements influence us, and
theirs should not.

Alas, you don't have much choice is the legacy code is passing objects.
In that case I would buy into your setDataIF -- provided it is used in
the surrogate implementation. B-)

If you consider data objects, the it is passing objects, however no
behavior
exists in the data, therefore I think not. Whether all the data is
relevant
and necessary is another story. I may want to look at that.

Thank you for your detailed response. Like I said, I will take the
next
year to study that blog :-).

Werner

.



Relevant Pages

  • Re: [RFC] Control Groups Roadmap ideas
    ... > Control Groups, or that I know others are planning on or working on. ... > included a facility for sending signals to all members of a cgroup. ... > - changing the way hierarchy ids are calculated - simply ORing ... > together the subsystem would no longer work since that could result in ...
    (Linux-Kernel)
  • Re: [RFC] Control Groups Roadmap ideas
    ... > Control Groups, or that I know others are planning on or working on. ... > included a facility for sending signals to all members of a cgroup. ... > - changing the way hierarchy ids are calculated - simply ORing ... > together the subsystem would no longer work since that could result in ...
    (Linux-Kernel)
  • Re: [RFC] Control Groups Roadmap ideas
    ... > Control Groups, or that I know others are planning on or working on. ... > included a facility for sending signals to all members of a cgroup. ... > - changing the way hierarchy ids are calculated - simply ORing ... > together the subsystem would no longer work since that could result in ...
    (Linux-Kernel)
  • [RFC] Control Groups Roadmap ideas
    ... Control Groups, or that I know others are planning on or working on. ... This was motivated by the recent "freezer" subsystem proposal, ... included a facility for sending signals to all members of a cgroup. ... Currently you can only add/remove subsystems to a hierarchy when it ...
    (Linux-Kernel)
  • Re: Programming TS
    ... To program the TS Client you either need to use the web version, msrdp.ocx, ... interfaces are mostly the same. ... >I am not using the Web "ActiveX" Control. ...
    (microsoft.public.windows.terminal_services)

Loading