+1 to Yifan’s recommendation. In Java, we may need to mark a method public for different reasons. Hence better to have annotations to mark public APIs. +1 to David’s point that we may need tooling to parse annotations and error/warn accordingly.
> On Aug 18, 2026, at 4:50 AM, Yifan Cai <[email protected]> wrote: > > +1 to Josh's annotation-based approach over "public by default". > > Java's public keyword is not an API commitment. Plenty of public methods > exist only because they're called from another package in the same project, > not because they are public APIs intended for external consumers to depend on > them. Treating Java's public keyword as API contract conflates two different > concerns. > > Scope annotations (@Public/@Internal/whatever we settle on) aren't just > documentation for consumers, but also a relief to code maintainers. W/o the > annotations, every public method becomes something we can't safely rename, > update or remove, even when it was never meant to be depended on by external > consumers. > > Explicit annotations let authors keep refactoring freely on everything not > deliberately promoted as public API, while still giving consumers a clear > surface to build against. > > Starting narrow and widening over time takes (significantly) less effort than > defaulting everything to public API and spending years walking it back. > > - Yifan > > On Mon, Aug 17, 2026 at 1:34 PM David Capwell <[email protected] > <mailto:[email protected]>> wrote: >> > They're all internal, this is a convenience to improve code sharing. >> >> Once they go into utils they are not “internal” (whatever that means). Why >> I started this effort in the first place is that the test utilities have >> been requested to be used in projects like Cassandra-ecosystem, but also >> non-cassandra projects. Both users need to know that a hot fix doesn’t >> break their build hence why I propose basic properties you would expect: >> major versions might have breaking changes, minor / patch won’t. For the >> classes anyone has talked about moving here, non of them should have issues >> with this; we are free to add new methods over time, but removing causes >> issues for consumers. >> >> > to improve code sharing. >> >> Even if you think about this only for cassandra ecosystem, if I depend on >> version 0.1.0 and we find a bug so get that fixed and now we depend on >> 0.1.10… I shouldn’t expect to deal with breaking changes. The mentality of >> “They’re all internal” as a justification to not document these assumptions >> causes me concern as breaking changes explicitly make it harder for parties >> to depend on these classes; breaking changes make is so much harder to >> “share code”. >> >> > We only care about versioning to ensure we don't break any builds >> >> What do you mean by this? Major versions I am ok with breaking changes; >> minor / patch is what I want to avoid. We can add new APIs without issue, >> the concern is only on removal. >> >> > and even decide when we upgrade the jar so can spot and fix any breakages. >> >> If we are upgrading to enable a new JDK change, I wouldn’t expect users to >> have to rewrite all their tests, redo all their collections, etc…. You >> shouldn’t have to worry about upgrading the version cross minor / patch >> versions, as that should impose a no breaking change rule. >> >> >> > On Aug 14, 2026, at 3:06 PM, Benedict Elliott Smith <[email protected] >> > <mailto:[email protected]>> wrote: >> > >> > Why are we defining this at all? They're all internal, this is a >> > convenience to improve code sharing. We only care about versioning to >> > ensure we don't break any builds, and we have all the builds, and even >> > decide when we upgrade the jar so can spot and fix any breakages. >> > >> > Let's not overcomplicate things, or bind our future selves in red tape and >> > regret. >> > >> > On 2026/08/14 17:57:40 Josh McKenzie wrote: >> >> While I read your email I found myself wondering "To what are we >> >> referring to when we say 'API'"? ;) >> >> >> >> Are you talking about a public interface? Or are you talking about "any >> >> class that's public and any public method within a public class"? >> >> >> >> If the latter, my primary theoretical concern is that if we pull in code >> >> that has components that are scoped public for cross-package >> >> accessibility within-project, promoting those to "public by default" >> >> immediately calcifies their interface whether we intend for that to be >> >> consumed or not. Basically, we don't have an interim scope layer between >> >> "package private" and "public" that corresponds to "project public". In >> >> theory the post JDK9 modularity kind of provides that but then everyone >> >> just add-opens bulldozes across things (the joys of legacy code...). >> >> >> >> I think "Any interface that's public is a public API" is pretty obvious >> >> to maintainers and users and good. I'm also good with "anything public is >> >> an API unless otherwise documented" and we add a simple annotation like >> >> @INTERNAL >> >> <https://github.com/apiguardian-team/apiguardian/blob/main/src/main/java/org/apiguardian/api/API.java#L87> >> >> from API Guardian to basically say "yeah, this is public, but it's not >> >> intended for public consumption" (I think we should roll our own to match >> >> our proposed lifecycles but that's a clear example of the idea). >> >> >> >> I'm worried about the approach of "Any public method in a public class is >> >> considered public API and you can't change it". I'd prefer we start with >> >> a more constrained surface area we commit to as being an API and widen it >> >> later if we find there's a need; it's much harder to go in the other >> >> direction. >> >> >> >> On Fri, Aug 14, 2026, at 1:24 PM, David Capwell wrote: >> >>> Josh and I talked about this offline and not perfectly in-sync so would >> >>> be good to get other peoples views >> >>> >> >>> My take is that if you are adding the API to this shared repo we need to >> >>> care about backwards compatibility so things should be PUBLIC by default >> >>> (anything that is java public is part of the public interface and >> >>> breaking changes are not allowed without a long enough deprecation >> >>> window similar to Cassandra’s.). I think Josh is in favor of using a >> >>> annotation to mark that a API is public, but without custom tooling I >> >>> don’t think anyone will notice and then we will get to a effectively >> >>> public state and breaking changes will be a nightmare to deal with for >> >>> the community. So if you want to post the API here, it should be stable >> >>> and we shouldn’t be putting APIs that have not been fleshed out first. >> >>> >> >>>> On Aug 7, 2026, at 8:16 AM, Josh McKenzie <[email protected] >> >>>> <mailto:[email protected]>> wrote: >> >>>> >> >>>> One thing worth immediately calling out that we might want to split >> >>>> out: we *could* do this work in Ant. >> >>>> >> >>>> It would be somewhat more imperative and brittle: we'd explicitly >> >>>> orchestrate the build ordering in Ant, while relying on the Gradle >> >>>> build inside Accord for its cassandra-utils dependency resolution / >> >>>> source substitution. That leaves us with a somewhat more complicated >> >>>> mixed Ant/Gradle build relationship but it's entirely workable for an >> >>>> interim time. >> >>>> >> >>>> So if the Gradle migration is a sticking point, we can break that out >> >>>> into a separate discussion and CEP rather than making it part of CEP-65. >> >>>> >> >>>> Doing so would mean retaining and extending some of the complexity in >> >>>> our existing build system that a future migration could remove, but >> >>>> it's not a crushing amount of additional complexity. The benefit of >> >>>> doing that work here with this CEP is that we have one more concrete >> >>>> build need providing a reason to move toward a unified build stack, and >> >>>> it fits the "clean things up and refactor as you're working on things >> >>>> that could benefit from that work" approach many have argued for in the >> >>>> past on the project. >> >>>> >> >>>> On Fri, Aug 7, 2026, at 10:58 AM, Josh McKenzie wrote: >> >>>>> As per the previous ML thread: [DISCUSS] Forking Cassandra utilities >> >>>>> into a separately released library >> >>>>> <https://lists.apache.org/thread/7kllp45vvonsg7ggzxpz39c5kdcy7r6g>, >> >>>>> David and I put together a draft of what we discussed and worked >> >>>>> through some implications and requirements that came up as we tried to >> >>>>> nail things down. >> >>>>> >> >>>>> The goal here is to provide a material backstop to continue our >> >>>>> discussion and version it. As with all CEP DISCUSS threads, this is >> >>>>> very fluid and none of it should be taken as settled or an implicit >> >>>>> mandate. Let's see if we can make some progress on this long-standing >> >>>>> pain point in our ecosystem. >> >>>>> >> >>>>> CEP-65 DRAFT: link >> >>>>> <https://cwiki.apache.org/confluence/spaces/CASSANDRA/pages/446071230/CEP-65+cassandra-utils+-+A+shared+utility+library+for+the+cassandra+ecosystem+DRAFT> >> >>>>> >> >>>>> *Why You Should Read This Draft:* >> >>>>> 1. Build system impact: we need a parent project and one of its >> >>>>> submodule to depend on another submodule. We're proposing freezing >> >>>>> ant's API surface area, maintaining that into perpetuity, and moving >> >>>>> to gradle going forward. >> >>>>> 2. Branching model: read the draft to see what "One Branch to Rule >> >>>>> Them All" means. >> >>>>> 3. API Lifecycle: Is @BETA/@STABLE/@DEPRECATED enough? Do we need a >> >>>>> @PRIVATE? >> >>>>> 4. To Release or Not To Release: we're proposing consumers embed this >> >>>>> as a submodule initially to minimize friction in moving shared code >> >>>>> into a shared space. >> >>>>> We have 1 outstanding unanswered question we didn't come up with an >> >>>>> opinionated proposal for: >> >>>>> >> >>>>> What should unannotated methods and classes in the library be >> >>>>> considered by potential consumers? @PRIVATE? @PUBLIC? Should we lint >> >>>>> and fail on any class without a top-level annotation forcing us to >> >>>>> make a choice on our dev list [DISCUSS] threads whenever we bring in >> >>>>> new things? >> >>>>> >> >>>>> There's no timeline on this thread; let's keep turning the crank on >> >>>>> this until we've hit our pareto-polish frontier. ;) >> >>>>> >> >>>>> ~Josh >> >>>>> >> >>>>> >> >>>> >> >> >>
