Why learn this text?
one about easy methods to construction your prompts to allow your AI agent to carry out magic. There are already a sea of articles that goes into element about what construction to make use of and when so there’s no want for one more.
As a substitute, this text is one out of a sequence of articles which might be about easy methods to maintain your self, the coder, related within the fashionable AI coding ecosystem.
It’s about studying the methods that allow you to excel in utilising coding brokers higher than those that blindly hit tab or copy-paste.
We’ll go into the ideas from present software program engineering practices that try to be conscious of, and go into why these ideas are related, significantly now.
- By studying this sequence, it’s best to have a good suggestion of what frequent pitfalls to search for in auto-generated code, and know easy methods to information a coding assistant to create manufacturing grade code that’s maintainable and extensible.
- This text is most related for budding programmers, graduates, and professionals from different technical industries that wish to degree up their coding experience.
What we are going to cowl not solely makes you higher at utilizing coding assistants but in addition higher coders normally.
The Core Ideas
The excessive degree ideas we’ll cowl are the next:
- Code Smells
- Abstraction
- Design Patterns
In essence, there’s nothing new about them. To seasoned builders, they’re second nature, drilled into their brains by means of years of PR critiques and debugging. You ultimately attain a degree the place you instinctively react to code that “feels” like future ache.
And now, they’re maybe extra related than ever since coding assistants have turn out to be a vital a part of any builders’ expertise, be it juniors to seniors.
Why?
As a result of the handbook labor of writing code has been offloaded. The first duty for any developer has now shifted from writing code to reviewing it. Everybody has successfully turn out to be a senior developer guiding a junior (the coding assistant).
So, it’s turn out to be important for even junior software program practitioners to have the ability to ‘overview’ code. However the ones who will thrive in in the present day’s business are those with the foresight of a senior developer.
This is the reason we will probably be overlaying the above ideas in order that within the very very least, you possibly can inform your coding assistant to take them under consideration, even in the event you your self don’t precisely know what you’re searching for.
So, introductions are actually accomplished. Let’s get straight into our first subject: Code smells.
Code Smells
What’s a code scent?
I discover it a really aptly named time period – it’s the equal of bitter smelling milk indicating to you that it’s a foul thought to drink it.
For many years, builders have learnt by means of trial and error what sort of code works long-term. “Smelly” code are brittle, vulnerable to hidden bugs, and tough for a human or AI agent to know precisely what’s occurring.
Thus it’s typically very helpful for builders to find out about code smells and easy methods to detect them.
Helpful hyperlinks for studying extra about code smells:
Now, having used coding brokers to construct all the pieces from skilled ML pipelines for my 9-5 job to whole cell apps in languages I’d by no means touched earlier than for my side-projects, I’ve recognized two typical “smells” that emerge if you turn out to be over-reliant in your coding assistant:
- Divergent Change
- Speculative Generality
Let’s undergo what they’re, the dangers concerned, and an instance of easy methods to repair it.
Divergent Change
Divergent change is when a single module or class is doing too many issues directly. The aim of the code has ‘diverged’ into many various instructions and so somewhat than being targeted on being good at one activity (Single Accountability Precept), it’s making an attempt to do all the pieces.
This ends in a painful state of affairs the place this code is all the time breaking and thus requires fixing for numerous unbiased causes.
When does it occur with AI?
When the developer isn’t engaged with the codebase and blindly accepts the Agent output, you might be doubly vulnerable to this.
Sure, you could have accomplished all the right issues and made a properly structured immediate that adheres to the newest is in immediate engineering.
However normally, in the event you ask it to “add performance to deal with X,” the agent will normally do precisely as it’s advised and cram code into your present class, particularly when the prevailing codebase is already very difficult.
It’s in the end as much as you to take into consideration the position, duty and supposed utilization of the code to provide you with a holistic method. In any other case, you’re very prone to find yourself with smelly code.
Instance — ML Engineering
Beneath, now we have a ModelPipeline class from which you may get whiffs of future extensibility points.
class ModelPipeline:
def __init__(self, data_path):
self.data_path = data_path
def load_from_s3(self):
print(f"Connecting to S3 to get {self.data_path}")
return "raw_data"
def clean_txn_data(self, information):
print("Cleansing particular transaction JSON format")
return "cleaned_data"
def train_xgboost(self, information):
print("Operating XGBoost coach")
return "mannequin"
A fast warning:
We are able to’t speak in absolutes and say this code is dangerous only for the sake of it.
It all the time is dependent upon the broader context of how code is used. For a easy codebase that isn’t anticipated to develop in scope, the beneath is completely positive.
Additionally word:
It’s a contrived and easy instance as an instance the idea.
Don’t hassle giving this to an agent to show it could possibly work out that is smelly with out being advised so. The purpose is for you to recognise the scent earlier than the agent makes it worse.
So, what are issues that ought to be going by means of your head if you have a look at this code?
- Information retrieval: What occurs once we begin having multiple information supply, like Bigquery tables, native databases, or Azure blobs? How possible is that this to occur?
- Information Engineering: If the upstream information adjustments or downstream modelling adjustments, this can even want to alter.
- Modelling: If we use totally different fashions,
LightGBMor some Neural Internet, the upstream modelling wants to alter.
It’s best to discover that by coupling Platform, Information engineering, and ML engineering issues right into a single place, we’ve tripled the explanation for this code to be modified – i.e. code that’s starting to scent like ‘divergent change‘.
Why is that this a potential drawback?
- Operational threat: Each edit runs the chance of introducing a bug, be it human or AI. By having this class put on three totally different hats, you’ve tripled the chance of this breaking, since there’s 3 times as extra causes for this code to alter.
- AI Agent Context Air pollution: The Agent sees the cleansing and coaching code as a part of the identical drawback. For instance, it’s extra prone to change the coaching and information loading logic to accommodate a change within the information engineering, despite the fact that it was pointless. In the end, this will increase the ‘divergent change’ code scent.
- Threat is magnified by AI: An agent can rewrite a whole bunch of strains of code in a second. If these strains symbolize three totally different disciplines, the agent has simply tripled the possibility of introducing a bug that your unit exams may not catch.
Learn how to repair it?
The dangers outlined above ought to provide you with some concepts about easy methods to refactor this code.
One potential method is as beneath:
class S3DataLoader:
"""Handles solely Infrastructure issues."""
def __init__(self, data_path):
self.data_path = data_path
def load(self):
print(f"Connecting to S3 to get {self.data_path}")
return "raw_data"
class TransactionsCleaner:
"""Handles solely Information Area/Schema issues."""
def clear(self, information):
print("Cleansing particular transaction JSON format")
return "cleaned_data"
class XGBoostTrainer:
"""Handles solely ML/Analysis issues."""
def practice(self, information):
print("Operating XGBoost coach")
return "mannequin"
class ModelPipeline:
"""The Orchestrator: It is aware of 'what' to do, however not 'how' to do it."""
def __init__(self, loader, cleaner, coach):
self.loader = loader
self.cleaner = cleaner
self.coach = coach
def run(self):
information = self.loader.load()
cleaned = self.cleaner.clear(information)
return self.coach.practice(cleaned)
Previously, the mannequin pipeline’s duty was to deal with your entire DS stack.
Now, its duty is to orchestrate the totally different modelling levels, while the complexities of every stage is cleanly separated into their very own respective courses.
What does this obtain?
1. Minimised Operational Threat: Now, issues are decoupled and duties are stark clear. You may refactor your information loading logic with confidence that the ML coaching code stays untouched. So long as the inputs and outputs (the “contracts”) keep the identical, the chance of impacting something downstream is lowered.
2. Testable Code: It’s considerably simpler to put in writing unit exams because the scope of testing is smaller and nicely outlined.
3. Lego-brick Flexibility: The structure is now open for extension. Have to migrate from S3 to Azure? Merely drop in an AzureBlobLoader. Wish to experiment with LightGBM? Swap the coach.
You in the end find yourself with code that’s extra dependable, readable, and maintainable for each you and the AI agent. Should you don’t intervene, it’s possible this class turn out to be larger, broader, and flakier and find yourself being an operational nightmare.
Speculative Generality

While ‘Divergent Change‘ happens most frequently in an already massive and sophisticated codebase, ‘Speculative Generality‘ appears to happen if you begin out creating a brand new mission.
This code scent is when the developer tries to future-proof a mission by guessing how issues will pan out, leading to pointless performance that solely will increase complexity.
We’ve all been there:
“I’ll make this mannequin coaching pipeline help all types of fashions, cross validation and hyperparameter tuning strategies, and ensure there’s human-in-the-loop suggestions for mannequin choice in order that we are able to use this for all of our coaching sooner or later!”
solely to seek out that…
- It’s a monster of a job,
- code seems flaky,
- you spend an excessive amount of time on it
- while you’ve not been in a position to construct out the easy LightGBM classification mannequin that you simply wanted within the first place.
When AI Brokers are vulnerable to this scent
I’ve discovered that the newest, excessive performing coding brokers are most vulnerable to this scent. Couple a strong agent with a obscure immediate, and also you rapidly find yourself with too many modules and a whole bunch of strains of recent code.
Maybe each line is pure gold and it’s precisely what you want. After I skilled one thing like this lately, the code actually appeared to make sense to me at first.
However I ended up rejecting all of it. Why?
As a result of the agent was making design selections for a future I hadn’t even mapped out but. It felt like I used to be shedding management of my very own codebase, and that it will turn out to be an actual ache to undo sooner or later if the necessity arises.
The Key Precept: Develop your codebase organically
The mantra to recollect when reviewing AI output is “YAGNI” (You ain’t gonna want it). It’s a precept in software program improvement that means it’s best to solely implement the code you want, not the code you foresee.
Begin with the best factor that works. Then, iterate on it.
It is a extra pure, natural manner of rising your codebase that will get issues accomplished, while additionally being lean, easy, and fewer vulnerable to bugs.
Revisiting our examples
We beforehand checked out refactoring Instance 1 (The “Do-It-All” class) into Instance 2 (The Orchestrator) to show how the unique ModelPipeline code was smelly.
It wanted to be refactored as a result of it was topic to too many adjustments for too many unbiased causes, and in its present state the code was too brittle to take care of successfully.
Instance 1
class ModelPipeline:
def __init__(self, data_path):
self.data_path = data_path
def load_from_s3(self):
print(f"Connecting to S3 to get {self.data_path}")
return "raw_data"
def clean_txn_data(self, information):
print("Cleansing particular transaction JSON format")
return "cleaned_data"
def train_xgboost(self, information):
print("Operating XGBoost coach")
return "mannequin"
Instance 2
class S3DataLoader:
"""Handles solely Infrastructure issues."""
def __init__(self, data_path):
self.data_path = data_path
def load(self):
print(f"Connecting to S3 to get {self.data_path}")
return "raw_data"
class TransactionsCleaner:
"""Handles solely Information Area/Schema issues."""
def clear(self, information):
print("Cleansing particular transaction JSON format")
return "cleaned_data"
class XGBoostTrainer:
"""Handles solely ML/Analysis issues."""
def practice(self, information):
print("Operating XGBoost coach")
return "mannequin"
class ModelPipeline:
"""The Orchestrator: It is aware of 'what' to do, however not 'how' to do it."""
def __init__(self, loader, cleaner, coach):
self.loader = loader
self.cleaner = cleaner
self.coach = coach
def run(self):
information = self.loader.load()
cleaned = self.cleaner.clear(information)
return self.coach.practice(cleaned)
Beforehand, we implicitly assumed that this was manufacturing grade code that was topic to the varied upkeep adjustments/function additions which might be steadily made for such code. In such context, the ‘Divergent Change’ code scent was related.
However what if this was code for a brand new product MVP or R&D? Would the identical ‘Divergent Change’ code-smell apply on this context?

In such a situation, choosing instance 2 may very well be the smellier selection.
If the scope of the mission is to contemplate one information supply, or one mannequin, constructing three separate courses and an orchestrator could depend as ‘pre-solving’ issues you don’t but have.
Thus, in MVP/R&D conditions the place detailed deployment concerns are unknown and there are particular enter information/output mannequin necessities, instance 1 might be extra applicable.
The Overarching Lesson
What these two code smells reveal is that software program engineering isn’t about “appropriate” code. It’s about context.
A coding agent can write excellent Python in each perform and syntax, nevertheless it doesn’t know your whole enterprise context. It doesn’t know if the script it’s writing is a throwaway experiment or the spine of a multi-million greenback manufacturing pipeline revamp.
Effectivity tradeoffs
You might argue that we are able to merely feed the AI each little element of enterprise context, from the conferences you’ve needed to the tea-break chats you had with a fellow colleague. However in apply, that isn’t scalable.
If you need to spend half and hour writing a “context memo” simply to get a clear 50-line perform, have you ever actually gained effectivity? Or have you ever simply remodeled the handbook labor of writing code into that of writing prompts?
What makes you stand out from the remaining
Within the age of AI, your worth as a knowledge scientist has essentially modified. The handbook labour of writing code has now been eliminated. Brokers will deal with the boilerplating, the formatting, and unit testing.
So, to make your self stand out from the opposite information scientists who’re blindly copy pasting code, that you must have the structural instinct to information a coding agent in a path that’s related to your distinctive state of affairs. This ends in higher reliability, efficiency, and outcomes which might be mirrored on you, making you stand out.
However to realize this, that you must construct this instinct that comes years of expertise by realizing the code smells we’ve mentioned, and the opposite two ideas (design patterns, abstraction) that we are going to delve into in subsequent articles.
And in the end, having the ability to do that successfully offers you extra headspace to concentrate on the issue fixing and architecting an answer an issue – i.e. the actual ‘enjoyable’ of information science.
Associated Articles
Should you appreciated this text, see my Software program Engineering Ideas for Information Scientists sequence, the place we develop on the ideas most related for Information Scientists

