We scan new podcasts and send you the top 5 insights daily.
The classic domain-model hierarchy in OOP is architecturally weak because many essential features, like multi-selecting and editing a common property (e.g., color), are cross-cutting. This forces developers to pollute the base class with accessors, breaking the encapsulation the hierarchy was meant to provide.
Build products on simple, foundational concepts rather than complex, rigid features. These core building blocks can then be combined and layered, leading to emergent complexity that allows the product to scale and serve diverse needs without being overwhelming by default.
Liskov developed her famous principle by analyzing Smalltalk's inheritance. Her research group focused on defining modules by their specified behavior, not their internal implementation. This perspective allowed her to solve a problem the implementation-focused OOP community was struggling with: a subclass must behave like its superclass to be substitutable.
Scala was designed to uniquely synthesize functional and object-oriented programming. This fusion allows developers to use functional programming for logic and leverage OO's strengths for structuring components, modules, and encapsulation—areas where pure functional languages are often weaker.
To prevent a "ball of mud" codebase, OpenAI's system defines strict architectural layers using package boundaries and folder structures. By convention and tooling, different roles are restricted to specific layers—designers to the UI, PMs to business logic—ensuring modularity and preventing architectural decay.
The worst code often stems from detailed upfront design. Architects simply cannot hold all the system's complexities in their heads, leading to designs that are disconnected from the practical realities discovered only during implementation. This results in convoluted and inefficient code.
Conway's Law, which states that software architecture mirrors team structure, is essentially unbreakable. This is because communication bandwidth between teams is inherently lower than the "computation" speed within a single team, embedding those communication boundaries into the final product.
In imperative code, functions can silently read or write shared global variables, creating invisible and dangerous dependencies. Functional programming forces these interactions to be explicit (e.g., through function arguments or monads), encouraging a more modular and less coupled design that is easier to reason about and maintain over time.
Instead of designing an abstract API first, build the core, functional code (e.g., a rasterizer). Then, create the API by abstracting the patterns from that working implementation. This bottom-up approach ensures the final API is practical and well-suited to the actual problem.
Python's design allows external code to modify a module's internal state. Liskov argues this is a critical flaw for large projects, as it relies on every programmer's discipline rather than compiler-enforced rules. Without encapsulation, the system's integrity is vulnerable to the least-skilled member of the team.
Ivan Sutherland's 1960s Sketchpad used an architecture akin to modern Entity-Component-Systems. Instead of adopting this flexible model, early OOP proponents focused on its hierarchical aspects, leading to decades of rigid domain modeling that struggled with problems Sketchpad had already solved.