[hibernate-dev] [OGM and others] API, SPI and FPI
Sanne Grinovero
sanne at hibernate.org
Thu May 22 12:03:34 EDT 2014
Looks like we're all aligned?
Steve made some concrete examples, Emmanuel pointed out how we have
been defining this vs. apparently other people.
I don't feel the need to change our interpretation, if that's what is
being discussed.
It's good to remember that there are different kinds of SPIs; we
indeed came to the conclusion that it's often much nicer to have an
abstract class when the SPI is meant to be provided by 3rd party code
but I think we need an interface in that case as well (in addition to
the abstract class).
Also breaking an SPI could bring as much pain as an API change.. when
an API changs the user is often in the position to be able to do
something about it. More often people get in trouble because they are
using a mixture of versions of different frameworks and libraries
which are meant to work together, and they don't.. in such scenarios
the user might not be able to do something about it, other than
lobbying and begging for fixes and releases in projects out of his
control.
An API change just invalidates project for people who are not able to
recompile, and makes books and training outdated :) Sure that's
annoying too, my point is just that SPI is not less important
*generally* but it depends on what API and what SPI we're talking
about.
But even when we discuss the same "kind" of SPIs, some are more
critical than others, and some are "internal" SPIs (like
hibernate-search to hibernate-search module), some are very close
(hibernate-orm to hibernate-search) some are slightly further down
(infinispan - hibernate-search).. others need critical stability
(container integration, etc..). And of course it's less painfull when
it affects something that 99% of users didn't know it existed in the
first place.
Conclusion, the package name will never set a rule: to me it's more
like a reminder to be carefull in any way possible as "someone" is
going to hate me. I am personally not even a fan of these specific
package naming conventions, an annotation would be just as good,
provided it gets somehow visibility in the javadoc (or even hides
javadocs for internals).
Sanne
On 22 May 2014 15:32, Steve Ebersole <steve at hibernate.org> wrote:
> 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
>>
> _______________________________________________
> 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