I don't remember exactly where or who, but writing re-usable code was impressed upon me as an important thing
I now completely disagree with that.
Do not write reusable code.
One of the worst things you can do when writing code is to make it "re-usable" before you have multiple uses.
I tried so much to make things re-usable. I mostly tried to make it as non-coupled to the project I was working in as possible. Remove as many assumptions as possible. Create as much flexibility as possible... all very wrong things to do.
Code reuse is critical to maintainable software - but I never knew how to do it. I never understood. All the books I read, never gave me that clarity. Maybe a re-read would make it clear now, but I'm not sure. I've re-read a number of the "must read" books, none give me the clarity I have now on how to write re-usable code.
I want to first show what I tried to do when I tried to make re-usable code... then I'll talk about how MicroObjects get us actually re-usable code.
Reuse Isn't Through Packaging
I ended up looking at re-usable code as code that could be packaged as a DLL, JAR, AAR... something that another project could pull in and use. That's how I approached writing a lot of the foundation for my projects. "It'll need to X, Y, and Z - let's make that and it'll be REUSABLE!!!"
Never reused one of those. It either got tightly coupled (because there was only one use case) or was never needed elsewhere.
I couldn't write code that was re-used because I only considered re-usable as cross-product/project. This never worked as I always built for a single use case, and tried to make it more universal - doomed to failr from the start.
This is one of the points of what code reuse - ISN'T.
Despite it being code that is used many places - libraries and dependencies are not code reuse.
We're not "reusing" the code. We're simply using it. It's the purpose of the package to be pulled in and used. That's it's life. It's not being "re-used".
This was my original ideal of what code re-use meant, writing a packagable module that I would re-use (forcing the word in) across products.
Reuse Isn't Through Class 'Lift'
I found that I couldn't make whole modules that'd work well being packaged for re-use in other modules.
Or the only value was in very small sets of classes, or a single class.
Code reuse is not writing a class that can be lifted into another product as is, or even with minor modifications.
This isn't even code re-use. It's code copy. This is a valid practice - take the foundation and make it work elsewhere. It's not the "code should be re-usable" that I was always aiming for. It's not re-using the code, it's modifying the code.
I could only do this with classes so simple and brain dead it was either Utils (BOOOO) which had a bunch of functionality I didn't need ("yet" I told meself) or so small it was faster to re-write it than find it to copy.
This isn't code re-use.
We can't just lift code into a new project and consider it "re-use" - it's not being "reused" it's being put in for the first time.
What is Code Reuse?
Both of the "not" sections have a theme - Code reuse is not about taking code and migrating it to a new project. Regardless of it being through a package or copy and paste. Using code somewhere else isn't code re-use.
Let's talk about what code reuse is.
Recently I finally found what code reuse it. I found it through the application of microObjects.
My simple definition is the ability to use code already in a project when refactoring without having to change the logic.
Reuse the code when you refactor w/o having to rewrite the internals if the class.
Code ReUse allows a change of behavior, of logic, of flow; all without changing the contents of any methods.
An example of this was a pomodor timer I wrote.
Pomodoro is a way to focus and take breaks to continue to work effectively. You work very focused for a period of time; the session; then take a short break. Every 4th session is followed by a long break. My timer had the option after the 4th session to take a short break or a long break.
Well... That was the intent.
I had a couple things wrong. The choice wasn't until after the 4th short break. And it wasn't between a(nother) short break and long break, it was between a session and a long break.
Oops. I had the choice after the wrong action, and between one of the wrong actions.
Session.Next ? LongBreak : ShortBreak
was instead
ShortBreak.Next ? LongBreak : Session
The onlything correct is that one of the choices was a long break.
Probably a bit of a pain to change this around. Not HARD, just a pain. Some brancing somewhere to change the choice, but implement it in another piece of the code...
Something like that?
I didn't have to change ANY methods. The only changes to fix this was class instantiation.
It was three lines of code. All what objects were instantiated.
This is code re-use. Being able to fix bugs, to refactor, without needing to re-write the functionality, just shift instantiation around.
This is where the idea of classes as "LEGO blocks" applies. It's simple classes that are combined to perform complex behaviors. MicroObjects forces this into our code, it forces the availability of all the great practices that seem to be in the shadow of our industry. "Oh yes, I know that... oh no... the code doesn't support it"
The code can support it - but it takes a skill I think a lot of engineers never get to practice, refactoring.
Code re-use is the ability to use existing classes when refactoring or making changes to the behavior, without making changes to method logic.
I've done this, multiple times. I know it's possible - and it's amazing. This is part of how you can go so fast.
The technical practices of microobjects will help you get there. You'll see some of it, and it'll be awesome. A full MicroObjects code base can do even more.