Component Theory
Introduction
I was on a flight to Cancun for Ed’s 30th birthday, where I was looking at the plane engine just outside my door waiting for boarding to complete, and noticed a dozen or so locations on
**Introduction**
I was on a flight to Cancun for Ed’s 30th birthday, where I was looking at the plane engine just outside my door waiting for boarding to complete, and noticed a dozen or so locations on the engine labeled “Hoist Point”. These locations are pre-designed places that can bear load while lifting an engine in air, detached from the wing. A seemingly small detail, but important nonetheless.
As an engineer with experience in designing systems for aerospace and defense, semiconductors, consumer electronics, full stack software engineering, and applied artificial intelligence, this got me thinking - at what point in the engine design did engineers add the hoist points? Beginning, middle, or end? If I were an engineer of engines, would I design the core turbine first or focus on hoist points to hold the engine in air?
The answer is that engine design is iterative in nature. If starting from scratch, an engineer likely designs a core turbine capable of meeting certain minimal specs first to demonstrate a proof of concept (MVP). These preliminary requirements likely involve minimum/maximum thrust, overall weight, aerodynamic properties, and attachment points to the plane (to name a few).
Then, as more requirements are added, the engine design is modified to meet the additional constraints. After each modification, tests and simulations are run to ensure that the new design continues to meet previous specs.
This iterative process allows engineers to focus on one thing at a time only, thus allowing the design of new features into infinity.
But not every component needs to be designed from scratch. For example, you likely don’t need to design the common fasteners for your engine - there are likely many existing fastener components already existing and in production that meet your needs.
But how do you know of their existence, how do you find them, how do you know if they meet your criteria, and how can they be improved over time?
These are problems of engineering, science, and philosophy. At its core, Component Theory provides a logical framework for building things that can scale into infinity. It’s a process and a design philosophy optimized for efficiency, productivity, and iterative development of ridiculously complex systems.
**What is a Component?**
From a component-based design perspective, components have specific specs that they meet and are tested well.
Elements of a Component
- components always have a unique name across all other components. This allows them to be placed as subcomponents of larger components and referenced by other components
- components can depend on other components
- components often have revisions and improve over time. Revisions are necessary so that a component can be improved materially without impacting existing designs in production.
- components should fully encapsulate any and all functionality they provide (even through other components)
- components often accept inputs and produce outputs.
**Are components things or actions?**
In React, a component definition is a thing, but instances of components execute functions. So, components are functionally both things and they also perform actions.
**Do components have a parent or do they exist in isolation?**
In theory, components are typically designed with the purpose of being used in a particular design or higher-level component. However, it is quite common to design a component for use-case A, but also use the component for use-case B in some design downstream. In the multi-application instance, it’s imperative to version components, because upgrading a component for use-case A without releasing a new version may inadvertently break application B.
**How do components fit in with software?**
Components are typically created as software libraries or packages. However, these libraries and packages are usually difficult to version and maintain, in particular if they have their own code repository, access requirements, credentials, and more.
This leads to component-bloat, which eliminates the use-case for a highly efficient and scoped component in the first place.
**Is everything in a design a component?**
**Yes - or at least, *everything should be.***
Except in the case of a component library, which contains an index of components versioned together, everything in a good design should be its own component.
**Component naming and namespaces**
It is possible to produce an infinite number of components with unique names. It’s also possible to nest components infinitely via categories. But both approaches are completely unworkable at their logical boundaries (thousands or millions of unique names, or thousands or millions of levels of hierarchy).
Thus, we must balance between one infinitely long list and one infinitely deep hierarchy. And how do we know the optimal balance?
The theoretically optimal balance is one which allows for the most efficient and accurate method of finding the correct component one is searching for. It’s one which optimizes network traversal when seen as a network.
This can vary based on quite a lot of variables and preferences, but I generally like the following naming convention:
{namespace}/{key}
In this example, a component or component library is represented by this unique naming convention with exactly one level of hierarchy, and each unique complete name is a versioned component.
**Component libraries**
Component libraries are a distinct type of component where subcomponents are packaged and versioned together as part of the component library. This is often the case of software libraries where each functional unit is highly dependent on the other functional units within the same Component, and almost always share identical dependencies. The library often functions better as a cohesive unit, and is therefore packaged as such.
In this case, the Component should have no default export, only named exports.
**Can components have circular dependencies?**
Ideally, and in most applications, no. Probably in all physical applications, no.
**Which software languages implement Component theory?**
While languages like Python are great at simple scripting, they simply do not provide support for nested namespacing, monorepos, etc. For this reason, Python is not a viable candidate to implement Component Theory.
Typescript, however has support for namespacing, multiple monorepo options, and package versioning within a monorepo. Additionally, typescript has better default support for code you intend to make visible to the outside via exports, and requires entrypoints (instead of allowing imports from literally anywhere).
Additionally, typescript/javascript is no more than a specification for a language, meaning that a company or org could implement their own JavaScript implementation in rust or go, for example.
For these reasons, Typescript is an excellent choice to use with Component Theory.
Thoughts:
Loop this in with pull requests for inventory! Each usage of a component can create a “pull” in the system, and dependencies can automatically know to get another component. Dependencies are automagically there already.By Mike Morton