Archived

This forum has been archived. Please start a new discussion on GitHub.

Why operations on classes?

bernard
bernard Jupiter, FL
Hi guys,

Impressive product, congratulations!

I like the stated goal of "pick[ing] a feature set that is both sufficient and minimal: you can do everything you want, and you can do it with smallest and simplest possible API.". Of all the CORBA features you could keep or discard, I am surprised you put operations on Slice classes in the "keep" bucket.
What's the value in specifying local operations in a language such as Slice or IDL? I see the downside: you can't get any signature you want for your functions and methods; where is the upside?
Local object behavior can as easily be provided through derivation (the functions/methods are on the class implementation) or wrapping (another object holds the data). For example:
// Slice
class PrinterState { string message };

// C++
Printer myPrinter(initial->getPrinter());

Wrapping also provides better data encapsulation.

Then, which kind of problem is best solved by implementing an interface with a class? It may be sometimes convenient to do so at the implementation level (have the same object be a servant and class object at the same time); but why expose such a detail in Slice?

If Slice classes had only data members, their mapping would be much simpler; it would not make sense to pass them by proxy (reference) so no need for the * Slice notation (interface would always be by proxy, classes always by value).

Maybe you could share a good use case for these features?

Thanks!

Bernard

Comments

  • Re: Why operations on classes?
    Originally posted by bernard


    Impressive product, congratulations!


    Hi Bernard! Thanks for the kind words!
    Originally posted by bernard


    I like the stated goal of "pick[ing] a feature set that is both sufficient and minimal: you can do everything you want, and you can do it with smallest and simplest possible API.". Of all the CORBA features you could keep or discard, I am surprised you put operations on Slice classes in the "keep" bucket.
    What's the value in specifying local operations in a language such as Slice or IDL? I see the downside: you can't get any signature you want for your functions and methods; where is the upside?
    Local object behavior can as easily be provided through derivation (the functions/methods are on the class implementation) or wrapping (another object holds the data). For example:
    // Slice
    class PrinterState { string message };

    // C++
    Printer myPrinter(initial->getPrinter());

    Wrapping also provides better data encapsulation.


    I'm not sure I fully understand. First, classes don't have to be transferred by-value. You can do so, but you don't have to.

    If you decide to transfer classes by value, then operations give you a standard interface to such classes. For example, you could have a class "Address", with an operation "string format()", which returns the address in a format suitable for the client. How exactly format() is implemented depends on your client. You simply derive from Address, implement format() as you wish, and then install a factory for your derived class.

    If you do not like this approach, but rather prefer to have operations and data separate, you can still opt to not add operations to classes.

    As for non-local classes, they are in essence interfaces with data members added. Due to language constraints (like in Java), there must be a separate class type for such "interfaces with data members".

    Now, non-local classes with data members are for persistence: With Freeze, you can automatically make instances of such classes with data members persistent. Slice is not just an interface definition language, it is also a language to describe persistent state. (We decided to use one single language for both type descriptions and persistence, because this make writing Ice programs a lot simpler.)

    You might object to classes with operations in the non-local case, because the client will have knowledge about data members in the servers, which it doesn't really need to know about. For small projects and rapid prototyping, this is usual not a problem. However, if you consider this a problem for large-scale projects, then you can move the operations into an interface, keep the data members in the class, and have the class implement the interface. Your client will then only get the Slice code for the interface, while your server gets the class with data members implementing the interface.
    Originally posted by bernard


    Then, which kind of problem is best solved by implementing an interface with a class? It may be sometimes convenient to do so at the implementation level (have the same object be a servant and class object at the same time); but why expose such a detail in Slice?


    See the explanation above. It's again important to note that Slice is not only a type and interface definition language. It is also a language for describing persistent state.
    Originally posted by bernard


    If Slice classes had only data members, their mapping would be much simpler; it would not make sense to pass them by proxy (reference) so no need for the * Slice notation (interface would always be by proxy, classes always by value).

    Maybe you could share a good use case for these features?


    I hope my explanation above explains the use cases.

    We are currently working together with another company on a very large-scale project that uses Ice (sorry, can't disclose yet who it is -- we're under NDA). This other project needs persistence everywhere. So far the class approach for persistence (as opposed to having a separate persistence language) worked out very well. It simplifies development dramatically.

    Take care,
    Marc