Public/protected/private is an unnecessary feature

Role of access modifiers

  • Many commenters frame public/protected/private as tools to:
    • Mark what is stable API vs internal implementation.
    • Reduce cognitive load when reading unfamiliar code.
    • Signal who “owns” breakage when internals change (author vs user).
    • Help compilers/JITs optimize (e.g., inlining, representation changes).

Arguments that private/protected are unnecessary or harmful

  • Anything “private” can often be bypassed:
    • Reflection, unsafe accessors, name-mangling tricks.
    • Forking the library and removing/modifying access keywords.
    • Preprocessor hacks or pointer tricks in C++.
  • This leads some to argue privacy is mostly social signaling and should be a non-binding annotation (like TypeScript types or @internal), or omitted entirely.
  • Strict enforcement can hurt downstream maintainers when vendors change visibility across versions, making upgrades painful.
  • In contexts where you control the whole stack (e.g., backend services in containers), forking to expose internals is often seen as acceptable.

Arguments in favor of access control

  • Library and framework authors rely on private/internal members to:
    • Freely refactor internals without worrying about external dependencies.
    • Prevent consumers from coupling to fragile details and accruing tech debt.
  • In many settings (OSes, runtimes, proprietary apps, system libraries), consumers can’t realistically fork the dependency, so access control matters more.
  • Even in non-OOP or inheritance-light code, marking internal functions/fields reduces convention-based ambiguity and naming games like _DO_NOT_USE or _UNSAFE.

Soft vs hard privacy mechanisms

  • Some prefer “soft” privacy:
    • Python underscores and name-mangling; conventions over enforcement.
    • Go’s package-private vs exported (capitalization-based) model.
    • C#/Java internal/assembly/package-level visibility; namespace-based “internal” APIs.
    • Common Lisp’s exported vs unexported symbols.
  • Others argue that once annotations for privacy are standardized, they effectively become language features, so they might as well be enforced.

Inheritance, composition, and OOP context

  • The original article’s stance is tied to a broader “inheritance is an antipattern” view; several commenters reject this.
  • Many see private/protected and inheritance as valuable for:
    • Partial implementations in base classes.
    • GUI frameworks and other extensible systems where subclassing is common.
  • Others push for composition, traits/protocols, and FP-style patterns instead, but concede that pure composition can become verbose and awkward.