Wider Structural Considerations, versus Sentinels

Thomas W twhitmore.nz at gmail.com
Mon Dec 29 01:40:55 UTC 2014


Hi Peter, Brian, people,

I'm warming to 'Layering' as an approach -- it avoids many issues with
nulls and method-naming -- but don't yet feel specialization itself, can
justify the structural & language footprint needed for layering.

The simpler alternative I proposed uses syntactical constructs, at the
method level, with the goal of having a single "specializable" class
flatten appropriately to both reftype & valuetype implementations (eg,
Map<Object> and Map<int>).

Until we can make a strong determination, I would like to continue
entertaining both possible approaches. We can compare them thus:

A) Layering:
- "layers" selected by subtype,
- to provide extra methods/bridges,
- and API/ implementations suitable for value types (no nulls).

B) Method-level approach:
- renaming/bridging by annotation,
- syntactical constructs to replace direct usages of null;
- recommended to include Optional/ or non-sentinel based API also, but that
is up to class author.


Sentinels
------------

I appreciate the comments on 'Optional' returns and these are obviously
desirable to introduce to the API (not in Java 8, though). I believe
sentinels _can_ be part of a robust & correct low-level specialization
approach, for the following reasons:

1) Map.get() API has already been designed with a single-word return &
sentinel-based API.
2) A strong & robust general-purpose specializer should be able to
specialize single-word return APIs, no less than others, where such API is
desired.
3) API choice is up to the class author.
4) Specialization is about performance;  we ought not to force the
introduction of wrappers where the explicit purpose is low-level
optimization.

Sentinel-based APIs may be unsuitable in some circumstances -- I've never
proposed them as the only API (!!), just an effective & fairly-equivalent
way to transform existing API (Map.get()) to a value-type form.

For sentinel-based API to be unsuitable, the first two of the following
four conditions have to be met. (That's an AND conjunction).
1) Presence of keys in the map are optional (ie, not fully prepopulated)
2) Full range of 'int' is required for values
3) A 'getOptional()', 'getOrDefault()' or (non-concurrent)
containsKey()/get() API not be available
4) A wider (eg. long) value-type cannot be substituted.

Just as we see with reftype Map.get(), there are many many usages where a
'sentinel' is not at all a problem. So provided we add a Map.getOptional()
API, there are no real problems with still retaining a sentinel-based
Map.get(). Essentially, 'null' is a sentinel for reftypes and we have not
yet ruled out a simple low-level specializer based on syntactic constructs.


Structural Considerations
----------------------------------

Java is a simple language. There are many cases for which we might want, or
it would be very convenient to have, a layer of structure between 'class'
and 'member'. Some examples:

1) distinct lifecycles;  initialization, vs building, vs operational use.
2) separate features:  configuration, vs metrics/statistics, vs subordinate
components, vs own data, vs active APIs
3) separate interactions:  external API, vs component SPI, vs own internal
machinery.

All of the above (generally, "lifecycles" or "facets") are more than
deserving of structure. Do they get it in Java? No. There is no structure
in Java other than class, and member.

Another two cases, less deserving:
4) Properties -- famously weakly-structured in Java
5) mixins or multiple inheritance

For a long time I have been amazed by properties & Javadoc. Why would
anyone sort or document a behaviour-free getter/setter combination
separately??? But that is how the Java language is specified.

We've learned to live without structure, and Java functions well enough as
a class- and member-based language. If we're going to add structure, it
should address more than such a tiny corner case!


Wider Consideration of "Structure"
---------------------------------------------

Essentially my point is, that if we're going to look at adding structure,
it maybe that we should add it more widely -- not just for specialization.

Many other aspects of classes could benefit from better structure, and the
overhead to add a large feature to Java language for just a small number of
method & null fixups doesn't justify it.

Could this be a possible example?

class OrderBuilder {
    lifecycle Configuration {
        @Autowired
        public void setOrderService (OrderService orderService);
        @Autowired
        public void setWarehouseService (WarehouseService warehouseService);
    }
    lifecycle Building > Configuration implements IOrderReceiver {
        public void addItem (OrderItem item);
    }
    lifecycle Operation > Building {
        public Order result();
    }
}


I'd like to explore the area of "structure", to see what useful things we
can do with it. If we _can_ justify the cost by achieving other benefits, I
am all for going Layering.

Of course, failing that I'm still a Grinch :)

What are people's thoughts on feature/ lifecycle/ interaction structuring?
How can they be used? Even organizing Javadocs & source to not be such a
jumble-sale of methods, could be a major improvement. What else can we do
with a moderately-simple structural mechanism?

Comments?


Regards,
Thomas


More information about the valhalla-dev mailing list