[ 
https://issues.apache.org/jira/browse/RNG-136?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17347861#comment-17347861
 ] 

Alex Herbert edited comment on RNG-136 at 5/19/21, 8:37 PM:
------------------------------------------------------------

h2. Updating existing classes changes functional compatibility

Although there is no binary compatibility change for existing classes there is 
functional compatibility change with updating to the new interface.

For example:
{code:java}
public class CollectionSampler<T> implements 
SharedStateSampler<CollectionSampler<T>> {
{code}
Becomes:
{code:java}
public class CollectionSampler<T> implements SharedStateObjectSampler<T> {
{code}
The implementation signature of {{SharedStateSampler}} remains unchanged:
{code:java}
public CollectionSampler<T> withUniformRandomProvider(UniformRandomProvider 
rng) {
{code}
Due to type erasure the change from {{SharedStateSampler}} to 
{{SharedStateObjectSampler}} is not detected as binary incompatible as the 
class still implements {{SharedStateSampler}}. But the {{SharedStateSampler}} 
is now of type {{SharedStateSampler<SharedStateSampler<T>>}} instead of 
{{SharedStateSampler<CollectionSampler<T>>}}.

If the derived sampler is assigned to the correct type this is functionally 
compatible:
{code:java}
CollectionSampler<String> sampler1 = new CollectionSampler<String>(rng1, list);
CollectionSampler<String> sampler2 = sampler1.withUniformRandomProvider(rng2);
{code}
If the derived sampler is assigned to a {{SharedStateSampler}} this is 
functionally *incompatible*; this will *not* compile with version 1.4 where it 
will with code from version 1.3:
{code:java}
CollectionSampler<String> sampler1 = new CollectionSampler<String>(rng1, list);
SharedStateSampler<CollectionSampler<String>> sampler2 = 
sampler1.withUniformRandomProvider(rng2);
{code}
The functionally incompatible change is to the following existing classes:
{code:java}
public CollectionSampler<T> implements SharedStateSampler<CollectionSampler<T>> 
public CombinationSampler implements SharedStateSampler<CombinationSampler>
public DiscreteProbabilityCollectionSampler<T>
    implements SharedStateSampler<DiscreteProbabilityCollectionSampler<T>>
public PermutationSampler implements SharedStateSampler<PermutationSampler>
public UnitSphereSampler implements SharedStateSampler<UnitSphereSampler>
{code}
In each of the classes the method implementation {{withUniformRandomProvider}} 
returns an instance of the class. Thus changing the interface implemented by 
the class has not changed the signature of the method implementation.

If a user has coded their use of the interface to assign the result to an 
instance of the class (as per the unit tests) then code will be functionally 
compatible. If they have assigned an instance of {{SharedStateSampler<R>}} then 
code will not be functionally compatible.

Note that the SharedStateSampler<R> interface only has 1 method:
{code:java}
public interface SharedStateSampler<R> {
    R withUniformRandomProvider(UniformRandomProvider rng);
}
{code}
So it is unlikely any user will assign the result of the method to an instance 
of {{SharedStateSampler}} as functionally it can only be used to create more 
instances. No sampling can actually be done from a {{SharedStateSampler}}. Code 
that has done this will later have to cast the {{SharedStateSampler}} to some 
other class to use it for sampling. This usage is incorrect and supporting it 
is not a priority.

I propose to allow this change without updating the major version number of the 
code. The functional compatibility change can be added to the release notes.


was (Author: alexherbert):
h2. Updating existing classes changes functional compatibility

Although there is no binary compatibility change for existing classes there is 
functional compatibility change with updating to the new interface.

For example:
{code:java}
public class CollectionSampler<T> implements 
SharedStateSampler<CollectionSampler<T>> {
{code}
Becomes:
{code:java}
public class CollectionSampler<T> implements SharedStateObjectSampler<T> {
{code}
The implementation signature of {{SharedStateSampler}} remains unchanged:
{code:java}
public CollectionSampler<T> withUniformRandomProvider(UniformRandomProvider 
rng) {
{code}
Due to type erasure the change from {{SharedStateSampler}} to 
{{SharedStateObjectSampler}} is not detected as binary incompatible as the 
class still implements {{SharedStateSampler}}. But the {{SharedStateSampler}} 
is now of type {{SharedStateSampler<SharedStateSampler<T>>}} instead of 
{{SharedStateSampler<CollectionSampler<T>>}}.

If the derived sampler is assigned to the correct type this is functionally 
compatible:
{code:java}
CollectionSampler<String> sampler1 = new CollectionSampler<String>(rng1, list);
CollectionSampler<String> sampler2 = sampler1.withUniformRandomProvider(rng2);
{code}
If the derived sampler is assigned to a {{SharedStateSampler}} this is 
functionally *incompatible*; this will *not* compile with version 1.4 where it 
will with code from version 1.3:
{code:java}
CollectionSampler<String> sampler1 = new CollectionSampler<String>(rng1, list);
SharedStateSampler<CollectionSampler<String>> sampler2 = 
sampler1.withUniformRandomProvider(rng2);
{code}
The functionally incompatible change is to the following existing classes:
{code:java}
public CollectionSampler<T> implements SharedStateSampler<CollectionSampler<T>> 
public CombinationSampler implements SharedStateSampler<CombinationSampler>
public DiscreteProbabilityCollectionSampler<T>
    implements SharedStateSampler<DiscreteProbabilityCollectionSampler<T>>
public PermutationSampler implements SharedStateSampler<PermutationSampler>
public UnitVectorSampler implements SharedStateSampler<UnitVectorSampler>
{code}
In each of the classes the method implementation {{withUniformRandomProvider}} 
returns an instance of the class. Thus changing the interface implemented by 
the class has not changed the signature of the method implementation.

If a user has coded their use of the interface to assign the result to an 
instance of the class (as per the unit tests) then code will be functionally 
compatible. If they have assigned an instance of {{SharedStateSampler<R>}} then 
code will not be functionally compatible.

Note that the SharedStateSampler<R> interface only has 1 method:
{code:java}
public interface SharedStateSampler<R> {
    R withUniformRandomProvider(UniformRandomProvider rng);
}
{code}
So it is unlikely any user will assign the result of the method to an instance 
of {{SharedStateSampler}} as functionally it can only be used to create more 
instances. No sampling can actually be done from a {{SharedStateSampler}}. Code 
that has done this will later have to cast the {{SharedStateSampler}} to some 
other class to use it for sampling. This usage is incorrect and supporting it 
is not a priority.

I propose to allow this change without updating the major version number of the 
code. The functional compatibility change can be added to the release notes.

> ObjectSampler<T> and SharedStateObjectSampler<T> interfaces
> -----------------------------------------------------------
>
>                 Key: RNG-136
>                 URL: https://issues.apache.org/jira/browse/RNG-136
>             Project: Commons RNG
>          Issue Type: New Feature
>          Components: sampling
>    Affects Versions: 1.4
>            Reporter: Alex Herbert
>            Assignee: Alex Herbert
>            Priority: Major
>          Time Spent: 40m
>  Remaining Estimate: 0h
>
> The sampling package currently contains interfaces for creating int and 
> double samples and their extensions to implement the SharedStateSampler 
> interface:
> {code:java}
> public interface DiscreteSampler {
>     int sample();
> }
> public interface SharedStateDiscreteSampler
>     extends DiscreteSampler, SharedStateSampler<SharedStateDiscreteSampler> {
>     // Composite interface
> }
> public interface ContinuousSampler {
>     double sample();
> }
> public interface SharedStateContinuousSampler
>     extends ContinuousSampler, 
> SharedStateSampler<SharedStateContinuousSampler> {
>     // Composite interface
> }
> {code}
> Add a matching ObjectSampler interface for all samplers that create objects:
> {code:java}
> public interface ObjectSampler<T> {
>     T sample();
> }
> public interface SharedStateObjectSampler<T> extends
>         ObjectSampler<T>,
>         SharedStateSampler<SharedStateObjectSampler<T>> {
>     // Composite interface
> }
> {code}
> Samplers currently returning an object should implement the new interface:
> {code:java}
> int[] CombinationSampler.sample()
> int[] PermutationSampler.sample()
> double[] UnitVectorSampler.nextVector()
> T CollectionSampler<T>.sample()
> T DiscreteProbabilityCollectionSampler<T>.sample()
> double[] BoxSampler.sample()
> double[] LineSampler.sample()
> double[] TriangleSampler.sample()
> double[] TetrahedronSampler.sample()
> double[] UnitBallSampler.sample()
> {code}
> Only the UnitVectorSampler will require a new {{sample}} method. The current 
> {{nextVector}} method can be marked deprecated.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to