Understanding the World
Let’s continue our discussion. Previously, we mentioned that the essence of code dependency is the dependency of thought, a change in thought leads to a change in code. However, in the real world, although changes propagate and spread, their impact is not as drastic and is always confined within certain scopes. At least, why should adjusting a query directory affect my mom’s food delivery?
Surely, it must be the fault of the language, or at least the framework, their design must be flawed! If it were that simple, why not design a new language to fix this defect? Upon reflection, it seems that changing to any language wouldn’t solve this problem: if the UserInterface
depends on Search
and it changes, then UserInterface
must change too. The food delivery system depends on UserInterface
and thus suffers, and then the business relying on the food delivery system suffers, and so on. No matter what language is used, the solution is to separate the food delivery system and UserInterface
into services. Then, when UserInterface
is upgraded, some resources can be scheduled to keep the food delivery interface accessible.
But isn’t language a reflection of thought? People don’t operate this way, they are much more flexible. Why must systems be so rigid? Yes, if all this is correct: our code expresses our thoughts, our systems can’t withstand changes, yet our real world isn’t like this, then there is only one possibility: our thoughts is wrong! Our understanding of the world is flawed. The world doesn't operate as we imagine, it has edges we have yet to perceive
.
Between people, and between people and the real world, there are countless connections and dependencies, needs and contributions, but a change in one doesn’t necessitate a change in another. Just because I once depended on you doesn’t mean I cease to be myself, and if you disappear, I won’t cease to exist. On the contrary, humans have an independent core that isn’t swayed by external factors. The connection between people and external things lies in continually adapting to environmental changes while maintaining the self. Environmental changes affect the connection between people and the world, not the people themselves.
Not only humans, but all things have their essence. Connections are not inherent in the essence of things but arise from the collision and interaction of essences
. These independent substances construct our world, bringing about the evolution of the world through constant collisions and pressures. These unchangeable essences form barriers that control the spread of local changes, keeping our world relatively stable and preventing significant fluctuations. This is the true nature of the world.
So, it is really our code that’s wrong. Why did we write the Search
interface into the UserInterface
?
Our Connection with the World
At this point, many people are on the verge of madness. What exactly should we do? Please clarify, if UserInterface
doesn’t obtain the Search
interface, how should it call it?!
This question should actually be asked to yourself. When you, as a user
, want to search
, how do you do it?
When a person first exists in this world and begins to interact with it, at the very beginning, when their essence has not yet formed and is about to be born, they are in an omnipotent self. This world is designed for them, whatever they want, the world should provide feedback accordingly. Whatever their wishes, the world should satisfy them. At this moment, they are closed within themselves, needing neither to understand external things nor to rely on others. Their wishes and motivations construct their essence.
When you are the center of the universe, do you need someone to give you a search interface? Isn’t the world revolving around you? Isn’t what you want the most important thing? This is what belongs to your essence. So, the answer is simple: follow your heart. As long as you can achieve your wishes, write and call however you want. Just state your demands to the world, and let the world fulfill them. The interface you propose is solidified in your essence, unique to you, and naturally won’t disappear with changes in external things.
However, as we grow, we realize the world isn’t like that; we are not the masters of everything. After countless disappointments, we understand that to achieve our goals, we must adhere to certain agreed-upon rules. Thus, our bodies begin to develop external interfaces, organs for adapting to the environment and connecting with the outside world. Without these, we cannot rely on and cooperate with others. But having these doesn’t mean we lose ourselves; we are still who we are, wanting what we want and doing what we should do.
As we grow, our behavior patterns become more mature. But if you think about it, we are still based on our own desires when making demands on the world, only using interfaces recognized by the world. When we want to achieve a goal, we first consider our own position and then formulate our plan. If external assistance is needed, when the time comes, we look for suitable interfaces in the outside world and then try our luck. If one doesn’t fit, we just try another. Just like job hunting, do we stall because of one rejection? What we hope for and what we can get from the outside world are two different things; the former belongs to the self, the latter to the world. We don’t wait for others to give us something to decide what we need. We don’t change ourselves because others change, nor do we destroy ourselves because the world isn’t as we imagined. Therefore, as humans, no matter what stage we are at, it is never someone else who decides how to search
.
Now, we have the answer to why our systems don’t operate like the real world. What identity does our thinking take when constructing the system? Is it still ourselves? On the contrary, we are the world
responsible for satisfying everything. We need to know the wishes of all modules and meet all their requirements. We know everything, understand all agreed rules, focus on the connections between substances, but unfortunately ignore their essence, stuffing various external things into their core. Then arrogantly tell them, this is part of you, your wishes should be realized this way. Thus, the essence of the modules in our system is invaded. However, the world is constantly changing, and so are the rules. Soon, we find that the system we constructed, all modules are hollow
, lacking a stable core, unable to withstand even slight changes. After a storm of innovation, everything perishes, and the world we built resets and restarts.
When can we stop playing the world
and instead stand from the self
to write our systems?
The Basic Structure of the World
The next question becomes somewhat bizarre: on one hand, we are asked to adapt to this world and follow various rules; on the other hand, we are asked to maintain a stable essence, not easily changing with external things. However, the world is vast, and these rules are countless and ever-changing. These three aspects are mutually contradictory and impossible to achieve simultaneously! How can we prepare all interfaces with the constantly changing outside world in advance? How can we describe all possible processes and methods in code? If not prepared, how can we not change when changes come?
Let’s look back at how we adapt to changes: we live in the world without omniscience of all people and things. Through growth and learning, we acquire basic methods of dealing with people and general knowledge of understanding the world, understanding various rules. Some are superficial and constantly changing. Some are essential, often simple and profound, buried where we can hardly see, but if we grasp them, we can measure everything with their scale. When we collaborate with people, we don’t need to grow up together from childhood; when we understand unknown things, we don’t need to trace back to the creation of the earth to sort out their origins. The former only requires both parties to follow familiar conventions, and the latter only needs to measure with universal laws operating in everything. This is our interface with the world. With these, we can go to places we’ve never been, see worlds we’ve never seen, meet people and things we’ve never experienced, collide and cooperate with them, and after the accidental encounter, wave goodbye and keep our original selves, ready for the next journey.
So, what are these conventions and laws? Well, before answering this question, let’s look at the consensus we’ve already achieved through the previous discussion. We recognize that all things are independent substances with relatively stable cores. When they meet, they form various connections. Some of these substances are changing, and these changes spread through connections and stop when they encounter stable cores. So, the goal is clear. The universal law we need to study is the law of connection and response to changes, and the consensus we need to reach is this law itself.
When we study the connections and changes between substances, we might imagine: do the connections between substances also hide some universal laws? Ignoring the complex appearances, are there some inherent fixed formulas that can express all possible processes of connection between things? If the answer is yes, then the problem is solved. We can use a set of limited interfaces to prepare for infinite connections, standing on our own while using a resonant way to express our demands to the world. These demands belong to us, unrelated to how external modules operate, or even whether they exist at the moment. Thus, we gain freedom and are always ready to dialogue with the world. If all of us follow the same method and use the same interfaces to connect with the world, then similar concepts
is born. When all of us use similar concepts
to create independent modules, when the system needs to run, and they need to connect, we let them gather.
Will these self-contained modules necessarily satisfy each other? Let actual operation decide, perhaps requiring coordination, compromise, or change. Coordination and compromise often only involve our connection with the world, our face adapting to the environment, external things. Only when we are truly wrong, incompatible with various environments, and hit walls everywhere, do we need to change ourselves, often involving pain and cost. But modifying and changing modules is much easier than changing people, isn’t it?
If we can achieve the above, software systems will become something incredible. Imagine:
- When developing any module, we only need to focus on the domain the module handles, i.e., the module’s boundary, then use
similar concepts
to express our demands to the world and provide services to the world. This means software development is freed from external dependencies and can proceed as needed. It means a large group can work in parallel with fewer constraints. It means people worldwide can contribute modules, make demands, and construct systems usingsimilar concepts
. - Modules are autonomous and independent during development, self-contained within the
self
boundary, only connecting into a complete system during operation, needing adaptation and docking. This means high cohesion and low coupling of modules, environmental independence, and reusability, continuously accumulating components for the system, allowing system assembly and evolution to adapt to the environment. - System changes are confined to module boundaries, limited to specific areas. We can easily update the system without worrying about the spread of changes, making adjustments quick and low-cost. We can also easily identify the boundary between stable cores and unstable connections based on system changes, finding truly independent substances and encapsulating even a few lines of code’s core to isolate changes. This makes modifications quick and maintenance costs low.
Thus, we get a highly dynamic, instantly changing, almost uncoupled, parallel-developed, continuously accumulating, on-demand assembled, easily modified system, a system that once existed in ideals but was hard to achieve.
So, the key question now is, does such similar concepts
exist? This involves three questions: objective, subjective, and the combination of both. Objectively, we need to answer whether it exists; subjectively, we need to answer whether it is knowable; combining both, we need to answer how we should do it.
First, the objective question: is it possible to use a set of fixed concepts to apply to all things in the objective world, which doesn’t change according to human will? This requires delving into the basic structure of the world. What is the basic structure of the world? This is essentially an ontological question. Throughout history, sages have given various answers, each explaining the basic structure of the world.
Democritus of ancient Greece believed that the basic modules of the world are atoms. Their movement causes connections, and their collisions form everything. Everything is in constant change, while atoms remain themselves. Eventually, the disintegration of atoms leads to the demise of things, and atoms continue to move, forming new things.
So, in Democritus’ view, the connection of everything has only one interface: move. According to his view, the similar-concepts interface should
public interface Thing<P, R> {
public R move(P... otherThings){}
}
How touching, who said there’s no way to express the connection of everything in a unified way? Democritus did it with just one interface. No method call can escape its grasp. If our module internally relies solely on this eternal concept, we can almost freely express our demands to the outside world. Do we need to care about how to search
? It’s just the difference between move(keyword)
and move(keyword, dir)
, we don’t need to rely on someone giving us an interface.
Leibniz believed the world is composed of countless monads. These monads are different and indivisible; external things cannot change their internal nature. They only arise, change, and perish due to internal causes. Everything is composed of monads, but interestingly, monads are not equal. Rational monads, with wisdom and thought, are the highest level. Lower-level monads gather around higher-level ones to form things. But even if monads move and aggregate, they have no connection and cannot recognise or perceive each other (uh…). So how does this world operate? Because the internal program of monads is written by the omnipotent God, they move according to inside codes, governed by a supreme will, appearing harmonious.
Leibniz’s model is roughly like this:
public class God {
private static God theOne = new God();
private God( {}
public God getTheOne() { return theOne; }
public Monad manageTheWorld(Monad... monads){}
}
public class Monad {
void preHarmony(){}
}
God is a singleton, and its only task is to manage these monads. Monads have no input or output, only a Preestablished harmony
method for God to call. This preHarmony
should ideally be a private method, only accessible to God and itself. Let’s forget about Leibniz; his model requires God to integrate all the code, which is impractical.
For Wittgenstein, the basic organizational unit of the world is facts. This fact doesn’t refer to specific objects but logically determined truths. The connection of facts is determined by logical propositions seeking truth. Understanding the world involves finding the general form of propositions. He listed about a dozen truth functions, which he believed were the only ways to express the world. Anything beyond this is meaningless and must remain silent.
Wittgenstein must have been a fan of functional languages. His model is roughly like this:
public interface Fact {}
public interface Function extends Fact {
boolean wahrheitsfunktion(Fact a, Fact b){}
}
...
// Die allgemeine Form des Satzes
...
Note that Function
itself is a Fact
that can determine truth values, so its parameters can also be Function
. Below the comment, a set of about a dozen Die allgemeine Form
is defined, which I won’t list here. The entire interface implementation is just these. Wittgenstein didn’t need to write many modules; his focus was on how to assemble these dozen modules to determine the truth value of a problem.
Now we can conclude the previous question: Yes, we can indeed use a few concise forms to express all connections between substances, in more than one way. The basic structure of the world depends on how we view it. Our different understandings of it produce different expressions of its structure. But any well-designed method, if complete, can express the entirety of the world as we know it. If this basic principle is established, our system’s structure will be fundamentally different. The dependency relationships and connection patterns of substances will fundamentally change, freeing software from its shackles, and a new system form will emerge.
Like this, all static dependencies between modules are removed; they all depend only on similar-concepts, freeing them from the dependency network. Their relationships change from internal dependencies to external connections, dynamically assigned at runtime, allowing changes at any time. Doesn’t this resemble the world we know?
Now that the existence of similar-concepts interfaces is proven, let’s look at the subjective question. Each of us is an individual with a different core. Even if we follow the same similar-concepts interfaces to handle the same things, can we achieve similar cognition? This is essentially an epistemological question. Millions of coders live on this planet, possibly in San Jose, Beijing, or drifting on a raft to a remote island in Mauritius, or coding while hanging from a tree in the Amazon rainforest. With such different people, even if given the same interfaces, can they achieve similar-concepts and produce modules that can coordinate?
This question also has many answers. Plato, in his Republic
, likened people’s sensory experiences of the world to seeing shadows in a cave. Inside the cave, all seen are illusions; outside the cave is reality. Ignorant people see various illusions, producing various misconceptions, while the real ideal world is perfect and singular. Beneath the changing appearances lies unchanging truth, which ordinary people cannot know. Only through guiding people to metaphysical thinking can they be led to true knowledge. Yes, Plato’s Republic is unique, and its true knowledge is absolute. As understanding deepens, people’s knowledge converges. Eventually, everyone will gather at the same place and witness the same truth.
Spinoza believed that the world is composed of substance (natural existence), which is eternal, infinite, unique (note that here, uniqueness and infinity are not contradictory; Spinoza’s substance is essentially equivalent to the concept of a class. There can be an infinite number of classes in the world, but an identical class can only be unique. Think about how we cannot define a class with the same class name, it would be meaningless) and indivisible. The extension representing material and the thought representing ideas are fundamentally two attributes of the same substance (class) (these concepts existed back then; programming is essentially a form of metaphysics, especially object-oriented programming), and each thing necessarily corresponds to an idea. The order and connection of ideas are the same as the order and connection of things, and a true idea must correspond to its object. People have various erroneous ideas and cannot recognize necessity because they lack reason and are deceived by instinct
(this part is brilliant, I recommend one of my favourite novels, “Of Human Bondage”). Human ideas are divided into three types according to their source: opinion, reason, and intuition. The first type comes from the crude cognition of the senses, lacks value, and all kinds of erroneous understandings stem from this. The latter two can both achieve the true idea of the essence of substance.
According to Spinoza’s determinism, the world is unique and necessary, and a true idea corresponding to a thing is singular. All people, as long as they have enough reason, will necessarily recognize the same true idea. Moreover, humans do not possess free will; true freedom lies in recognizing and obeying necessity, thereby obtaining rational true knowledge. So, according to his view, if your module does not match the one developed by a programmer in the Amazon rainforest, it must be because one of you lacks reason and is enslaved by instinct, unable to generate a true idea… or perhaps both of you are.
In his “Critique of Pure Reason,” Kant argued that correct understanding of objective things comes from a priori analytic judgments or a priori synthetic judgments. A priori means innate; Kant believed that humans are endowed with the abilities of categorization, analysis, reasoning, and logic from birth. These abilities are not acquired later and therefore do not change with different growth environments. In other words, if a programmer surviving on a deserted island and you analyse or synthesise a thing, the conclusions should be the same, and this conclusion should be correct and unique. So why do people have diverse opinions on things? It is because they are still using a posteriori synthetic judgments. A posteriori judgments are acquired, relying on sensory experience, which is accidental and unreliable, and thus not truth, but merely opinions or viewpoints. This story tells us to use rational analysis more in development and rely less on feelings, so your module can match with others.
The above thinkers are all rationalists, and their conclusions are consistent: correct cognition (truth) exists and is unique, and if pursued, the result will inevitably be the same. The key issue is how to obtain the correct understanding.
Personally, I hold an empiricist attitude. I believe that humans are born knowing nothing and do not possess innate identical cognition. Humans are essentially a sum of experiences and memories, whether these experiences and memories come from the environment or are acquired through education. Therefore, different people may not have the same or similar understanding of the same thing. However, the thing itself is objective and does not change with human opinions. Therefore, the correct understanding of a thing is universal and unique, applicable everywhere, and in this regard, I agree with the aforementioned thinkers. However, since our starting point for cognition can only be sensory experience, it is inevitably incomplete, and we find it challenging to possess pure reason. Thus, truth is difficult to attain, and we always maintain a distance from it, whether close or far. Consequently, different understandings are bound to be more correct, less correct, or all incorrect, each with its unique mistakes. So how can we judge the superiority of different understandings? Only by relying on logic and empirical evidence.
Does this mean that due to differences in experience and memory, it is almost impossible for different people to reach a similar concept? Actually, no. Precisely because humans are collections of experiences, similar or identical experiences and memories carry similar or identical cognitions. In other words, the more similar the experiences people have acquired, the closer their understanding of the same thing will be. This is the foundation of Eight. Therefore, I used similar
rather than identical
in my earlier question because our concept only needs to be similar to facilitate communication and collaboration. As we interact with the world and encounter various people and events, we find some conversations enjoyable and others difficult. We can always achieve more resonance with those who share similar language, culture, beliefs, historical memories, educational backgrounds, and growth environments, understanding their thoughts, knowing their needs, and maintaining tacit understanding without complex mutual notifications. These similar-concepts are the gift of experience and memory. We do not need to be completely identical.
Similarly, system designers, as people who live by coding, have accumulated many shared experiences and memories throughout their long careers and in facing various challenges. Therefore, when they face the same coding problem and are required to use the same set of interfaces, their thinking will naturally converge. For example, for a car, if required to provide an interface in the form of k-v, both the programmer from Amazon and the partner from Mauritius will naturally think of the following structure:
const car = {type:"byd", model:"Han", color:"black"};
The difference lies in the slight variations in the attributes they provide, the naming of keys, and possibly other minor differences. These can be adjusted and adapted at runtime. Therefore, what we should be concerned about is an inexperienced outsider suddenly throwing a bomb at us. But how can we determine who is an inexperienced outsider? This is left to logic and practical proof (commonly known as run me the code
).
Thus, we have a positive answer to whether we can reach similar concepts. Next, we address the issue of combining subjective and objective aspects. All the aforementioned discussions on understanding emphasize the need for correct methods of understanding, but what exactly constitutes correct understanding? As developers, how do we distinguish the problems we face, which are the substances and which are the connections? What do these connections refer to, and how should they be represented? When we start from the self
, the consensus we achieve is merely similar
. How should we adjust to merge these harmonious but different modules into one system? These are essentially methodological issues. Compared to the previous two questions, methodological concerns are more specific and practical.
So, the discussion of principles ends here, and we will now look at something specific: Eight. Because Eight itself is a methodology.
Eight’s Similar-Concepts Interfaces
In Eight’s worldview, the world is composed of things
, which have two parts: attributes representing their characteristics and behaviours representing their actions. Thus, Eight divides the similar-concepts interfaces into two families, respectively for operating attributes and behaviours. The interface family oriented towards attributes is called Resource
, representing the static part of things; the interface family oriented towards behaviours is called Processor
, representing the dynamic part of things, and these two parts form intricate connections
. Eight believes that the operation of any system results from processes acting on resources, with things influencing each other’s static resources through dynamic processes, thereby forming the system.
Eight’s Processor family has three interfaces, defined as follows:
public interface IProcessor<T,R> {
public R process(T object);
}
public interface IBiProcessor<K, V, R> {
public R perform(K first, V second);
}
public interface ITriProcessor<T, K, V, R> {
public R operate(T first, K second, V third);
}
The Resource family is similar to a map structure, consisting of a combination and derivation of a set of basic interfaces. Defined as follows:
public interface IInputResource<K, V> {
public V find(K ... paras);
}
public interface IOutputResource<K, V> {
public <P> P store(V value, K ... paras);
public <P> P discard(K ... paras);
public <P> P empty(K ... paras);
}
public interface IListable<K, V> {
public Collection<K[]> keys(K ... paras);
public Map<K[], V> all(K ... paras);
}
public interface IResource<K, V> extends IInputResource<K, V>, IOutputResource<K, V> {}
public interface IReadonlyListable<K, V> extends IInputResource<K, V>, IListable<K, V> {
public interface IListableResource<K, V> extends IResource<K, V>, IReadonlyListable<K, V> {}
public interface ITransaction<K, V, U extends IResource<K, V>, R> {
public R execute(IProcessor<U, R> processor);
}
public interface ITransactionResource<K, V, U extends IResource<K, V>, R> extends IResource<K, V>, ITransaction<K, V, U, R> {}
public interface IListableTransaction<K, V, U extends IResource<K, V>, R> extends IListableResource<K, V>, ITransactionResource<K, V, U, R> {}
Specifically, to provide more comprehensive completeness to deal with rare cases unsuitable for the resource
and process
model, a set of universal supplementary interfaces is also provided (note the strict control of usage scope
). The supplementary model views everything as a combination of names
, where each name
represents a resource
or process
, forming a part of the thing
. This part can be obtained on the thing
by name, and these resource
or process
can operate on the thing
, and they themselves may also be extendable things
. As shown:
public interface IExtendable<M> {
public Collection<M> methods();
public <N> N extend(M method);
}
public interface IThing {
public <L> L present(Class<L> clazz);
}
Finally, there is an interface that aggregates all interfaces:
public interface IUniversal <K, V, U extends IListableResource<K, V>, T, R> extends IProcessor<T,R>, IBiProcessor<K, V, R>, ITriProcessor<T, K, V, R>, IListableTransaction<K, V, U, R>, IExtendable<T>, IThing {
public <O> O realObject();
}
Below are explanations of each interface:
Interface Name | Description | Remarks |
---|---|---|
IProcessor | Unary process function | |
IBiProcessor | Binary process function | |
ITriProcessor | Trinary process function | |
IInputResource | Read-only resource | Input parameters are arrays, representing multi-level paths. |
IOutputResource | Write-only resource | |
IListable | Listable resource | |
IResource | Resource composed of read-only and write-only resources, forming a readable and writable resource | |
IReadonlyListable | Listable read-only resource composed of read-only and listable resources | |
IListableResource | Listable read-write resource composed of readable and writable resources and listable resources | |
ITransaction | Transaction interface for resource data access when atomic transactions are required | Needs to implement the R execute(IProcessor<U, R> processor) method, which accepts an IProcessor process. This process takes U extends IResource<K, V> as input, meaning it accepts an IResource<K, V> as a parameter. The passed-in resource should ensure that the processor’s operations on it either all succeed or none are executed. |
ITransactionResource | Read-write transaction resource composed of readable and writable resources and transaction resources | |
IListableTransaction | Listable read-write transaction resource composed of listable read-write resources and transaction resources | |
IExtendable | Extension interface IExtendable, which can be attached to any thing (including resources and processes), adding any operable part to the thing |
|
IThing | The IThing interface is another form of extension, representing a thing that can be any interface’s (resource or process) composite . |
Presented through the present method, showing different aspects of the thing |
IUniversal | Interface composed of all interfaces | The realObject method is used to obtain the thing it proxies |
Below is the lineage diagram of all these interfaces:
In total, there are 15 interfaces and 14 methods, which constitute the entire world of Eight.