Decoding the Soul of Software: A Guide to Understanding Code's Dual Purpose
As we increasingly delegate the writing of code to AI agents, a pressing question emerges: Will source code even exist in the future? To grapple with this, we must first understand what code really is. Unmesh Joshi offers a powerful lens: code serves two intertwined purposes—it provides instructions to a machine and it models the problem domain conceptually. This guide will help you appreciate this duality and apply it to your work with modern AI tools. By the end, you'll see why code is not just a technical artifact but a profound thinking tool that shapes how we solve problems.
What You Need
- A computer or device with a text editor or IDE installed (optional but helpful for experimentation).
- Basic familiarity with at least one programming language (e.g., Python, JavaScript). No expert-level skill required.
- An open mind willing to see code as more than a set of instructions.
- Access to a large language model (LLM) such as ChatGPT, Claude, or GitHub Copilot (optional for Step 4).
Step-by-Step Guide
-
Step 1: Recognize That Code Has Two Distinct but Intertwined Purposes
At first glance, code is simply a series of commands that tell a machine what to do. But this is only half the story. Every line of code also encodes a conceptual model of the problem you're solving—it represents how you think about the domain. For example, when you write a variable named
customerEmail, you're not just storing a string; you're embedding a concept from your business logic. Joshi emphasizes that understanding this duality is critical because it impacts how you design systems and communicate with others (including AI). Take a moment to examine any piece of code you've written. Ask yourself: What real-world concepts does this code represent? How does it shape my mental model of the problem?
Source: martinfowler.com -
Step 2: Build a Vocabulary to Talk to the Machine
Programming languages are not just syntax—they are thinking tools. Each language offers a unique vocabulary and way of structuring thought. For instance, object-oriented languages like Java encourage you to model the world as interacting objects, while functional languages like Haskell shift your mindset toward transformations and purity. To truly master code, you must intentionally learn this vocabulary. Start by studying idioms common in your language of choice. Write small snippets that push against your habitual patterns. The goal is to make the vocabulary second nature so that you can fluently express both instructions and concepts. As Joshi notes, building this vocabulary is vital because it bridges the gap between human intent and machine execution.
-
Step 3: Use Programming Languages as Thinking Tools
Once you have a vocabulary, you can leverage languages to think better. A program is never just a set of instructions; it's an evolving theory of the problem domain. When you refactor code, you're refining your conceptual model. When you write tests, you're formalizing assumptions. This step asks you to consciously treat code as a medium for thought. Try this exercise: pick a small feature you've built and rewrite it in a different paradigm (e.g., convert a loop to recursion, or a class hierarchy to a set of pure functions). Notice how your understanding of the problem shifts. This is the essence of what Joshi calls the “conceptual model” purpose of code. By practicing this, you'll become more adept at both writing clear instructions and designing elegant abstractions.
-
Step 4: Apply This Understanding to Working with Large Language Models
In the age of AI, many developers worry that LLMs make source code obsolete. But Joshi's framework suggests otherwise. When you prompt an LLM to generate code, you are still providing conceptual input—your description of the problem. The code it produces reflects both the machine instructions and the conceptual model you've implied. To work effectively with LLMs, you must become explicit about the conceptual layer. Before asking an AI to write code, write a brief specification that outlines the key concepts and their relationships. Treat the LLM as a partner that helps you materialize your mental model, not as a replacement for understanding. For example, instead of saying “write a function to sort customers,” say “write a function that sorts a list of Customer objects by their last name, preserving the conceptual grouping by city.” This clarity improves the AI's output and helps you maintain control over the dual purpose of the code.
-
Step 5: Envision the Future of Source Code
Will source code survive? According to Joshi, yes—but its role may shift. As AI agents take over the syntactic, instruction-level writing, humans will focus more on the conceptual modeling aspect. Code will become a higher-level representation of intent, perhaps closer to a formal specification. To prepare for this future, practice documenting your conceptual models in a way that can be interpreted by both humans and machines. Use comments not just to explain “how” but “why”. Consider using domain-driven design techniques to make your conceptual model explicit. The bottom line: code's dual nature ensures it remains relevant, as long as we value the link between human understanding and machine capability.
Tips for Mastering Code's Dual Nature
- Always pair technical instruction with conceptual clarity. When you write a comment, state the purpose and the concept, not just the algorithm.
- Refactor your code with both purposes in mind. Is it still easy to understand the domain? If not, restructure.
- Experiment with different languages to expose yourself to diverse conceptual models. Each language teaches you a new way to think.
- When using LLMs, treat the conversation as a dialogue about concepts, not just prompts. Iterate on the conceptual model together with the AI.
- Read code written by others and try to infer the underlying conceptual model. This skill will help you collaborate and learn.
- Don't discard source code even if AI writes it. Keep it as a record of the conceptual decisions you and the AI made.
- Stay curious. The evolution of code is ongoing. Embrace the dual purpose as a compass for navigating the future.
Related Articles
- Maximizing Go Performance Through Stack Allocation
- CommitAI: Your Offline Git Assistant Powered by Gemma 4
- Go 1.26 Arrives: Language Enhancements, Performance Boosts, and Experimental Features
- How to Streamline Development with Structured Prompt-Driven Workflows
- Why JavaScript Date Handling Is Broken and How Temporal Fixes It
- Python Insider Blog Relaunches with Open Source Git-Based Platform
- Go Team Unveils Major Performance Boost: Shift from Heap to Stack Allocations
- The Unchanging Core of Programming and the One Revolution That Changed Everything