There's a lot of tools that exist to make what developers to easier to do. If it's something we do a lot, we tend to find ways to have something do it for us.
I've done it. I'll probably do it again. I built a little tool to automate the generation of Android Services based off JSON because I spent so much time copy/pasting existing services and editing them into the new serevice. Copy and Paste means you're missing an abstraction - I couldn't find it, so I built a tool to deal with it.
We find challenges and difficulties accomplishing what we want to do, so we find things we can do to reduce that pain, to simplify the process. It's one of the things I really enjoy about being a developer - I can simplify things I want to do.
The downside of the things that get built, is they get built for the way that developers write code and that's very often not inline with the technical practices. These tools promote writing code in the fashion they're built to simplify. I find that they make it very hard to write good object oriented code. It's simpler to write (not maintain) bad OO code, especially with these tools.
Frameworks provide an abstraction to some generic functionality. This can be fantastic. That abstraction though, isn't always the abstraction your code needs.
When you have to change the code to support using a particular abstraction - Your code will suffer.
You cease being in control of the code you are actively writing because of a tool choice.
I refuse to allow my tools to dictate what I can do with the code I'm writing. This is why I interface everything.
Frameworks make things easy. Easy is upfront cost. Not long term cost.
Control your code
I've been part of a project that used ReactiveX due to a strong recomendation from the consultants helping us. It made A LOT of the early development go quick.
I didn't like it - Partically because the promises the consultants made sounded too good. Too good to be true.
I think ReactiveX is an aamzing library - but I don't think it should be the solution for the breadth of problems I've seen it used for. It infested the entire application. From the UI button click and displaying data to making the network call and debouncing additional calls.
This isn't blaming the Framework itself, it's that they make it easy to implement quickly in a way that slaughters the maintainability of the product.
Seeing how the first product was going, I heavily advocated not using it on a second product. We ensured we had examples of how to do everything w/o the tool.
The other product is still working to strip out ReactiveX from the more intrusive sections.
The team has been unable to remove a framework from their code - for over a year!
The tool is dictating what they can do! This is horrible for a products maintainability - You can't do what you need to!
This is just one example.
Frameworks that provide the foundation of your application dicate what you can do with your application.
Control your encapsulation
A framework I loved to use before understanding the power from Object Oriented programming was Retrofit. It makes network interaction amazingly simply.
I tried to use it in a project I followed the MicroObject practices on - I couldn't.
Using Retrofit as per the examples FORCES us to break encapsulation.
@FormUrlEncoded @POST("user/edit") Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);
We have to pull the data out. Something has to pull teh data out and give it away. Smidge of a violation of never giving away your data.
I had to use a bunch of internal classes to hide the non-OO style. This isn't always terrible, but it's pretty bad.
The MicroObjects style also has a lot of classes; so what's the difference?
How you use it.
With my use of Retrofit I have a
HackerNewsAccess class that takes a Callback.
This is a much more complex style of code to maintain. If for nothing else than the required cognitive load to understand the flow of an event. The call back goes down a bunch of classes, then gets invoked, which bounces back up the entire stack - unless it was wrapped in another callback, which is invoked and could opt to not invoke the original callback...
The highest level of this callback sequence isn't guaranteed to know anything. Invocation of your callback isn't guaranteed. You may never be alerted to the excpetion because it prevents your callback from being invoked.
This uncertainity drives A LOT more code to handle situations to ensure we can get information back to the top.
Introducing uncertainity into the application creates a massive jump in the cognitive load required for the developer to work in the application. They can, by the nature of uncertainity, actually know what the application WILL do - just what it's most likely to do... if we've accounted for everything... everywhere it's required to be accounted for...
I don't want to work into a system like that. That's just going to grow. More places need more condition handling... Overall this will make the codebase even more uncertain, have a higher cognitive load.
It's going to fall over and I feel bad for whatever poor soul is trying to follow that quantum-bouncing ball. I've been there.
Free Your Code
The solution isn't to reinvent every wheel - but write the code you need. If you find the code you need IS a framework; then put that under your EXISTING abstractions. Don't code yourself into a corner by coding to the framework; write what you need, fit the tool underneath that. If the tool doesn't fit - It's clearly not the right tool for what the code needs.
Maintaining the abstraction is going to free you to think about what the application NEEDS, not how you can implement it via a tool.
I can see areas these frameworks will be fantastic, but they need to be the implementation detail for what your system needs to do; not force the application to do it a certain way.
Frameworks can free us from a lot of wheel invention, but we need to be sure our application doesn't know what wheel we're using.