Programming as Composition
Ishe Chinyoka
- 5 minutes readTable of Contents
The most important programming lesson may not be writing functions. It may be learning to compose them.
One of the biggest surprises of my journey into programming was discovering that I had been programming long before I knew what a function was.
At first, that sounds absurd.
How can someone program without writing programs?
The answer lies in a different way of seeing the computer.
Most introductions to programming begin with syntax. You learn variables, loops, conditions, functions, and classes. Eventually, you assemble these pieces into a useful application.
The Unix tradition quietly reverses this process.
Instead of beginning with source code, it begins with tools.
Each command already performs one useful task.
Your job is not to build everything from scratch.
Your job is to compose.
Every Tool Is a Callable
Over the years, I began to think of every command-line program—and eventually every graphical application—as though it were a function.
You call it.
It performs a specific task.
It receives input.
It produces output.
It may change something in the world.
Then it disappears.
That description fits a shell command.
It also describes a Python function.
It describes a C function.
It even describes clicking Save in a graphical editor.
Every program is simply another callable.
Once you begin seeing software this way, programming becomes much less mysterious.
A Computer Is Already Running Programs
Imagine watching someone use a computer.
They open a browser.
Download a file.
Edit it.
Convert it to PDF.
Upload it somewhere.
What are they really doing?
From one perspective, they are simply using applications.
From another, they are executing a program.
The operating system becomes the runtime.
The user becomes the orchestrator.
The applications become functions.
Programming merely automates what the human was already doing manually.
This realization changed how I thought about software.
Instead of asking,
“How do I write a program?”
I started asking,
“How would I perform this task manually?”
The program practically wrote its own outline.
Composition Comes Before Code
Consider this shell pipeline:
grep ERROR server.log | sort | uniq -c | sort -nrNothing here is new.
Every command existed long before this pipeline.
Yet together they produce something none of them could achieve individually.
This is composition.
Programming languages work in exactly the same way.
A Python program rarely performs everything itself.
Instead, it calls libraries.
Libraries call operating system functions.
The operating system calls device drivers.
The processor executes instructions.
Every layer composes the one beneath it.
The shell simply makes this composition visible.
Functions Are People Using Computers
One day another thought occurred to me.
Suppose every function in a program is simply another person sitting at a computer.
One function opens a file.
Another searches it.
Another transforms the results.
Another writes the report.
They communicate by passing information to one another.
That sounds remarkably familiar.
Because it is exactly how we use computers ourselves.
Programming languages merely formalize this cooperation.
Once I began imagining functions as tiny users of the computer, source code became much easier to understand.
I stopped memorizing syntax.
Instead, I asked simple questions.
Who is calling this function?
What information does it receive?
What information does it return?
Does it change anything outside itself?
Does it depend on hidden state?
Those questions reveal far more than syntax ever could.
Side Effects Matter
Thinking in terms of composition also highlights something programmers call side effects.
Some commands simply transform information.
Others permanently change the system.
Consider these examples.
sort names.txtprints sorted text.
Nothing changes.
Now compare it with:
rm names.txtThe command leaves the world different from how it found it.
The distinction is important.
Good programmers—and good shell users—learn to recognize which operations merely compute and which operations modify reality.
Composition is not just about connecting tools.
It is about understanding their consequences.
Pipelines Are Programs in Disguise
This explains why shell pipelines feel so satisfying.
They are not merely sequences of commands.
They are small programs whose source code happens to consist of existing tools.
Every pipe removes another temporary file.
Every filter adds another transformation.
Every redirect defines another destination.
Before long, what began as a handful of commands has become an application.
Perhaps that is why Unix users often smile when someone asks what programming language they should learn.
Many have already written dozens of useful programs without realizing it.
The Difference Is Only Scale
As programs grow larger, nothing fundamentally changes.
The pieces simply become more sophisticated.
Instead of shell commands, you compose functions.
Instead of functions, you compose classes.
Instead of classes, you compose services.
Instead of services, you compose entire systems.
The principle remains unchanged.
Complexity emerges from composition.
Not from complexity itself.
Why This Matters in the Age of AI
Artificial intelligence is remarkably good at generating code.
But even AI writes software by composition.
It calls libraries.
Uses existing APIs.
Connects functions together.
Builds on previous work.
The human contribution remains the same as it has always been.
Recognizing what should be composed.
Knowing where the boundaries belong.
Understanding which pieces already exist and which ones still need to be created.
That is not merely a programming skill.
It is a way of thinking.
The Textsmith’s View of Programming
Perhaps this is why shell scripting feels like such a natural gateway into programming.
It teaches composition before syntax.
It teaches problem-solving before language features.
It teaches that software is not magic.
It is simply a conversation among many small pieces, each doing one thing well.
The textsmith already understands composition.
A paragraph is composed of sentences.
A document is composed of paragraphs.
A website is composed of pages.
A pipeline is composed of commands.
A program is composed of functions.
The patterns never really change.
Only the scale does.
Reflection
Programming is often presented as the art of writing code. I have come to think of it differently. Programming is the art of composition. Whether we compose words into paragraphs, commands into pipelines, or functions into applications, we are practicing the same craft: taking simple, understandable pieces and arranging them into something that is greater than the sum of its parts. Perhaps that is why the journey from textsmith to programmer feels so natural. Both are, at heart, composers.