Lessons Learned from Building Holism

Lessons Learned from Building Holism

Explore the architectural, engineering, and organizational lessons learned while building the Holism Software Product Line.

Holism is designed as a Software Product Line for building different business applications from reusable cores and parts. The work highlights a recurring tension: shared foundations reduce duplication, but they must remain understandable and flexible enough for real products. The most useful lessons concern boundaries, configuration, operations, and the discipline required to keep reuse valuable for small and medium-sized businesses.

Reuse needs clear ownership A shared rule should live in the layer that can explain and maintain it. Identifiers, settings, localization, cache conventions, and API response behavior belong in common foundations when several products depend on them. A blog or course part should contain its domain behavior without importing another part's internal files. Public interfaces let parts be composed into runnable products while preserving the ability to change one part. Reuse is not the number of abstractions in the repository; it is the reduction in repeated decisions and fixes across products.

Composition shapes development The cores and parts are not independently runnable applications. They become a product inside a composed container. That changes how teams test and deploy: an isolated repository check is useful, but the assembled product needs its own build and integration verification. Bundling boundaries should reflect the architecture so one part can be changed without unintentionally combining unrelated code. Development commands should make the composition repeatable and visible. When setup requires hidden knowledge, the platform has not yet captured enough of its own rules.

Configuration should replace repeated forks Different tenants need different languages, content limits, layouts, and feature settings. Represent repeated variation as scoped, validated settings rather than copying a product for every customer. Defaults and fallbacks should be defined centrally so new tenants work without extensive manual records. Still, avoid exposing every implementation detail as a setting; the product should offer meaningful choices that can be explained and supported. A configurable platform succeeds when it serves real customer differences without making every feature a matrix of special cases.

Keep the API authoritative Clients are easier to maintain when the API returns ordered, filtered, localized, render-ready data with the flags needed for display. The browser can manage unavoidable presentation state, but business permissions and calculations should stay on the server. This matters when an admin panel and public site consume the same domain information. Tenant isolation and cache keys must remain consistent across those processes. Centralizing such rules reduces disagreements between products and makes defects easier to diagnose.

Match architecture to business scale SMBs need software that is secure, extensible, and affordable to operate. A modular application and simple deployment may meet those needs better than a large network of services. Add complexity when measured workload, availability promises, or customer contracts justify it. Maintain backups, monitoring, certificate renewal, and deployment commands from the start; operational discipline matters even with modest infrastructure. The platform's value depends on the total cost of delivering and running a customer product, not only how fast a new page can be scaffolded.

Keep learning visible Conventions should be tested against actual products and revised when they create friction. Document the reason behind boundaries, run composed checks, and review incidents for repeated causes. Avoid claiming that every planned capability is already complete; distinguish current behavior from intended architecture. Holism's strongest lesson is that reuse requires ongoing care. A shared platform saves effort when its rules are clear, its parts remain replaceable, and the team can operate the resulting products confidently. Each new part is an opportunity to test whether a shared convention is truly reusable. If a rule fits only one niche workflow, keep it close to that product instead of making every other part depend on it. When a rule is broadly useful, move it into the appropriate core and simplify the leaves.