Make concrete classes final by default

It’s all in my Scala Sphere talk. Watch it there: https://m.youtube.com/watch?v=2wkEX6MCxJs.

A library that does not need to care about binary compatibility is niche.

2 Likes

This is a really good talk! It’s probably the perfect time for me to watch it since I’m starting to work on a contribution to Mockito Scala – which is quite a new project. Would you consider coming to Israel in the summer to talk in the Scalapeno conference (assuming there will be one next year)?

This may not be the core issue here, but I’d like to address the point you brought up in the talk about breaking source compatibility by adding methods because of implicit-classes. IMHO this is an acceptable way of breaking source compatibility, much like it would be in Java when adding methods in non-final classes.

If one decides to extend a non-final library class, one should be aware that it’s unsafe and cannot expect this “API” to remain intact. With implicit-classes it’s even worse, since in the case of extending non-final classes, adding a method would break the user code (because of missing override modifier), while with implicit-classes the code would likely still compile. Perhaps the Scala compiler should prevent “overriding” existing methods with implicit-classes?

Anyway, back to the topic at hand.

As you elegantly demonstrated in your talk, the deeper a library is down the dependency stack, the higher the risk of a non-binary-compatible change to screw things up, and the lower the importance of maintaining source compatibility.

Thing is, I believe this “formula” goes both ways: The closer a library is to the top of the stack, the more important it is to maintain source compatibility and the lesser it is to maintain a binary one. Why? well, since the “higher” a library is, the less likely it is for other libraries to depend on it, and the more likely it is for an “end-user” to use it directly; meaning, breaking binary compatibility becomes less of a risk, and breaking the source making it more likely that the end-users would have to concern themselves with it.

I’ll make the assumption that most library maintainers (in terms of sheer numbers) are maintaining libraries closer to the top of the stack – libraries which may very well be of niche use only, and may not be used by a large community of other developers. I would also make the assumption that these libraries require less skill to be maintained, and are expected to make major changes more often.

Given these assumptions, I’d say that most library maintainers should not be so concerned with binary compatibility. This is obviously a plus to have, but I don’t expect most maintainers to have the necessary skill and / or time to deal with these concerns. I would much rather them experimenting with their libraries up to the point where they find balance, and that only then they’d start thinking about long-term repercussions of their design decisions.

2 Likes

Martin is proposing sealed instead: PRE-SIP: Make classes `sealed` by default.