One of my bedrock OO programming practices is a use of internal immutability. I don’t know if there is an expression that describes this but that is what I call it. By this I mean calls to a procedure or function of a class from within another procedure or function of the same object shouldn’t change the state of any data members of a class. This is often referred to as avoiding side effects. Isn’t it fundamentally essentially that an object consists of both state and behavior? (As an aside, I am omitting the third characteristic of an object, identity.) State that is exposed to another object is allowable, and indeed essential for OO programming.
This practice is etched in mind through prolonged exposure to pain. I began my programming career by supporting the implementation of a subsystem developed by an experienced Fortran developer required to write his first C++ program. The essential flaw to this design was that each column of each database table used represented a data member in a SINGLETON class. What happened was that the state would get overwritten and lost in processing events. Development had started out very promisingly but slowed down by the time I joined the team. I assisted by testing the development code baseline. As I identified test case failures, the developer, who had both a phenomenal work ethic (12 hours a day, 7 days a week) and a keen ability in logic, would painstakingly correct the code. Once corrected, test cases would frequently fail again over time. Once implementation was undertaken, despite the fact that the system had no error-handling logic, it needed babysitting round the clock. I spent my evening onsite for this application querying and updating Oracle records to provide that fault handling. This is an extreme case but was helpful to develop OO religion.
This is a long-time practice of mine but not one that I could formally articulate until I recently read Growing Object-Oriented Software Guided By Tests, written by Steve Freeman and Nat Pryce. This book has a lot of insights into OO design that stand apart from its focus on TDD. Let me quote their wonderful explanation.
“
As well as distinguishing between value and object types (page 13), we
find that we tend towards different programming styles at different
levels in the code. Loosely speaking, we use the message-passing style
we’ve just described between objects, but we tend to use a more
functional style within an object, building up behavior from methods and
values that have no side effects. Features without side effects mean
that we can assemble our code from smaller components, minimizing the
amount of risky shared state. Writing large-scale functional programs is
a topic for a different book, but we find that a little immutability
within the implementation of a class leads to much safer code and that,
if we do a good job, the code reads well too.”
No comments:
Post a Comment