Table of Contents Previous Next
Logo
The Slice Language : 4.21 A Comparison of Slice and CORBA IDL
Copyright © 2003-2008 ZeroC, Inc.

4.21 A Comparison of Slice and CORBA IDL

It is instructive to compare Slice and CORBA IDL because the different feature sets of the two languages illustrate a number of design principles. In this section, we briefly compare the two languages and explain the motivation for the presence or absence of each feature.
Slice is neither a subset nor a superset of CORBA IDL. Instead, Slice both removes and adds features. The overall result is a specification language that is both simpler and more powerful than CORBA IDL, as we will see in the following sections.

4.21.1 Slice Features that are Missing in CORBA IDL

Slice adds a number of features over CORBA IDL. The main additions are:
• Exception inheritance
Lack of inheritance for exceptions in CORBA IDL has long been a thorn in the side of CORBA programmers. The absence of exception inheritance in CORBA IDL prevents natural mappings to languages with equivalent native exception support, such as C++ and Java. In turn, this makes it difficult to implement structured error handling.
As a result, CORBA applications typically use a plethora of exception handlers following each call or block of calls or, at the other extreme, use only generic exception handling at too high a level to still yield useful diagnostics. The trade-off imposed by this is rather draconian: either you have good error handling and diagnostics, but convoluted and difficult-to-maintain code, or you sacrifice error handling in order to keep the code clean.
• Dictionaries
"How do I send a Java hash table to a server?" is one of the most frequently asked questions for CORBA. The standard answer is to model the hash table as a sequence of structures, with each structure containing the key and value, copy the hash table into the sequence, send the sequence, and reconstruct the hash table at the other end.
Doing this is not only wasteful in CPU cycles and memory, but also pollutes the IDL with data types whose presence is motivated by limitations of the CORBA platform (instead of requirements of the application). Slice dictionaries provide support for sending efficient lookup tables as a first-class concept and eliminate the waste and obfuscation of the CORBA approach.
• Idempotent operations
Knowing that an operation is idempotent permits the Ice run time to transparently recover from transient errors that otherwise would have to be handled by the application. This makes for a more reliable and convenient platform. In addition, idempotent operations (if they do not modify the state of the object) can be mapped to a corresponding construct (if available) in the target language, such as C++ const member functions. This improves the static type safety of the system.
• Classes
Slice provides classes that support both pass-by-value and pass-by-proxy semantics. In contrast, CORBA value types (which are somewhat similar) only support pass-by-value semantics: you cannot create a CORBA reference to a value type instance and invoke on that instance remotely.
Slice also uses classes for its automatic persistence mechanism (see Chapter 36). No equivalent feature is provided by CORBA.
• Metadata
Metadata directives permit the language to be extended in a controlled way without affecting the client–server contract. Asynchronous method invocation (AMI) and asynchronous method dispatch (AMD) are examples of the use of metadata directives.

4.21.2 CORBA IDL Features that are Missing in Slice

Slice deliberately drops quite a number of features of CORBA IDL. These can broadly be categorized as follows:
• Redundancies
Some CORBA IDL features are redundant in that they provide more than one way to achieve a single thing. This is undesirable for two reasons:
1. Providing more than one way of achieving the same thing carries a penalty in terms of code and data size. The resulting code bloat also causes performance penalties and so should be avoided.
2. Redundant features are unergonomic and confusing. A single feature is both easier to learn (for programmers) and easier to implement (for vendors) than two features that do the same thing. Moreover, there is always a niggling feeling of unease, especially for newcomers: "How come I can do this in two different ways? When is one style preferable over the other style? Are the two features really identical, or is there some subtle difference I am missing?" Not providing more than one way to do the same thing avoids these questions entirely.
• Non-features
A number of features of CORBA IDL are unnecessary, in the sense that they are hardly ever used. If there is a reasonable way of achieving something without a special-purpose feature, the feature should be absent. This results in a system that is easier to learn and use, and a system that is smaller and performs better than it would otherwise.
• Mis-features
Some features of CORBA IDL are mis-features in the sense that they do something that, if not outright wrong, is at least of questionable value. If the potential for abuse through ignorance of a feature is greater than its benefit, the feature should be omitted, again resulting in a simpler, more reliable, and better performing system.

Redundancies

1. IDL attributes
IDL attributes are a syntactic short-hand for an accessor operation (for read-only attributes) or a pair of accessor and modifier operations (for writable attributes). The same thing can be achieved by simply defining an accessor and modifier operation directly.1
Attributes introduce considerable complexity into the CORBA run time and APIs. (For example, programmers using the Dynamic Invocation Interface must remember that, to set or get an attribute, they have to use _get_<attributename> and _set_<attributename> whereas, for operations, the unadorned name must be used.)
2. Unsigned integers
Unsigned integers add very little to the type system but make it considerably more complex. In addition, if the target programming language does not support unsigned integers (Java does not), it becomes almost impossibly difficult to deal with out-of-range conditions. Currently, Java CORBA programmers deal with the problem by ignoring it. (See  [9] for a very cogent discussion of the disadvantages of unsigned types.)
3. Underscores in identifiers
Whether or not identifiers should contain underscores is largely a matter of personal taste. However, it is important to have some range of identifiers reserved for the language mapping in order to avoid name clashes. For example, a CORBA IDL specification that contains the identifiers T and T_var in the same scope cannot be compiled into valid C++. (There are numerous other such conflicts, for C++ as well as other languages.)
Disallowing underscores in Slice identifiers guarantees that all valid Slice specifications can be mapped into valid programming language source code because, at the programming language level, underscores can reliably be used to avoid clashes.
4. Arrays
CORBA IDL offers both arrays and sequences (with sequences further divided into bounded and unbounded sequences). Given that a sequence can easily be used to model an array, there is no need for arrays. Arrays are somewhat more precise than sequences in that they allow you to state that precisely n elements are required instead of at most n. However, the minute gain in expressiveness is dearly paid for in complexity: not only do arrays contribute to code bloat, they also open a number of holes in the type system. (The CORBA C++ mapping suffers more from the weak type safety of arrays than from any other feature.)
5. Bounded sequences
Much the same arguments that apply to arrays also apply to bounded sequences. The gain in expressiveness of bounded sequences is not worth the complexity that is introduced into language mappings by the feature.
6. Self-referential structures via sequences
CORBA IDL permits structures to have a member that is of the type of its enclosing structure. While the feature is useful, it requires a curiously artificial sequence construct to express. With the introduction of CORBA valuetypes, the feature became redundant because valuetypes support the same thing more clearly and elegantly.
7. Repository ID versioning with #pragma version
#pragma version directives in CORBA IDL have no purpose whatsoever. The original intent was to allow versioning of interfaces. However, different minor and major version numbers do not actually define any notion of backward (non-)compatibility. Instead, they simply define a new type, which can also be achieved via other means.

Non-Features

1. Arrays
We previously classified arrays as a redundant feature. Experience has shown that arrays are a non-feature as well: after more than ten years of published IDL specifications, you can count the number of places where an array is used on the fingers of one hand.
2. Constant expressions
CORBA IDL allows you to initialize a constant with a constant expression, such as X * Y. While this seems attractive, it is unnecessary for a specification language. Given that all values involved are compile-time constants, it is entirely possibly to work out the values once and write them into the specification directly. (Again, the number of constant expressions in published IDL specifications can be counted on the fingers of one hand.)2
3. Types char and wchar
There simply is no need for a character type in a specification language such as slice. In the rare case where a character is required, type string can be used.3
4. Fixed-point types
Fixed-point types were introduced into CORBA to support financial applications that need to calculate monetary values. (Floating-point types are ill-suited to this because they cannot store a sufficient number of decimal digits and are subject to a number of undesirable rounding and representational errors.)
The cost of adding fixed-point types to CORBA in terms of code size and API complexity is considerable. Especially for languages without a native fixed-point type, a lot of supporting machinery must be provided to emulate the type. This penalty is paid over and over again, even for languages that are not normally chosen for financial calculations. Moreover, no-one actually does calculations with these types in IDL—instead, IDL simply acts as the vehicle to enable transmission of these types. It is entirely feasible (and simple to implement) to use strings to represent fixed-point values and to convert them into a native fixed-point type in the client and server.
5. Extended floating-point types
While there is a genuine need for extended floating-point types for some applications, the feature is difficult to provide without native support in the underlying hardware. As a result, support for extended floating-point types is widely unimplemented in CORBA. On platforms without extended floating-point support, the type is silently remapped to an ordinary double.

Mis-Features

1. typedef
IDL typedef has probably contributed more to complexity, semantic problems, and bugs in applications than any other IDL feature. The problem with typedef is that it does not create a new type. Instead, it creates an alias for an existing type. Judiciously used, type definitions can improve readability of a specification. However, under the hood, the fact that a type can be aliased causes all sorts of problems. For many years, the entire notion of type equivalence was completely undefined in CORBA and it took many pages of specification with complex explanations to nail down the semantic complexities caused by aliased types.4
The complexity (both in the run time and in the APIs) disappears in absence of the feature: Slice does not permit a type to be aliased, so there can never be any doubt as to the name of a type and, hence, type equivalence.
2. Nested types
IDL allows you define types inside the scope of, for example, an interface or an exception, similar to C++. The amount of complexity created by this decision is staggering: the CORBA specification contains numerous and complex rules for dealing with the order of name lookup, exactly how to decide when a type is introduced into a scope, and how types may (or may not) hide other types of the same name. The complexity carries through into language mappings: nested type definitions result in more complex (and more bulky) source code and are difficult to deal with in languages that do not permit the same nesting of definitions as IDL.5
Slice allows types to be defined only at module scope. Experience shows that this is all that is needed and it avoids all the complexity.
3. Unions
As most OO textbooks will tell you, unions are not required; instead, you can use derivation from a base class to implement the same thing (and enjoy the benefit of type-safe access to the members of the class). IDL unions are yet another source of complexity that is entirely out of proportion to the utility of the feature. Language mappings suffer badly from this. For example, the C++ mapping for IDL unions is something of a challenge even for experts. And, as with any other feature, unions extract a price in terms of code size and run-time performance.
4. #pragma
IDL allows the use of #pragma directives to control the contents of type IDs. This was a most unfortunate choice: because #pragma is a preprocessing directive, it is completely outside the normal scoping rules of the language. The resulting complexity is sufficient to take up several pages of explanations in the specification. (And, even with all those explanations, it is still possible to use #pragma directives that make no sense, yet cannot be diagnosed as erroneous.)
Slice does not permit control of type IDs because it simply is not necessary.
5. oneway operations
IDL permits an operation to be tagged with a oneway keyword. Adding this keyword causes the ORB to dispatch the operation invocation with "best-effort" semantics. In theory, the run time simply fires off the request and then forgets all about it, not caring whether the request is lost or not. In practice, there are a problems with this idea:
The semantics of oneway invocations were poorly defined in earlier versions of CORBA and refined later, to allow the client to have some control over the delivery guarantees. Unfortunately, this resulted in considerable complexity in the application APIs and the ORB implementation.
Architecturally, the use of oneway in IDL is dubious: IDL is an interface definition language, but oneway has nothing to do with interface. Instead, it controls an aspect of call dispatch that is quite independent of a specific interface. This begs the question of why oneway is a first-class language concept when it has nothing to do with the contract between client and server.
Slice does not have a oneway keyword (even though Ice supports oneway invocations). This avoids contaminating Slice definitions with non-type related directives. For asynchronous method invocations, Slice uses metadata directives. The use of such metadata does in no way affect the client–server contract: if you delete all metadata definitions from a specification and then recompile only one of client or server, the interface contract between client and server remains unchanged and valid.
6. IDL contexts
IDL contexts are a general escape hatch that, in essence, permit a sequence of name–string pairs to be sent with every invocation of an operation; the server can examine the name–string pairs and use their contents to change its behavior. Unfortunately, IDL contexts are completely outside the type system and provide no guarantees whatsoever to either client or server: even if an operation has a context clause, there is no guarantee that the client will send any of the named contexts or send well-formed values for those contexts. CORBA has no idea of the meaning or type of these pairs and, therefore, cannot provide any assistance in assuring that their contents are correct (either at compile or run time). The net effect is that IDL contexts shoot a big hole through the IDL type system and result in systems that are hard to understand, code, and debug.
7. Wide strings
CORBA has the notion of supporting multiple codesets and character sets for wide strings, with a complex negotiation mechanism that is meant to permit client and server to agree on a particular codeset for transmission of wide strings. A large amount of complexity arises from this choice; as of CORBA 3.0, many ORB implementations still suffer interoperability problems for the exchange of wide string data. The specification still contains a number of unresolved problems that make it unlikely that interoperability will become a reality any time soon.
Slice uses Unicode for its wide strings, that is, there is a single character set and a single defined codeset for the transmission of wide strings. This greatly simplifies the implementation of the run time and avoids interoperability problems.
8. Type Any
The IDL Any type is a universal container type that can contain a value of any IDL type. The feature is somewhat similar to exchanging untyped data as a void * in C, but improved with introspection, so the type of the contents of an Any can be determined at run time. Unfortunately, type Any adds much complexity for little gain:
The API to deal with type Any and its associated type description is arcane and complex. Code that uses type Any is extremely error-prone (particularly in C++). In addition, the language-mapping requires the generation of a large number of helper functions and operators that slow down compilations and take up considerable code and data space at run time.
Despite the fact that type Any is self-describing and that each instance that is sent over the wire contains a complete (and bulky) description of the value’s type, it is impossible for a process to receive and re-transmit a value of type Any without completely unmarshaling and remarshaling the value. This affects programs such as the CORBA Event Service: the extra marshaling cost dominates the overall execution time and limits performance unacceptably for many applications.
Slice uses classes to replace both IDL unions and type Any. This approach is simpler and more type safe than using type Any. In addition, the Slice protocol permits receipt and retransmission of values without forcing the data to be unmarshaled and remarshaled; this leads to smaller and better performing systems than what could be built with CORBA.
9. Anonymous types
Earlier versions of the CORBA specification permitted the use of anonymous IDL types (types that are defined in-line without assigning a separate name to them). Anonymous types caused major problems for language mappings and have since been deprecated in CORBA. However, the complexity of anonymous types is still visible due to backward compatibility concerns. Slice ensures that every type has a name and so prevents any of the problems that are caused by anonymous types.

1
IDL attributes are also second-class citizens because, prior to CORBA 3.x, it was impossible to throw user exceptions from attribute accesses.

2
As of version 2.6.x of CORBA, the semantics of IDL constant expressions are still largely undefined: there are no rules for type coercion or how to deal with overflow, and there is no defined binary representation; the result of constant expressions is therefore implementation-dependent.

3
We cannot recall ever having seen a (non-didactic) IDL specification that uses type char or wchar.

4
CORBA 2.6.x still has some unresolved issues with respect to type equivalence.

5
Again, the number of published specifications that actually use nested type definitions can be counted on the fingers of one hand; yet, every CORBA platform must bear the resulting complexity.

Table of Contents Previous Next
Logo