| I would say less overuse of final, more underuse of interfaces. If everything takes/returns/stores values by interfaces (excluding data containers with no behavior) then you don't need to "jailbreak" any class to mock it. Of course you get code bloat defining interfaces for everything you intend to implement once, and you have to enforce these rules, but this is something that could be made easier. Not in Java, but imagine a language where: - Concrete classes can only be used in new, or in some platform provided DI container. - Methods can only accept interface types and return interface types. - Fields are private only, all public/protected is via properties (or getters/setters, it just has to be declarable in an interface) - You have a ".interface" syntax (akin to ".class" but for types) that refers to the public members of a class without tying you to the concrete class itself. You can use this as a shorthand instead of declaring separate interfaces for everything. Eg. ``` final class GDrive { ... } public Download file(GDrive.interface drive) { ... } class MockDrive implements GDrive.interface { ... } ``` The closest I can think of is a hypothetical typed variant of NewSpeak, but maybe something like this exists already? |
Interfaces with one implementation are terrible. They just clutter everything and make the code navigation a pain, so it's good that people are avoiding them.
Perhaps a special "test-only" mode that allows to patch finals is a better idea.