
AI has revolutionized the software development industry by fundamentally changing how software is designed, developed, and maintained. It has made a highly positive impact on coding productivity. However, AI adoption also brought several negative effects that are pushing software development to a breaking point. Problems AI Created for Software Engineering Loss of Source Code Control Enormous velocity of code production by AI has a significantly negative side-effect: software developers are getting overloaded with PRs they need to review, understand and approve. However, developers experience a huge pressure from the management demanding manifold performance gains to justify implementation of AI in an organization. As a result, many PRs are either approved quickly without thorough review, or they are not reviewed at all and approved automatically. The biggest problem of such approach is a snowball effect: once review quality start to slip – it is very hard to get it back because it would require developers to re-read source code to understand the current state of the codebase. Developers will not be able to fully understand impact of new incoming changes without clear picture of the current codebase. On the other hand, they are under pressure to deliver productivity gains while re-reading all code would take significant time developers just do not have. So, nobody does it and once review quality starts slipping, there is no way back and the team loses control over source code. As a result, the team understands its own code less and less with every AI-produced change. At the end, only catastrophic incident on production might wake up the management to the fact that the working knowledge of the source code is gone. AI Fails on Complex Requirements AI code production starts with specification. Several sentences of a text prompt will be enough for case of a simple application. However, anything more complex would require prepared specification document. Creation of such document is not easy, and it requires special skills. However, let’s assume we have a complete document fully describing what we want in unambiguous way. Would it be enough for AI to produce code exactly to supplied specification? The answer is – it depends on size and complexity of specifications. The more complex and larger the spec is – the more deviations and hallucinations AI makes when generating the code. Also, there is a phenomenon formally known as the "Lost in the Middle" effect. AI models have a strong positional bias, meaning their performance follows a U-shaped curve: they are highly accurate when relevant information is placed at the very beginning or end of a document, but struggle significantly with the middle. Unfortunately, this is a very nature of the current LLM models and there is not much we can do to change it. At some level of specifications complexity, the quality of generated code becomes so poor that it is not worth time to do post-generation fixes. Therefore, it becomes faster and easier to throw everything out and re-write manually. So, what is the solution? It is simple – generating only application scaffolding and/or base-level software primitives easily explainable to AI, while the rest continues to be completed incrementally, one prompt at a time. However, that approach defeats the whole purpose of AI. Developers are forced back to iterative AI-assisted text coding, as AI cannot follow spec without human guidance. AI Brought Us Security Armageddon AI reached level of sophistication when it can find vulnerabilities in open-source code in seconds, giving everyone an ability to easily find vulnerabilities and exploit them, whereas before it required high-level experts to do that. This situation becomes even more critical if we consider the fact that modern AI models are stochastic, meaning that if one person run model and found some bugs in certain codebase, another person running same model for the same codebase does not necessarily find same bugs (or any bugs at all). It means someone can accidentally find serious zero-day bugs no one else was able to detect. The first solution is closing open-source projects. That might help for some time, but there is another way to search for vulnerabilities - dynamic probing of endpoints. AI can tremendously help to compose special requests for server probing. On the other hand, open-source brought significant benefits to software development community. Closing it does not solve the problem fundamentally while it would kill all benefits. Another solution is speeding up process of software patching. This will quickly become a race between velocity of vulnerability discovery and the speed of software patching. The most likely outcome is that vulnerabilities will be discovered much faster than patching of corresponding bugs, because AI models are constantly improving while patching process has its limits. These limits are imposed by fundamental flaws in both phases of patching – detection and resolution. Detection is mostly based on analyzing production logs. However, the information gets into the logs from the code and developers must explicitly add these log statements into the code. Today, it is a common practice to have logs statements added to code frequently from the beginning, but they are added only in specific places where developers see their importance. However, many other places are not covered. It means that detection does not see anything not present in logs because log statements were not added for such cases in source code. That makes detection blind in many aspects. To start logging new information, the process assumes full redeployment after adding more log statements. If there is still more logging needed – another redeployment is needed, etc. This makes the process of adding new logs long and complex. This is especially critical for debugging process that often involves an exhausting and repeating cycle of adding/changing logs followed by redeployment when investigating a problem. Another aspect of patching is resolution – preparing and applying the fix. The first question is how the vulnerable system is going to work while the team is waiting for the patch. Does it need to be brought down or kept online in hope nobody will not exploit this vulnerability while the fix is on its way? In first case, the business might suffer due to limited or disabled functionality. The second case involves risks that exploiting the vulnerability by a malicious third-party might result in real data theft or loss. Another possible solution is hardening security of open-source libraries. For example, IBM and Red Hat announced Project Lightwell and committed $5B to secure software supply chain. That will improve their protection. However, will they be able to match the speed of vulnerability discoveries and the fact that certain zero-day bugs might be accidentally found just one time during “lucky” AI code analysis rerun nobody else can rediscover? Also, what about mostly domain-specific private and limited distribution libraries? What about vulnerabilities in business logic layer on top of common libraries, especially closed-source code? There are many questions, and Project Lightwell does not provide answers to many of them. The conclusion of this analysis is that we need more fundamental and long-term solution to these problems brought by AI. \ Root Causes of These Problems Before we dive into the solution, let’s try to identify root causes of the specified problems. Problems of source code control loss and AI failure to follow complex requirements have the same root cause – the human limits in comprehension of text information. In first case, developers are overloaded with huge amount of text code they need to review. In second case, they need to come back to text-based coding due to LLM-based AI flaws in understanding documents and following its guidelines. The root cause of limited detection and resolution capabilities is low granularity of modern software. It means that we deploy software in large modules: adding new logs and replacing compromised code both require redeployment of the whole module. There are attempts to increase granularity of software – for example, via plugins or microservices. However, all attempts to split software to smaller components resulted in sharp increase in overall complexity of managing the entangled graph of component interactions. For example, many companies concluded that microservice architecture is too complex for their projects that might easily be re-implemented as a monolith as a much cheaper alternative in terms of software complexity management. Why do we need high granularity? This is because we can get direct access to a single small component that we can fix, update, isolate, measure or debug in-place at runtime, instead of going full long cycle of adding logs or updating a compromised component followed by redeploying the whole module. \ \ Why Visual Programming Is the Solution There is a technology that provides both the best human comprehension and maximum granularity – visual programming. Visual representation is a clear winner comparing to text and that makes logic perception much easier for human brain. Maximum granularity provides multiple benefits: In-place component fixing, update or isolation at runtime – every visual block is directly accessible during execution, meaning a compromised or underperforming component can be fixed, updated, or isolated in production without recompilation or redeployment. Dynamic telemetry collection by connecting to inputs/outputs in real-time without the need to add logs into source code and redeployment – any block can be probed directly at runtime by connecting to its inputs and outputs, eliminating the need to add log statements to source code and redeploy just to start collecting new diagnostic data. Painless debugging by direct probing of any component at runtime – debugging becomes trivial as every block can be interrogated directly at runtime, replacing the exhausting cycle of adding logs, redeploying, and inferring what happened with direct observation of what is actually going on. Some of these benefits allow almost instant reaction to attempts to breach security, especially if application self-healing engine is involved in the process of collecting telemetry and reaction to application security breaches. In fact, visual programming is the perfect match with self-healing engine that can react on threats instantly. Text-based application forces self-healing engine to wait for a full cycle of source code fix and CI/CD redeployment, making it impossible to react to threats in real time. The next question is what specific visual programming language we can use. There is the wide selection of them: LabVIEW, Node RED, Simulink. However, all of them tend to shift in one direction: they are either simple but general-purpose or sophisticated but domain specific. We need a visual language that is both general-purpose and sophisticated, because this is the quality of all text-based language we intend to replace with visual diagrams. There is one such recently introduced visual language: Pipe (see pipelang.com ). This is general-purpose visual programming language designed specifically to be able to replace text-based code. Why Pipe Is The Best Candidate Visual programming language Pipe implements multiple unique concepts that makes it a pretty sophisticated language. I will mention just some of them because they are relevant to the topic of this article. Execution nodes of Pipe are called runlets, and each of them may contain other runlets inside. As a result, runlets compose tree-like structure with leaves containing text-based code. Such structure is ideal for gradual migration from text-based code to visual diagrams: code gradually recedes in tree leaves while Pipe runlet structure grows upwards, absorbing more and more logic from text-based code. Eventually, leaf nodes will contain only a thin layer of text code handling external intercommunication, while all business logic lives in the visual structure above. Pipe provides full formal API for integration with text-based languages as a part of language specification, making it possible to integrate Pipe with almost any text-based programming language. Another relevant Pipe feature is designed to solve very painful problem of reconciling interfaces between different components. Pipe solution is providing binding model based on concept of domain – tree-like data structures similar to JSON. When output of one Pipe component is connected to input of another one, output and input generally have different assigned domains. To reconcile them, only data between domain tree nodes with common paths in both domains are transferred – this process is called domain overlap. Domain tree nodes on receiving end without match in domain from sending side take explicit or implicit default value. Overlap represents the case of extremely loose coupling while supporting data type safety: matching domain nodes must have compatible data types for domain connectivity to be valid. Together, runlets and domains make Pipe uniquely suited for the post-AI era: runlets provide the granularity needed for runtime observability and surgical fixes, while domains ensure that the connections between components remain type-safe, auditable, and comprehensible to human reviewers. Why High Granularity Works in Pipe But Not in Text Code The obvious question is: if high granularity is so valuable, why did microservices and plugin architectures fail to deliver it without massive management overhead? There are three reasons why Pipe is different. The first is topology. Microservices create an arbitrary dependency graph – any service can call any other, and as the system grows, this graph becomes impossible to reason about. Teams that went all-in on microservices often found themselves building expensive internal platforms just to manage the complexity, or quietly migrating back to monoliths. Pipe's runlet hierarchy is a tree between workflows – each composite runlet contains only its direct children, and you always work at one level at a time. The structure above and below stays out of the way. But that raises an obvious follow-up: what about inside a single workflow? Connections between components within a diagram can form an arbitrary graph – and that is true. The difference is that you can see it. Every connection is drawn on the diagram in front of you. In a microservice system, understanding which services are talking to which requires log tracing, dependency maps, and usually a dedicated observability platform. In Pipe , the complexity is visible and bounded within a single diagram. You are never looking at the whole system at once – just the level you are working on. The third is coupling. Classical APIs require both sides to agree on a shared contract. Change one side and you risk breaking every consumer. Pipe's domain overlap works differently – each component defines its own domain independently, and data flows only where those domains share compatible paths. Components can evolve without coordination. That is a qualitatively different kind of loose coupling, not just a variation on what microservices already do. Conclusion AI brought not only positive changes to software development industry, but also many new challenges. Their severity requires rethinking the whole approach of software development. Problem analysis points to visual programming as the best long-term solution. Visual programming language Pipe provides the best set of features for transitioning to new post-AI world. The GUI revolution made computers accessible to everyone. Visual programming is the second half of that revolution – making the act of programming itself comprehensible, auditable, and secure by design. Pipe is being built to be that language. Learn more at pipelang.com . :::tip This article is published under HackerNoon's Business Blogging program. ::: \
View original source — Hacker Noon ↗



