

More specifically, I’m thinking about two different modes of development for a library (private to the company) that’s already relied upon by other libraries and applications:
As a side note: I believe these approaches are similar in spirit to the continuum of microservices vs monoliths.
Speaking from recent experience, I feel like I’m repeatedly finding that users of my library have built towers upon obsolete APIs, because there have been multiple phases of experimentation that necessitated large changes. So with each change, large amounts of code need to be rewritten.
I still think that approach #1 was justified during the early stages of the project, since I wanted to identify all of the design problems as quickly as possible through iteration. But as the API is getting closer to stabilization, I think I need to switch to mode #2.
How do you know when is the right time to switch? Are there any good strategies for avoiding painful upgrades?
I like library providers that can provide mechanical upgrade instructions. For example:
model.adjust(x,1,y)
is nowmodel.single(Adjustment.Foo, x).with_attribute(y)
Or whatever. Then people can go through your instructions find-and-replacing the changes, or even better, have an automated tool do it.
Also you pay some of the maintenance burden by writing all this documentation, so you have a some stake in keeping the changes minimal.