Plasma::Service API review

Kevin Ottens ervin at kde.org
Sat May 17 01:01:59 CEST 2008


Hello,

Damn, being offline sucks really... typed my mail while you were sending the 
new draft, and I didn't find the time to review the new draft yet because I 
got buried under tons of mail. Bleh!

Le Friday 16 May 2008, Aaron J. Seigo a écrit :
> > itself is "Plasma::Service", that said that probably explains why
> > KConfigGroup got through. :-)
>
> KConfigGroup simply provides an easy way to do a number of interesting
> things related to key/value pairs.

Well, apart from the defaults (and well, using a QMap instead of a 
KConfigGroup is exactly the same if you already fill the map) what does it 
provides? I really don't get why KConfigGroup is so special in this context.

> > > Plasma::Service allows interaction with a "destination", the definition
> > > of which depends on the Service itself. For a network settings Service
> > > this might be a profile name ("Home", "Office", "Road Warrior") while a
> > > web based Service this might be a username ("aseigo", "stranger65").
> >
> > A "profile" or a "username" are "destinations"? Sounds odd to me. In
> > particular the "username" as destination example for a web service
> > doesn't feel natural at all to me (you'd definitely expect a url for this
> > one).
>
> think of twitter. the destination is the username.
> think of networking. one sets up profiles for commonly used settings.
>
> for many traditional web services, you are quite right, however. plasma
> isn't just about web services of course.

"A service represents an addressable set of operations of an implementation 
that are designed to be exposed for use by other implementations ..."
[http://www.osoa.org/download/attachments/35/SCA_AssemblyModel_V100.pdf?version=1 
p81]

Also, in the OASIS SOA Reference Model, section 3.2.2 "Interacting with 
services":
"Interacting with a service involves performing actions against the service. 
In many cases, this is accomplished by sending and receiving messages, but 
there are other modes possible that do not involve explicit message 
transmission. For example, a service interaction may be effected by modifying 
the state of a shared resource. However, for simplicity, we often refer to 
message exchange as the primary mode of interaction with a service."

So the "message transmission" metaphor is implied by service interaction 
(despite the implementation). And to me, "message" kind of implies "address".


> > > A Service provides one or more operations, each of which provides some
> > > sort of interaction with the destination. Operations are described
> > > using config XML which is used to create a KConfig object with one
> > > group per operation. The group names are used as the operation names,
> > > and the defined items in the group are the parameters available to be
> > > set when using that operation.
> >
> > Reading this, I'm kind of wondering if the API shouldn't be splitted. It
> > looks like it's talking both to applet writers (who use Service) and
> > service writers. They're probably not the same audience, and as an applet
> > writer I'd run away from this class after reading this (from the applet
> > writer point of view it looks too much like implementation details... he
> > just want to call a service operation). To me it looks like KConfigGroup
> > is overkill there (again for applet writers) I'd expect at most a
> > QMap<QString, QVariant> for the parameters.
>
> we'd end up with a set of QMaps, we'd want to know what the default values
> are, etc. i originally started out doing a QMap based implementation and
> discovered i was adding all sorts of API that actually mapped 1:1 with
> KConfigGroup.

OK, I'd still like to be enlightened on that if you don't mind.

> it really ends up being pretty much exactly the same thing, just with a lot
> less API in Plasma::Service when KConfigGroup is used.
>
> it also lets Services use config xml to define things.

Yup, I just wish the type had another name if we end up using that. ;-)

> > > A service is started with a KConfigGroup (representing a ready to be
> > > serviced operation) and automatically deletes itself after completion
> > > and signaling success or failure. See KJob for more information on this
> > > part of the process.
> > >
> > > Services may either be loaded "stand alone" from plugins, or from a
> > > DataEngine by passing in a source name to be used as the destination.
> >
> > I think that the vocabulary might need to be reevaluated. To me service
> > would relate to Service Oriented Architecture (SOA) and in such a case a
> > service is a collection of operations. Of course the same service can be
> > running at several places, and then you identify which one you're calling
> > using an address.
>
> so instead of "destination" you find "address" more natural?

Yup, definitely. To me "destination" is well... the destination (that is the 
service itself) while the "address" is how to get there. Yeah, I'm tortured 
like that...

> > > Sample use might look like:
> > >
> > > Plasma::DataEngine *twitter = dataEngine("twitter");
> > > Plasma::Service *service = twitter.serviceForSource("aseigo");
> > > KConfigGroup op = service->operation("update");
> > > op.writeEntry("tweet", "Hacking on plasma!");
> > > service->start(op);
> >
> > Just to place a call that looks weird to me. I mean, once the call is
> > done, my Plasma::Service instance is deleted. It effectly only did _one_
> > call to a service. I'd be tempted to say that this class is
> > Plasma::ServiceCall then and not Plasma::Service.
>
> see the new draft of the API which adresses this by providing a ServiceJob
> class.

Yeah yeah, getting there... :-)

> > >     ~Service();
> >
> > Fine with me. I'd tend to repeat the "virtual" here (that's really a
> > matter of giving more information to the reader).
>
> personally i prefer to only mark newly virtual methods.

Fine with me.

> > >     static Service* load(const QString &name, QObject *parent = 0);
> >
> > Now confusing, as an applet writer which one am I supposed to use? This
> > one, or the constructors?
>
> load, obviously. three times to say "make the constructors protected"? =P

Well, it was a sequential writing as I was reading the stuff. If I had load() 
first maybe I would have used only one time. ;-)

> > propose a setAddress(address)
>
> 'address' is very webby and doesn't make a lot of sense for non-webby
> things like "my Home network profile"

See above.

> > >     QStringList operations() const;
> > >     KConfigGroup parameters(const QString &operation);
> >
> > That's really the part where we mix services and calls to services.
>
> no, this is all about getting information on the service. =) calling doesn'
> thappen till much later.

Right.

> > s/operations/operationsName/? (you're returning only the names, not the
> > operations themselves).
> > s/parameters/operationParameters/?
> >
> > >     void start(const KConfigGroup &parameters);
> > >
> > >     QString name() const;
> > >     QVariant result() const;
> >
> > This one made me wonder if that'd make sense in KJob directly... On the
> > other hand not all the classes inheriting from KJob would need it.
> >
> > Now are we sure we want that at all? That kind of encourage people to use
> > the job synchronously (using exec(), which means blocking) without
> > further thinking.
>
> you get the object in the finished signals from KJob and can query there.

Wasn't really my point. But after thinking a bit more about it you don't have 
the choice anyway.

> > >     virtual void registerOperationScheme();
> >
> > Really unclear to me.
>
> this is called when the service should register the operation scheme, e.g.
> call setOperationsScheme(QIODevice *xml). the reason it's done this way is
> that QIODevice is not copyable, so i couldn't just have a QIODevice
> *operationsScheme() without forcing some ugly new/delete semantics on
> subclasses. i could force it to return an xml document or a qstring
> instead, but then we can't read out of a file or other source.
>
> > That somehow looks like a hook called at initialization time so that I
> > have the opportunity to call setOperationScheme()?
>
> exactly.

Damn, I guessed well. I'm still not sure about the name of this method, but 
I've no better proposal atm.

> >
> > OK, now my proposal for the apidox example if Service and ServiceCall
> > were splitted:
> > Plasma::DataEngine *twitter = dataEngine("twitter");
> > Plasma::Service *service = twitter.serviceForSource("aseigo");
> > QMap<QString, QVariant> args;
>
> and then add methods for getting what parameters are expected for a
> service, and what types and defaults

Make that a:
QMap<QString, QVariant> args = service.defaultsForOperation("update");
Assuming it's prefilled you get the parameters, their defaults and their 
types.

> and runtime documentation for them and 
> ... you end up with KConfigSkeleton.

KConfigGroup actually provides runtime documentation? I can't find it in the 
apidox (shows how expert I am with KConfigGroup :) ). Assuming it provides it 
that's probably not much API...

> > As a last (maybe crazy) remark, we might want to make it look even closer
> > to something like QtDBus on the applet writers side
>
> in which way exactly? setting up a connection, connecting to a named
> service, etc?

We can probably skip the connection setup, but maybe the "connecting to a 
named service" part... bah, scrap that, as I said "maybe crazy" (basically I 
had in mind that Plasma::Service could be our "QDBusInterface" with a simpler 
address scheme, and async calls with KJob).

Regards.
-- 
Kévin 'ervin' Ottens, http://ervin.ipsquad.net
"Ni le maître sans disciple, Ni le disciple sans maître,
Ne font reculer l'ignorance."
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 194 bytes
Desc: This is a digitally signed message part.
Url : http://mail.kde.org/pipermail/panel-devel/attachments/20080517/96321bfa/attachment.pgp 


More information about the Panel-devel mailing list