While reviewing the new Application.getFlowHandler() API:
+ /**
+ * <p class="changed_added_2_2">Return the thread-safe singleton
+ * {_at_link FlowHandler} for this application. For implementations
declaring
+ * compliance with version 2.2 of the specification, this method
must never return
+ * {_at_code null}, even if the application has no flows. This is
necessary to enable
+ * dynamic flow creation during the application's lifetime.</p>
+ *
+ * <div class="changed_added_2_2">
+ *
+ * <p>All implementations that declare compliance with version 2.2
+ * of the specification must implement this method. For the purpose
+ * of backward compatibility with environments that extend {_at_code
+ * Application} but do not override this method, an implementation is
+ * provided that returns {_at_code null}. Due to the decoratable nature
+ * of {_at_code Application}, code calling this method should always check
+ * for a {_at_code null} return.</p>
+ * </div>
+
+ * @since 2.2
+ *
+ */
+
+ public FlowHandler getFlowHandler() {
I am reminded again of a topic that came up during 2.0 spec development
(and maybe again in 2.1): how to go about adding new methods to abstract
classes.
We've got a variety of options:
1. Make the new method abstract.
2. Implement a "real" solution in the abstract class.
3. Implement a transparent, but stubbed (no-op) solution in the
abstract class.
4. Implement a non-transparent solution (eg. return null and require
the caller to check for this return value).
5. Thrown an UnsupportedOperationException.
We tend to do either #4 or #5, which in my mind are the worst options.
I know that it is too late to do anything about this for 2.2, but wanted
to send this out in the hopes that we'll discuss this in more detail
when 2.3 starts up.
I guess while we're here, I might as well say that I think that this:
> + * For the purpose
> + * of backward compatibility with environments that extend {_at_code
> + * Application} but do not override this method, an
> implementation is
> + * provided that returns {_at_code null}.
Is not doing anyone any favors. Instead of making it clear to the
Application subclasser that their subclass is failing to implement a new
responsibility, it hides this fact with a non-functional default
implementation. As such, instead of finding out about this failure at
compile time (as would be the case with #1), you won't find out about
this until some later point when your application fails in some more
subtle way.
Andy