Author’s plea: Be gentle…
Diving more into lessons and self-study of object-oriented programming with C#, I’ve begun learning about what inheritance can do for a programmer by practicing with abstract and sealed classes. It’s a mindset change, for sure.
Given the majority of my experience with code has been in procedural languages from days long gone, the first lesson I encountered introducing static methods caused me to move from feeling intimidated to completely confused. My inexperience (and ignorance) with OO was causing me to blend method with function as I know it: why the hell wouldn’t I want a method to be accessible without first creating an instance of the class? If I want to use a method, damnit, let me use it!
But after continuing more into classes and inheritance tonight, I’m realizing that a method is not a function akin to my experience. There’s a whole level of abstraction here that makes me nervous; no one likes to be working with something that makes him/her uncomfortable, let alone knowing there’s so much more that still needs to be understood. If I’m uncomfortable now, just wait until later…!
Here’s what I’m thinking and feeling at this moment:
A method isn’t just a “function”, in that it does some sort of action or computation to return a value. I’m still thinking a method is close to this definition, but clearly there’s an association to the class (and by relation, the other methods in the class) for purposes of organization. I’m getting the feeling that this organization isn’t just about maintainability, either, but part of the abstraction for how a developer may define his/her classes.
A class, as suggested above, is nothing like a procedure from my experience. Rather, it is a purposefully “chunked” collection of properties and methods that create a unified “whole”. In reflecting on my limited procedural history, I did create procedures that had a purpose (a “whole”), but objects and inheritance create a new line of thinking that is exciting and completely foreign.
As I practiced tonight, I wrote a basic program that looked at inheritance from the perspective of cars. I created a class called “Car” that had common properties like make, model, etc. But then the exercise introduced a question: What if we have a truck with properties a car doesn’t have?
My first thought was to create a new class called “Truck”, fully aware of the pain I encountered in the past maintaining multiple procedures with a ton of similar code (i.e., yes – I used copy & paste). But as the exercise continued, the idea of an abstract base class was introduced that caused me more than a couple sideways glances.
I think here is where inheritance really clicked for me, though. Rather than create a “Car” class to inherit from, pull back as far as possible… an abstract “Vehicle” class with the shared properties. Therefore:
class Car : Vehicle
class Truck : Vehicle
class Truck : Car
Simple to understand and maintain.
My Agile knowledge and thinking to this point
I’m experiencing two lines of thought that seem to be perfectly human in the face of new programming knowledge. One, the desire to be successful and design my code to be correct the first time… Two, the many possibilities of what a design might look like, coupled with unknowns, makes me question whether I could ever be “correct” the first time.
I suppose it is unsurprising that the desire to be perfect is a far stronger emotional sensation. Why would I want to waste time and experience the frustration of refactoring? Couldn’t I just invest the time to discover a great design up front?
I’ve allowed myself forgiveness to be human, as I don’t think anyone would choose “refactor as you go” over “get it right the first time”, assuming such outcomes could possibly be black and white. Yet my comfort with uncertainty has been trained over many years in applying Agile to things other than code, so I’ve found I can fall back to the pursuit of “simple” rather easily.
However, this is my first taste of experiencing the power of working code to allow design to emerge. The experience thus far suggests that, as long as we incrementally focus on small pieces and don’t wait for the code to bloat, refactoring as design emerges isn’t a burden; it’s the small price we pay to get it right.