Why C May Not Be the Best Choice for Object-Oriented Programming
The Case Against C as an OO Language
Many argue that C, despite its popularity, is not equipped to handle Object-Oriented Programming (OOP) with the elegance and efficiency it requires. C evangelists like Ken Gregg might categorically state that C is perfectly OOP, but the reality is far more nuanced.
...
Beginner Unfriendliness
C is notoriously difficult for beginner programmers to grasp. This is especially true when compared to languages in the Algol/Simula lineage, which are also unsuitable for OOP beginners. The reason for this is that decades of effort to support changing paradigms while maintaining backward compatibility with older code and programmers only serve to increase the learning curve and widen the semantic gap.
Prototyping Challenges
C is not well-suited for fast prototyping due to the long compilation times and lack of interpreters. Modern languages offer more efficient ways to prototype, making C a less attractive choice for rapid development.
Abstractions and Semantics
The abstractions provided by C are often leaky, meaning that internal details of the language can still be accessed by the programmer. This lack of encapsulation makes it difficult to maintain a distinction between public and private members. For example, private members must often be exposed due to the monolithic header file declaration, leading to a proliferation of subclasses and making simple tasks like renaming something a complex task involving global refactoring.
Language Quirks and Fragility
The language is quirky and not in a charming way. The standard library is huge and bloated but not always useful. Its pace of innovation is glacial, with much of the language set in stone due to committee decisions and technical debt such as the friend keyword. This results in a language that can be inflexible and burdensome to work with, especially in large projects where others' code needs to be integrated.
Historical Context and Alternatives
Looking at the history of programming languages, the evolution from C to other languages like Python and Java offers valuable insights. Python, in particular, offers a much more approachable and less complex framework for OOP, as it focuses on readability and maintainability. Interestingly, the committee-driven nature of current C and Java in the late 90s and early 2000s led to the creation of more dynamic and flexible languages like Ruby, Lua, and JavaScript.
Modern Language Design
Modern programming languages like Python have a smaller surface area and are more opinionated, which makes them easier to use and maintain. The emphasis on clear semantics and fewer quirky details means that developers are less likely to write bad code due to inexperience, deadlines, and fatigue. This is in stark contrast to C, where the learning curve is steep, and maintaining code is a significant challenge.
The author also mentions that the actor model of concurrent programming is more natural and intuitive, and criticizes the way objects have been modeled in the past as "smart records" rather than entities with behaviors. Instead, modern languages like Scala and Rust provide more intuitive and flexible ways to model objects through traits and composition.
If not for the legacy of imperative programming and shared memory, we might have moved to a more natural and efficient model of concurrent programming. However, due to the historical context and choices made, we are still grappling with old paradigms and their limitations.