[prev in list] [next in list] [prev in thread] [next in thread] 

List:       orocos-dev
Subject:    [Orocos-Dev] PrivateAttribute?
From:       peter.soetens () gmail ! com (Peter Soetens)
Date:       2010-02-22 9:35:22
Message-ID: 201002221035.22916.peter.soetens () gmail ! com
[Download RAW message or body]

On Wednesday 10 February 2010 14:34:47 Klaas Gadeyne wrote:
> On Mon, Feb 8, 2010 at 4:30 PM, Peter Soetens <peter.soetens at gmail.com> 
wrote:
> > On Friday 05 February 2010 16:50:03 Klaas Gadeyne wrote:
> >> Hi,
> >>
> >> I have a case where it would be useful for me to be able to reuse as
> >> much from the property infrastructure as possible, but not everything.
> >>  In short:
> >>
> >> I would like to be able to read data from a file in an operation of
> >> component A.  That data is already used to set properties of another
> >> component B, so it is already available for free in the cpf format.
> >> Note that, for component A, the data is not to be considered as a
> >> property, but rather as private data not to be exposed to the outer
> >> world.
> >> As a workaround, I now just add the same properties to A and work with
> >> them as properties.  This means I can reuse the data file, don't have
> >> to worry about parsing, and I can reuse a simple
> >> marshalling->loadProperties() to load the data from the file.
> >> However, that also means that any peer component could theoretically
> >> modify those values, which is what i don't want.
> >>
> >> Is there some primitive available in RTT that better fits to my
> >> problem than using properties?
> >
> > You could use the CPF marshaller classes directly, which saves you from
> > adding the property bag to your taskcontext, as a consequence, they
> > remain hidden.
> >
> > To elaborate on this further...
> >
> > The eternal discussion of public vs private is about the tools only. We
> > can't make anything *really* private. The C++ compiler doesn't either,
> > remember. The best we can do is 'mark' it as private and have the tools
> > refuse to display them/look them up in 'certain cases'. This would only
> > allow abuse when not using the tools that take these cases into account.
> 
> Strictly speaking, maybe yes, but look at the following cut and paste
> from reality...

Good. Real-world code speaks.

> In this case, IMHO, it's _not_ just about the tools, it's also about
> semantics and code readability.
> It's about me having to explain people having to use different orocos
> primitives depending on x, y, and z.

Please show an example of how you would like to express in code and 
documentation that a certain pimitive is private.

> 
> Consider the comments in this self-explaining real-life example (just
> copied from "production code").  [*]
> 
> <quote>
> class ValidatorComponent
> 
>   : public TaskContext
> 
>     {
> [snip]
>     protected:
>     /* Make a distinction between
>      * - events that are actually "commands" from other components for this
>      * component, but should be events since otherwise we can't react on
>  them * in our state machines and
>      * - events which are Events that are (or better: should be) fired _by_
>      * this component and to which other components can react.
>      */
>     /* The commands */
>     Event<void(void)> startTestEvent;
>     Event<void(void)> stopTestEvent;
> 
>     /* The real events to be used by this component's SM */
>     /* Shouldn't be fired by another component, but hey */
>     Event<void(void)> fatalErrorEvent;
>     Event<void(int)> operationDoneEvent;
>     Event<void(string)> setSDTypeEvent;
>     Event<void(string, string)> sendMessageEvent;
>     Event<void(void)> physicalErrorEvent;
>     Event<void(void)> recoverEvent;


These are still an open issue... in another thread where I'm waiting your 
answer.

For the commands part, state machines will want to attach callback handlers to 
operations in the component interface, this is wip. 
For the real event part, we're even further away from what you have. I also 
started a thread about this (events turned into output ports), without a 
conclusion yet.

> 
>     /* These are not real-properties and shouldn't be exposed to other
> components.  It's merely a
>      * workaround/shortcut to get the data necessary for the
> validation from the properties of the
>      * excitator.
>      */
>     Property<std::string> SDType;
>     Property<double> stiffness;
>     Property<double> damping;
>     Property<double> amplitude;
>     Property<double> bias;

Your workaround probably needed to be solved at the system level instead of at 
the component level. You probably added too much coupling here (guessing).

> 
>     /* Private Methods put in public API so we can use them in
>  StateMachines */ Method<void(void)> writeLogHeadersMethod;
>     Method<bool(void)> closeLogFilesMethod;
>     Method<void(double)> validateMethod;

I see your point. In 2.0, we group property/operation interfaces in services. 
Expressing that a group of primitives belongs to service named "private" is 
doing what you require. So the SM would call 'private.validateMethod(x)' or 
read 'private.bias'. Calling 'ComponentB.private.bias' would then clearly flag 
as a violation to the reader, but not to the RTT. It's easy and tempting to 
have RTT warn on the use of a 'private' service outside a component, but I'm 
not going to write it. Anyone wanting this will have to propose a patch.

Data Ports are not a part of the service interface, but of the component's 
data flow interface, which causes them to be always 'top level public'. This 
complicates things when you are converting your private Event to OutputPort in 
2.0. It seems 'private' Events will map to operations in a private service (to 
which the local SM can react) and public Events will map to output ports in 
the data flow interface, to which any SM can react.

It's likely that some of this stuff will be for 2.2.

Peter

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic