[hibernate-dev] [OGM and others] API, SPI and FPI

Steve Ebersole steve at hibernate.org
Thu May 22 10:32:10 EDT 2014


Deja vu as we have had this exact discussion before (and actually, our
discussions pre-date those TAG discussions....)

You are basing your specific reading of what SPI means based on a single
wikipedia page that goes out of its way to point out its incompleteness :)
 And really even then in my opinion you are reading too much into its
mention of the JDK ServiceLoader.  What the wikiepdia says specifically is:

*Service Provider Interface* (SPI) is an
API<http://en.wikipedia.org/wiki/Application_programming_interface>
intended
> to be implemented or extended by a third party. It can be used to enable
> framework extension and replaceable components


That's actually not much different (if at all) from how I use the term SPI.
 To me, SPI is simply "the API that is used between internal components to
accomplish something".  A specific important distinction here is that APIs
are meant for application code to bind to, SPIs are not.  As I have pointed
out probably 100 times already, yes there are 2 facets to this.  To me an
SPI is made up of:
1) The SPI contracts that are meant to be extended by users and/or 3rd
parties.
2) The SPI contracts that are not intended for extension.

Another correlated break down is:
1) SPI contracts that do things
2) SPI contracts that are inputs/outputs to (1)

Take for example, the idea of scanning deployments for annotated classes
(mainly because this one is fresh in my mind).  The main SPI contract here
is Scanner and ArchiveDescriptorFactory.  These are each intended as
extension points, they both "do stuff".  All the rest of the "scanning spi"
is inouts/outputs to these 2.  Why is this an important distinction?  Well,
generally speaking where we get into trouble in terms of "changing SPIs"
later is when we change this first group.  When we have to make
changes to Scanner
or make changes to ArchiveDescriptorFactory we cause problems downstream
for folks that implement/extend this stuff.  That's where patterns like
parameter objects and delegates are sooooooooo beneficial.  As an
illustration, say we need to pass some new information into the single
Scanner method (this was the recent case I worked through).  If that means
adding a new parameter to that Scanner method, well that just screwed every
implementor of the Scanner interface because now their implementation is no
longer valid.  If instead, Scanner had made use of parameter objects (it
now does btw), the parameter object itself would have been changed causing
no problem of existing Scanner implementations.  The "parameter object" is
still part of the SPI.  But it falls into this second category.  Changing
these guys is essentially irrelevant in terms of causing no issues for
existing SPI implementations.


And as far as "a tendency to consider the application developer more sacred
than the framework/integrator when it comes to breaking backward
compatibility" I would not phrase it like that.  There are  a few parts to
this in my mind:

First,  I think you need to step back and look at the bigger picture.  The
API defines the features that Hibernate is exposing to the application
(save this thing, find that thing).  Its kind of broad and generally avoids
defining a feature in relation to an interaction between 2 things.  SPIs in
many ways are inherently more complicated to design because they need to
consider both sides of the problem.  Going back to scanning, that SPI needs
to consider Hibernate's requirements from scanning as well as any
requirements the implementation needs especially accounting for any quirks
in the various potential implementations.

Second, because of the "overlap" or "integration" aspects between teams and
projects there needs to be coordination and cooperation when
building/designing an SPI.  To be honest, this part has been lacking even
within "our team" across projects because people get focused on their work.
 What happens instead, again from my perspective, is no
coordination/cooperation
occurs in the building/designing of these; and then later people get upset
when the SPI needs to change because it was not well designed to begin
with.  Another aspects of this is "more eyes"; the more people involved in
the design of an API (SPI fits in here equally) looking at it, the better
designed it will be.


All that said, I don't plan on changing use of the phrase SPI based on (a
questionable interpretation of) one wikipedia page.


On Thu, May 22, 2014 at 4:21 AM, Emmanuel Bernard <emmanuel at hibernate.org>wrote:

> (This discussion is around OGM but it is a very generic subject applicable
> to all projects.)
>
> I made a mistake in naming the spi packages SPI because the definition of
> SPI is quite narrow and even more narrower in Java than elsewhere.
>
> ## Definitions
>
> ### SPI
>
> In Java and according to Wikipedia, a SPI (Service provider interface) is
> related to the notion of ServiceLoader
> http://en.wikipedia.org/wiki/Service_Provider_Interface
> We certainly do not (or very rarely) have these kinds of services in our
> SPI packages.
>
> Another point of you comes from this StackOverflow article
> https://stackoverflow.com/questions/2954372/difference-between-spi-and-api
>
> - the API is the description of classes/interfaces/methods/... that you
> call and use to achieve a goal and
> - the SPI is the description of classes/interfaces/methods/... that you
> extend and implement to achieve a goal
>
> A third point of you is the NetBeans one
> http://wiki.netbeans.org/DevFaqApiSpi
>
> SPI stands for Service Provider Interface. It is a subset of all things
> that can be API specific to situations where a library is providing classes
> which are called by the application (or API library), and which typically
> change the things the application is able to do.
>
> I think everyone agrees that an SPI is kind of API.
>
> ### IPI or FPI (Integrator / Framework Public Interface)
>
> I will use FPI as it tastes better than IPI but I have no preferences over
> integrators vs frameworks.
>
> Now in my mind and for some obscure reasons, SPI really meant FPI. To my
> credit, I have done that fairly constantly on Hibernate Search and Bean
> Validation. Hibernate OGM was never properly packaged initially so that’s
> another story.
>
> A FPI is used by a framework integrating or extending the project exposing
> these FPIs.
>
> ## What does really matter?
>
> It is useful to differentiate an API used from an API extended (SPI)
> because the constraints are different:
>
> - APIs used can add new methods and should be interfaces rather than
> classes.
> - APIs extended (SPIs) should be abstract classes so that a new contract
> added can be offered by the project without breaking implementors.
>
> But from a user point of you, I’m tempted to say "so what?”. It does not
> change your inclination to make use of that contract.
>
> It is useful to differentiate application developer(*) facing APIs from
> framework/integrator facing APIs (FPIs) to keep the API simple to use and
> to document. There is also a tendency to consider the application developer
> more sacred than the framework/integrator when it comes to breaking
> backward compatibility.
>
> (*) I say application developer here but it really the primary user group
> of your project whereas the integrators are usually less numerous and more
> controllable.
>
> To me the latter (API/FPI) is more generally useful and that is the one I
> wish to separate in different packages naming conventions.
> The former it seems to me is very often self-obvious to the user and
> project maintainers. And from a usage PoV, it does not really matter. Plus
> there are cases where a contract is both used and extended (JDBC’s
> Connection contract for example).
>
> Can and should we split according to both dimensions? I don’t think so.
> And if I have to chose, I’d prefer to split according to the API/ FPI
> dimension which is more generally useful to our customers and makes it
> clear what is non breakable (API), what is inconvenient to break (FPI),
> what is free lunch (implementation).
>
> ## References
>
> There has been some discussions in the past as well
> https://issues.jboss.org/browse/TAG-47
>
> Emmanuel
> _______________________________________________
> hibernate-dev mailing list
> hibernate-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/hibernate-dev
>


More information about the hibernate-dev mailing list