All that said, how have others dealt with this issue? Did you just not work directly with Java libraries? Did you use the OO side as a Better Java?
All that said, how have others dealt with this issue? Did you just not work directly with Java libraries? Did you use the OO side as a Better Java?
I prefer an intermediate solution when I can get away with it: Localize the mutable Java objects as much as possible, and just make sure that I don't leave a team/teammate that has little Scala experience all alone for a while. This often leads to styles that might be frowned upon by both camps of programming, but in my experience, dropping to imperative code when FP solutions are harder to optimize, while making sure that mutability is well contained and doesn't cross interfaces is Scala's happy place. Depending on the work to be done, each codebase can be pretty FP heavy, or be mostly imperative with an FP facade.
The real trick with Scala is really library design though: It's very easy to make a new library that has dozens of new concepts and is hard to learn and use, all while exposing things like Shapeless HLists to the outside world, while libraries that are easier to consume and don't crush compilation times through type magic are often tougher on the author, leading to more code generation and macros. Most library authors know so much Scala that they don't realize that just using their library well incurs in quite the mental cost to new developers.
I've done all of these approaches in various projects - using Scala just as a better Java, with Java-style code, using Java libraries, then writing code that was in a more immutable style that used wrappers around Java libraries, then writing very pure (i.e. no unmanaged effects) code that either used scala libraries, or used Java libraries only in an interpreter for a monad. All of them work. Mixing mutable objects and pure functional style is never going to go well, and that's as true in Python-only projects (say) as it is in Scala/Java hybrid projects; the language interop doesn't leave you any worse off than you were without it, if that makes sense.
It's useful because the JVM ecosystem is much larger than the Scala ecosystem. There's almost always a library for your purpose. If it isn't as idiomatic Scala as you'd want you can often easy create a small wrapper.
> Suddenly I have to worry about the Jr Dev doing silly things like introducing mutable Java objects into functional code.
code reviews and education
Catching bad practices and anti-patterns in code review sounds fine on paper, but I'm sure we've all been in the situation where there simply isn't enough time in the day to do intensive code reviews while still maintaining the pace needed for delivery.
Implicit conversions (i.e. where a type is silently converted to another type) is dangerous and can lead to very surprising problems.