If you’re building software, you’re likely already using AI in some manner, even if just to autocomplete your code. If you’re not, there is a good chance someone on your team is. Like it or not, leveraging AI in software development will only become more prevalent as the quality and efficiency of AI improves and as more AI-integrated tools are created that support software development.
However, at least right now, using AI to write software is fraught with challenges. So far, it appears unlikely that AI will replace experienced software developers anytime soon. The complexity of most software projects is just too high for AI to navigate effectively or for product owners to feel confident with the results.
A fundamental reason why AI struggles to navigate software as it becomes more complex is context. As a software developer, you (or an AI agent) need to know a lot about how a complex system like a software project works in order to make appropriate changes successfully.
One strategy to improve this dynamic for AI is to increase the amount of context that the model can consume (or be trained on) in order to improve how the AI can contribute to a given project.
While this strategy seems plausible, such a solution diverges from how humans, as intelligent beings, handle complexity most effectively. Cramming as much raw information into your head as possible is a strategy one can attempt, but we often leverage more sophisticated methods. We build tools and devise abstractions to help us better think about and interact with complexity, which reduces the volume of information we have to keep in mind at any given moment.
Maybe we will develop AI that has such god-like abilities that tools and information abstractions will not be required for it to solve complex problems, but this seems unlikely. Even if it becomes possible for an AI to solve extremely complex problems on its own, doing so with relevant tools and abstractions would likely be far more efficient and less error-prone. Today with AI, we see this playing out already; as the amount of context grows, the AI’s speed of response slows down and the likelihood of an error increases.
If you want to explore other ways to approach complexity without simply relying on larger amounts of information, then we don’t have much of a choice than figure out how to work with less information. We need to be able to isolate specific aspects within a complex environment (in software, this would be parts of the overall application) so that we can think about, collaborate around, and iterate on them in a more focused and efficient manner.
As noted above, though, isolation lacks context, so you can’t just isolate pieces of information and act on them independently. You can’t effectively edit a paragraph in a book if you have no context about the story.
This is where abstraction becomes helpful. Abstraction allows us to take in a lot of information and boil it down, while retaining important aspects. A perfect abstraction isn't one that preserves all context, but one that finds a way to capture exactly what we need for the problem at hand, while discarding everything else. With such an abstraction, we can make faster and better decisions, while using less effort and energy.
One aspect of our exploration at CodeYam is how to make working with AI on software development more effective and powerful by using isolation and abstraction.
Any time you’re dealing with something complex, being able to deconstruct it into smaller pieces can be very helpful. This allows you to think about, communicate about, and iterate more easily. This is why we break software into files and functions and other small “puzzle pieces” that can be explicitly reasoned about more effectively.
CodeYam uses static code analysis and AI to analyze every function in a software application from multiple perspectives. We explore abstractions ranging from descriptions of what a given function does to the structure of the data that passes through the function and how that data can be modified to make the function behave differently. We further abstract the data that will trigger different paths through the function into instructions that isolate the key parts of the data required for each pathway.
We can then combine these abstractions together within a dependency tree (the functions that are imported to support more complex functions) to gain a clearer understanding of what a given function is doing and how functions connect together within the software application.
In this way, we can look at isolated aspects of an application (i.e. any given function) and have a better sense as to its purpose with the larger application and how other functions within the application impact this function. All of this information makes it easier to understand the function and its role in the application without having to hold the whole application in mind at one time.
Right now, we do all of this in order to create simulations of the application at every level, ranging from low-level foundational functions to the higher level functions that provide end-user experiences. These simulations are isolated parts of the application running with relevant data passed in to them and then captured so that you can see and interact with the result.
These simulations create a great way to think about, collaborate around, and iterate on every aspect of a software application. Today, this makes it easier to collaborate on software development and products with human colleagues. In the future, this will also make collaborating with AI agents as you seek to evolve and improve the application easier as well.
Without these simulations, we’re left with either code or the application itself. Code always requires significant effort to read and reason about even if you’re an experienced developer. If you’re a non-technical teammate the code offers no insight at all. On the other hand, the application itself requires clicking around and finding ways to generate and feed in appropriate data to get the application in the state you are interested in testing or viewing. This can be incredibly effortful (e.g. testing a fintech app with realistic, but not real, financial information for a fake user or having to manage dozens of fake user accounts that you have to log in/out of to view the app from different user states).
CodeYam’s simulations, which by default are automatically generated as code changes come in (but can be edited with AI or manually if desired), eliminate the time and effort required to test different product and user experiences. This makes it possible for any teammates involved in the software development life cycle to understand how the application is evolving, catch issues more quickly, and communicate and collaborate more effectively.
These simulations, which leverage isolation and abstraction, are just one strategy for both using and collaborating with AI around software development. Without such tools, though, our ability to understand how our software is evolving with a high level of confidence is reduced significantly. As AI becomes more involved in software development, it becomes even more critical to have tools that help us ensure that the software we are building not only doesn’t break but also behaves in ways that the end user appreciates.
CodeYam is a software simulator that helps teams develop software more effectively, generating simulations for all functions and changes to functions as they come in. The simulations provide test coverage, help you understand how an application is evolving, and can be used for documentation, demos, and general collaboration. If you are interested in learning more please reach out at hello@codeyam.com or sign up for the waitlist.