Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
201 lines (139 sloc) 8.25 KB

UniJ: Questions & Answers

← back to UniJ README

Table of Contents:

Generic Q&A

Two APIs

Q: Why are there two APIs (User API and Service API) in UniJ?

A: So that:

  1. for the user, we can exactly mirror the JDK API (equivalent class names, static methods), e.g.:

    • List.of()UniLists.of()
    • Collectors.toUnmodifiableList()UniCollectors.toUnmodifiableList()
  2. for the service provider, we can expose an interface with all the related method to be implemented together, e.g.:

    • UnmodifiableListFactory.of()
    • UnmodifiableListFactory.collector()

Multiple Bindings at Runtime

Q: What happens if multiple bindings of the same type are available at runtime (e.g. pl.tlinkowski.unij.service.misc.jdk8 and pl.tlinkowski.unij.service.misc.jdk11)?

A: If multiple bindings of the same type are present on the runtime classpath/modulepath, service implementations with the top priority (lowest number) will be selected.

In the example above, Jdk11MiscellaneousApiProvider (priority = 10) will be selected over Jdk8MiscellaneousApiProvider (priority = 40) for MiscellaneousApiProvider.

End User Q&A

ArrayList + Collections.unmodifiableList for End User

Q: Why not simply use ArrayLists wrapped with Collections.unmodifiableList, etc. instead of UniJ?

A: You can do it if you find it convenient. To me, it's too verbose (low readability), and hence more error-prone. Besides, it's not null-safe, not as efficient (UniJ's JDK 8 binding uses Arrays.asList instead of ArrayList), and doesn't allow for easy migration once you upgrade to JDK 11+.

Guava / Eclipse Collections for End User

Q: Why not depend on an external library providing immutable Lists instead of on UniJ (e.g. Guava or Eclipse Collections)?

A: If you program to Guava's / Eclipse Colletions' proprietary APIs, you get rather far from the JDK 9+ API and its specification. Once you decide to upgrade to JDK 11+, migrating to JDK's collections will not be straightforward due to API differences.

UniJ Dependency on JDK 11+

Q: What to do about a dependency on UniJ once I migrate to JDK 11+?

A: In such case, it's best to remove UniJ altogether (will be a simple matter of replacing all occurrences of UniLists with List, etc.). Alternatively (if you don't have time for that), you can just change your UniJ bundle to pl.tlinkowski.unij.bundle.jdk11.

Library Provider Q&A

ArrayList + Collections.unmodifiableList for a Library

Q: Why not simply use ArrayLists wrapped with Collections.unmodifiableList, etc. instead of UniJ?

A: See this end-user Q&A. Moreover, if your users themselves use JDK 9's, Guava's or Eclipse's Collections:

  • you'd waste potential by not using the best Collection implementations available
  • you'd introduce inconsistency regarding which Collection implementations are used in your users' app/library

Guava / Eclipse Collections for a Library

Q: Why not depend on an external library providing immutable Lists instead of on UniJ (e.g. Guava or Eclipse Collections)?

A: See this end-user Q&A. Moreover, by bundling with an external library, you'd impose a heavy (potentially unwanted) dependency on your users. On the other hand, bundling with extremely lightweight UniJ API shouldn't cause any problems.

Why Facade for a Library

Q: Why bother with a Collection factory method facade (like UniJ) for a library?

A: As a library maintainer, the choice of Collection implementations shouldn't be yours. It's the same as with logging — you shouldn't choose the logging backend, and should only program to a facade like SLF4J. That's precisely what UniJ lets you do with respect to Collection factory methods.

How to Use UniJ in a Library

Q: How can I use UniJ in my library?

A: You can choose one of the below artifacts as a dependency for your library:

  1. (recommended) UniJ User API (pl.tlinkowski.unij.api)

    • pros: extremely lightweight (API only); no redundant dependencies

    • cons: your users must add a dependency on a UniJ bundle / bindings of their choosing

  2. (alternative) UniJ JDK 8 bundle (pl.tlinkowski.unij.bundle.jdk8)

    • pros: your users don't have to add a dependency on any UniJ bundle / bindings (they may do so to override the JDK 8 bindings, though)

    • cons: heavier than API only; may result in redundant dependencies if the user overrides some bindings

Here's what needs to be done by you and your users to use each option:

  1. UniJ User API:

  2. UniJ JDK 8 bundle:

In both cases, your users may need to add certain external dependencies.

Custom Service Provider Q&A

How to Provide a Custom UniJ Binding

Q: How can I create a custom UniJ service implementation and provide it as a binding?

A: You can create a custom UniJ binding by:

Example:

@UniJService(priority = 1)
@AutoService(UnmodifiableListFactory.class)
public class CustomUnmodifiableListFactory implements UnmodifiableListFactory {
  // ...
}

You should also create the following Spock specification to ensure that your service implementation adheres to the UniJ specification:

class CustomUnmodifiableListFactorySpec extends UnmodifiableListFactorySpec {

  def setupSpec() {
    factory = new CustomUnmodifiableListFactory()
  }
}

← back to UniJ README

You can’t perform that action at this time.