I had assumed that application code having a compile-time dependency on
proton-j-impl (or theoretically on proton-jni) was anathema to proton's
interchangeable proton-c/proton-j philosophy.  However, the consensus seems
to be that this is acceptable.  I'm ok with that.

In this case, I would be happy for us to put the proposed ProtonC and
ProtonJ classes in the proton-jni and proton-j-impl modules respectively.

I therefore expect we'll have something like this:

=== In proton-api ===
package o.a.q.proton;

public abstract class Proton
{
  /** dynamically chooses whether to return a ProtonJ or a ProtonC */
  public static Proton newInstance();

  public Connection connection()
  { ... }
}


=== In proton-j-impl ===
package o.a.q.proton.*impl*;

public class ProtonJ extends Proton
{
  public ProtonJ()
  { }

  @*Override*
  public *ProtonJ*Connection connection()
  { ... }
}

Most applications would call Proton.newInstance() and would therefore omit
proton-j-impl (or proton-jni) from their compile-time classpath.  Whichever
of ProtonJ and ProtonC is returned at run-time, these applications would
experience a fully functional Proton (I struggle for a proper definition of
"fully functional", but I think we can rely on common sense here).

The minority of applications that wish to use implementation-specific
classes would directly construct a new ProtonJ/ProtonC.

We would document the intended usage, and package-scope (and possibly also
streamline) the XXXFactory and ProtonFactoryLoader classes to reduce our
users' confusion.

I agree that there are outstanding issues around Java package design, such
as the overlapping namespace of proton-api and proton-j-impl.  Also, the
need to properly define the public API of proton-j-impl becomes more
pressing if we're going to expect people to compile against it.  I'm not
sure what the right answers to these questions are, but propose that we
resolve this Proton/ProtonJ/ProtonC stuff first.


Phil



On 8 August 2013 17:45, Hiram Chirino <hi...@hiramchirino.com> wrote:

> You guys also need to keep in mind that doing dynamic loading of
> implementations classes may need to be implemented differently based
> on the container that the app is running in.  A good example is OSGi.
> The way factories are currently implemented would probably not work
> there.  So it's best to avoid getting into the factory business to
> begin with.
>
>
> On Fri, Aug 2, 2013 at 10:55 AM, Rob Godfrey <rob.j.godf...@gmail.com>
> wrote:
> > Given the Proton class doesn't require the user to know which
> > implementation they are using (but allows them to explicitly ask for a
> > particular implementation type if they so desire) I'm a little confused
> how
> > adding the requirement for the user to instantiate an implementation
> > specific class actually helps the user.  Am I missing something?  There
> > really is no need for a user to know about factories, etc...
> >
> > -- Rob
> >
> >
> > On 2 August 2013 15:13, Rafael Schloming <r...@alum.mit.edu> wrote:
> >
> >> On Fri, Aug 2, 2013 at 4:44 AM, Phil Harvey <p...@philharveyonline.com
> >> >wrote:
> >>
> >> > I agree that o.a.q.p.Proton is, overall, an improvement.  I was partly
> >> > responsible for creating the ProtonFactoryLoader and XXXFactory
> classes,
> >> > and acknowledge that they make life too hard for the user.
> >> >
> >> > This was a result of trying to meet the following design goals:
> >> > 1. User code should not need to have a compile-time dependency on any
> >> > proton-c/j/jni classes.  Given our current separation of the
> proton-api
> >> > from the proton-impl/proton-jni modules, it means user code should
> only
> >> > depend on proton-api at compile-time.
> >> > 2. Classes from the various "top level packages", such as engine,
> >> messenger
> >> > etc, should be kept separate unless they really need to be together.
> >> >
> >> > I still believe in goal 1 (though this will be discussed at greater
> >> length
> >> > on the related thread [1]), but am relaxed about item 2.
> >> >
> >>
> >> Thanks for describing the goals, it's helpful to have them written
> down. I
> >> personally don't feel that the Proton class is violating (2) in an
> >> important way so long as engine and messenger remain otherwise
> unentwined.
> >>
> >> I generally agree with (1) also, however I think it could use some
> further
> >> refinement. At the root of (1) is the desire to make it clear and
> obvious
> >> to developers if/when they are depending on the characteristics of a
> given
> >> implementation rather than on a more abstracted interface. Probably the
> >> most common example of this sort of thing within Java would be typical
> >> collections usage of interface/impl splits, e.g.:
> >>
> >>     List foo = new ArrayList();
> >>     ArrayList bar = new ArrayList();
> >>     LinkedList baz = new LinkedList();
> >>
> >> The suggested pattern for the Proton class would be following this
> pattern
> >> exactly:
> >>
> >>     Proton p = new ProtonJ();
> >>     ProtonJ pj = new ProtonJ();
> >>     ProtonC pc = new ProtonC();
> >>
> >> Now this pattern of course doesn't really speak to classpaths at all.
> The
> >> classpath issue is really entirely orthogonal to the interface/impl
> >> distinction. Right now we have separate classpaths, but a muddled
> >> interface/impl distinction since the impl jar adds new interfaces into
> >> packages belonging to the API jar, and the API jar has stuff in it that
> is
> >> really part of a specific impl. Likewise, you can have a clear
> >> interface/impl distinctions within a single jar as is the case with java
> >> collections.
> >>
> >> I'd argue that the classpath thing is really a distinct goal/requirement
> >> and is really more about a discovery mechanism for independent or third
> >> party implementations. I don't personally feel that this is a necessary
> >> requirement for us at this point, but I'm fairly relaxed if other people
> >> would like to support it.
> >>
> >> Given the above refinement of (1) into (1a) interface/impl split and
> (1b)
> >> independently implementable API, I would find it a bit odd to put the
> >> ProtonJ/ProtonC classes into the API package since that would introduce
> a
> >> dependency from the API package back to those impls (even if its only a
> >> runtime dependency) and would effectively give those impls an elevated
> >> position which in some sense is fine, but also seems contrary to the
> >> independently implementable notion in the first place. It seems like
> what
> >> you'd want in the API package is purely a generic discovery mechanism
> that
> >> would work for any implementation.
> >>
> >> As I said above, I don't feel like such a discovery mechanism is really
> a
> >> requirement for us right now. I think actually having a complicated
> >> discovery/factory pattern is in some ways detrimental as it creates a
> >> barrier to entry for all users when most don't care about the
> flexibility
> >> it offers (at least right now) and if they do care about that
> flexibility
> >> it is easy enough for them to build their own. In fact modulo exception
> >> handling it is really just one extra line of code:
> >>
> >>     Class impl = Class.forName(System.getProperty("blah"));
> >>     Proton p = (Proton) impl.newInstance();
> >>
> >> So I'd personally say go for the simple interface/impl split pattern
> that
> >> everyone knows and is used to and don't worry about a generic discovery
> >> mechanism until we actually have enough implementations for it to be
> >> warranted.
> >>
> >> --Rafael
> >>
>
>
>
> --
> Hiram Chirino
>
> Engineering | Red Hat, Inc.
>
> hchir...@redhat.com | fusesource.com | redhat.com
>
> skype: hiramchirino | twitter: @hiramchirino
>
> blog: Hiram Chirino's Bit Mojo
>

Reply via email to