Comparing Programming Paradigms: Procedural Programming vs Object-oriented Programming
As a fledging or perhaps a seasoned code wrangler, you have taken an incredible journey of learning about data types, program control flow, functions, and perhaps even classes. And these fundamental building blocks are indeed wonderful—they bring greater understanding and capability for problem-solving both in your direct development efforts as well as with abstract problem solving in real-world applications (including construction, strategic business planning, organization, and analysis). You are now ready to examine software development strategy and methodology.
Up and until this point you have likely been assembling code blocks from beginning to end in a procedural manner. That “procedure” I mention queues you to procedural programming.
Procedural programming (PP) is great because it’s simple, typically straight forward (or can be written such that it is straightforward), and with proper design, it allows good isolation and containment for variables when properly scoped with functions and control loops. Despite the elegance and simplicity offered by PP, there comes a time when building something, that you begin to realize, after about 5000 lines I speculate, that your project becomes more prohibitive to maintain—can you imagine having to comb through 6000 LOC just to update the setTimeout delay on a scanning feature? It becomes easier to break apart code into more modular-based units that work together interdependently. Enter Object Oriented Programming (OOP) and Design.
Object Oriented Programming (OOP)
When you begin reading this article, it was within a logical order from beginning to end. Imagine this article continuing onward for infinite characters. It would be a large book! If I told you to give me the first sentence on the second to the last page you would feel daunted with burden before smugly replying, “Sure, please furnish math.ceil(∞) – 2 and I’ll get that sentence for you!”
To convert the infinite article book to an object-oriented design would be akin to converting this article into a choose-your-own-adventure book instead. Breaking down the portions of content, we would instead have independent asynchronous units (albeit an ∞ number) that could aggregately, modularly, work to fill in as a composite solution for a myriad of business and scientific applications. Object-oriented design accomplishes non-trivial computational tasks through (classes) factories that create widgets (single-copy instances defined as an “object” used for processing, evaluating or storing computation).
It’s 2016, and C “With Classes” has been around since 1979 (that’s right, C++ turns 40 soon). Earlier languages such as Simula67 came a decade earlier and set the fundamental foundations for later languages. Simula came about and was used in the design of simulations. Objects/Object-Oriented Design found a place in simulation software, for example, simulating the probability of a plane crash due to an engine problem vs a weather problem vs a Mean Time Between Failure problem due to deterioration in structural integrity. How does one possibly store and retrieve values for the different variables necessary, in a repeatable manner, to compute an airplane crash? How can such software be made abstract such that *any* airplane simulation object can be defined in terms of weight, depreciation age, weather conditions, etc? Such problems occur in other applications as well. Shop factories seeking higher productivity, stock modeling, and forecasting, gene sequencing; these industries all benefitted tremendously through solutions put forth from the advent of the Object-Oriented Methodology. The Term “Object Oriented Programming” actually hails its origin from Xerox initially in reference to innovations with the “then new” language Smalltalk in the early 1970s.
Comparing Programming Paradigms: PP vs OO
You may wonder why we don’t begin with object-oriented design from the start, there are good reasons for not doing so. Notably, much development heavy lifting involves careful planning and forethought of current and future design considerations. Take for instance a postal code. Postal codes in the United States are numeric and can be represented as five digit integer. If your record-keeping system is set up such that you have a numeric field in a table in your database, that this field will return an error if you were to attempt to enter in letters or symbols—fast forward two years, business has been great and your boss would like to see expansion into Canada! Uh-oh… You designed the field to be an integer—your validation logic is based on that integer being returned, you created business logic to handle determining shipping costs based on the value of that specific integer using comparison iterators (< and >)… changing it to a simple Integer will not do. That, my friends, is the importance of forethought and why design considerations should be thoroughly analyzed before moving forward with building your application. Tying in OO design with your programming objectives can add considerable time for development and refinement. Having multiple prospective use cases before beginning development can help you decide on whether or not to abstract your codebase down into reusable modular objects.
Now before you consider dropping your Procedural Programming style from your code wrangler habits, consider that there are detractors to OOP Design including a fair bit of reasonable criticism warning against dangers of OOP’s “falsehood” thinking. Luca Cardelli shares reasonable concerns in a research paper titled “Bad Engineering Properties of Object-Oriented Languages”. By contrasting many of the Procedural Programming benefits gained over the course of technique refinement and improvement, Luca contests that the same gains cannot be stated so much with OO concepts. To quote from the book,
“Although reuse is a big win of object-oriented languages, it is also the case that these languages have extremely poor modularity properties with respect to class extension and modification. For example, it is easy to override a method that should not be overridden, or to reimplement a class in a way that causes problems in subclasses.”
Furthermore, “Smalltalk was originally intended as a language that would be easy to learn. C++ is based on a fairly simple model, inherited from Simula, but is otherwise daunting in the complexity of its many features. Somewhere along the line, something went wrong; what started as economical and uniform (“everything is an object”) ended up as a baroque collection of class varieties.”
Quite contrasting to popular consensus that OOP has been Computer Science’s panacea for the past 30 years—especially after the proliferation of Java in the mid to late 90s. For instance, when you glance Stackoverflow, you find an overwhelming support for OOP so much that many swears off “any hint of Procedural Programming” as inferior with regards to code reusability, performance, and separation of concerns. However, the counterpoint to OOP is that often times, budget and complexity constraints will force teams to pick and choose principles when convenient and not necessarily follow concepts consistently due to overcomplexity and expense (seen often in cross-cutting concerns between subclasses to shortcut/subvert the process of refactoring proper encapsulation and prototypical inheritance when passing messages between objects).
So which methodology should you choose? I’m glad to share that the answer should not be “it depends”! In fact, the answer (in my opinion) is that both paradigms should be used together, independently within the same codebase where instantiation of objects to store application logic has merit. Use functions for encapsulation and bundle functionality and interfaces into modules to be exported and used as necessary when dealing with procedural level code blocks in your application. A procedural language can be used exclusively if the OOP architecture will not provide any reuse benefits in the long term. Object-oriented programming is a methodology by which we can better organize our codebase so that projects containing more than 5000 lines don’t get out of hand. Furthermore, aspects such as encapsulation, instantiation, DRY principles are all more readily achieved through OOP methodologies.
Other aspects to consider include performance vs maintainability. If you really intend on having a specialized program that won’t have change requirements, designed for high performance, your efforts will be better served when building with PP concepts. A short script like programs that run against crontab, windows Powershell, or Launchctl shines here. Any sort of application that exists beyond the command line, requires asynchronous behavior, a graphical interface, or any multi-threaded applications will find great benefits and advantages utilizing an OOP methodology. Modularity should also be used as a guide.
Do you plan to implement the main program that has a few distinctive features that can all be contained in a single file that’s less than a few thousand lines? Consider keeping functions maintained locally in a single file via PP methodology.
Do you plan to implement features as part of a larger application? Some examples of features that may be part of a larger application include a scoring system or an inventory system in a game, an emailing module that is used as part of a reporting software package, a database connection file; these are all examples where a modular-based approach is superior due to the benefits of code reuse without violating DRY principles.
The underlying issue identified is “How, Frank, do I know when I’m ready to move onward into OOP Concepts?” Admittedly, it IS hard to know for when it makes sense to go one route vs another. If time is on your side and complexity is reasonably high, the proper approach is to choose the OOP route as a design preference. If you have an emergency use case where you need to patch together a critical fix for a production server, then most certainly PP is the ideal method to get your fix implemented and deployed to production. Just remember, there is no hard/fast rule. Pick a composite strategy of utilizing concepts from both methodologies when the circumstances merit doing so.
Have you built a Procedural-Based Application that you had to eventually refactor into an Object-Oriented one and did you see performance improvements as a result? Let’s discuss further in the comments below.
Related tutorials you might be interested in:
- Object-Oriented Programming (OOP) in C
- Getting Started with Object-Oriented WordPress Plugin Development
Frankenmint is a technophile with a penchant for Bitcoin, versed in web and software development.