HomeVideos

Your codebase is NOT ready for AI (here's how to fix it)

Now Playing

Your codebase is NOT ready for AI (here's how to fix it)

Transcript

276 segments

0:00

AI imposes super weird constraints on

0:04

your codebase. And most code bases out

0:06

there in the world, probably including

0:08

yours, are not ready. Your codebase, way

0:10

more than the prompt that you used, way

0:12

more than your agents.mmd file, is the

0:14

biggest influence on AI's output. And if

0:17

it's designed wrong, it can cost you in

0:19

a bunch of different ways. It can mean

0:20

that the AI doesn't receive feedback

0:22

fast enough. So, it doesn't know if what

0:24

it changed actually did what it

0:25

intended. It can find it super hard to

0:27

make sense of things and find files and

0:29

work out even how to test things. And

0:31

finally, it can lead you into cognitive

0:33

burnout as you try to hold together AI

0:36

and your codebase and patch it all up

0:37

and keep everything in your mind. And my

0:39

thesis here is that software quality

0:41

matters more than ever. In other words,

0:43

how easy your codebase is to change

0:45

makes a huge impact on how AI then goes

0:49

and changes it. And the stuff that we've

0:51

known about software best practices for

0:52

20 years still holds more true than

0:55

ever. And if you're interested in

0:56

getting better at this stuff, then check

0:57

out my newsletter, AI Hero. I teach you

0:59

all about AI coding, but this is not for

1:01

vibe coders. This is for real engineers

1:04

solving real problems. And if that's

1:05

you, and you're not sure how to handle

1:07

these new tools, then you are going to

1:08

love it. Now, let's imagine that this

1:10

here is our codebase. Each one of these

1:12

little squares represents a module. And

1:14

this module might export some

1:16

functionality. It might export a

1:17

function, might export some variables,

1:19

might export a component if it's like a,

1:21

you know, a React or a front end thing.

1:22

I want you to imagine that this is the

1:24

image of your codebase that you hold in

1:27

your head. Now you might inside here

1:28

have some vague groupings of different

1:30

functionality. For instance, here you

1:32

might have let's say a thumbnail editor

1:34

feature and all of these different

1:35

modules contribute to that. Over here

1:36

you might have a little video editor

1:38

feature or something. Down here is all

1:40

the code related to authentication. Up

1:42

here is a bunch of CRUD forms for

1:44

updating stuff maybe in a CMS. And over

1:46

here are a couple of example features

1:47

that I can't be bothered to think of

1:49

examples for. Now, this map that I've

1:50

created here of all of the located

1:52

modules in this particular codebase,

1:54

they're not actually reflected that much

1:56

in the file system. They're all really

1:57

jumbled up together. If I want to just

1:59

grab, let's say, an export from this

2:01

module and import it down into this

2:03

module, I can. There's nothing stopping

2:05

me. And so, what you might end up with

2:06

is a bunch of kind of disperate

2:07

relationships between stuff that doesn't

2:09

actually relate to each other. Now, you

2:11

as the developer understand the mental

2:13

map between all of these modules, but

2:14

what the AI sees when it first goes into

2:16

your codebase is this. It doesn't see

2:19

all of the natural groupings and all the

2:21

natural relationships. What it sees is a

2:23

bunch of disparate modules that can all

2:25

import from each other. That's because

2:26

AI when it jumps into your codebase, it

2:28

has no memory. It has not experienced

2:30

your codebase before. It's like the guy

2:32

from Momento who just steps in and goes,

2:34

"Okay, I'm here. Uh, what am I doing?"

2:36

So, my first assertion here is that you

2:38

need to make sure that the file system

2:41

and the design of your codebase matches

2:44

this internal map that you have of it.

2:46

This is because if you describe

2:48

something over in the video editor

2:49

section and you use it via a prompt,

2:51

then you want the AI to be able to find

2:53

it easily. The AI won't go in knowing

2:56

every single function, every single

2:58

module and what they supposed to do and

3:00

how they link to each other. And the

3:01

best way I have found to do that is with

3:03

deep modules. Now, deep modules comes

3:05

from this book here, which is a

3:06

philosophy of software design. And the

3:08

idea is that in order to make your

3:10

system easily navigable and easy to

3:12

change and also easy to test is that you

3:15

have a deep module so lots of

3:17

implementation controlled by a simple

3:19

interface. What that looks like in terms

3:20

of our graph is instead of many many

3:23

small modules you end up with these big

3:26

chunks of modules with simple

3:28

controllable interfaces and this means

3:30

that any exports from these modules have

3:32

to come from that interface. Now when I

3:34

read that about deep modules, I

3:35

immediately thought about putting AI in

3:39

control of these modules because this is

3:41

an opportunity to introduce a kind of

3:42

seam into the codebase. I don't really

3:44

care about what's happening inside here

3:47

which is the implementation. I just care

3:49

about what's happening in the interface

3:51

because the interface which is you know

3:53

the publicly accessible API of this

3:55

module I can carefully control and I can

3:58

apply my taste to and design and then

4:00

the stuff inside here I can just

4:02

delegate to an AI to control and I can

4:05

write tests that completely lock down

4:08

the module in terms of its behavior. So

4:09

these are not just deep modules with

4:11

simple interfaces, they're also graybox

4:13

modules. In other words, I don't

4:15

actually need to look inside these

4:18

modules. I can if I want to, if I want

4:20

to influence their outcome or if I need

4:21

to apply some taste to the

4:23

implementation or I need to improve

4:24

their performance or something, but as

4:26

long as the tests are good, then I don't

4:28

really need to care about what happens

4:29

inside. Now, this has three massive

4:32

benefits. The first one is that I can

4:34

make my codebase way more navigable.

4:36

Let's for the sake of argument just call

4:37

each of these services, right? The video

4:39

editor service, the thumbnail service,

4:41

whatever. If I document these each

4:43

inside their own folder and I have the

4:45

publicly accessible interface kind of

4:46

like uh really obvious in a type

4:48

section, then the AI when it's exploring

4:51

my codebase, it can see all of these

4:53

different services on the file system.

4:55

It can read and understand the types

4:57

that they export before it actually

4:58

looks at the implementation. And then it

5:00

can say, okay, I've seen the interface.

5:02

I understand what this does. I don't

5:03

need to look inside because I can just

5:05

trust what it's returning. In other

5:06

words, we've designed our codebase for

5:08

progressive disclosure of complexity.

5:10

The interface sits at the top and it

5:12

just explains what the module does and

5:14

then when we need to we can look inside

5:16

the module and make changes to it or

5:17

look at it to understand its behavior

5:19

more deeply. The second one is that we

5:21

reduce the cognitive burnout of managing

5:23

this codebase. Now as a user I can just

5:26

go right I need something from uh I

5:28

don't know this madeup feature or let's

5:30

say the authentication bit over here.

5:32

Let's say what let's see what the public

5:34

interface is. Let's just grab that and

5:36

use it. And instead of needing to think

5:38

about the inter relationships between

5:39

all of these modules, I can just keep

5:41

kind of like seven or eight lumps of

5:43

stuff in my head and go, okay, the AI

5:45

manages the stuff inside that. I only

5:48

need to worry about designing the

5:49

interfaces and how they fit together.

5:50

Now, this of course is still a million

5:51

miles away from vibe coding because you

5:53

need to apply taste at the boundaries of

5:56

these modules. You need to be really

5:57

good at deciding, okay, what goes into

5:59

that module, what goes into that module.

6:01

And what you really want to avoid are

6:02

lots of little shallow modules, which is

6:05

kind of what we had up here, right? Each

6:06

of these modules is just like, sure,

6:08

it's kind of interrelated and grouped

6:10

together, but really they're lots of

6:12

tiny shallow modules which are testable

6:14

in these tiny units which are really

6:16

hard to keep all in your head. And so by

6:18

simplifying the mental map of the

6:20

codebase, we reduce cognitive burnout

6:22

that comes from managing this codebase.

6:24

And again, this is nothing new. This is

6:26

a 20-year-old software practice. And the

6:28

third one here, I mean, I'm really just

6:29

repeating myself, but this is what we've

6:32

been doing all along. This is how good

6:34

code bases have supposed to have been

6:36

designed. So, what works here for humans

6:38

is also great for AI. We need to stop

6:40

thinking about AI as like this

6:42

superpowered developer as like, you

6:43

know, it's going to reach AGI and

6:45

understand that it's got some weird

6:46

limitations. And the limitations that it

6:48

has are that it's a new starter in your

6:50

codebase. So you need to make your

6:52

codebase friendly and ready for new

6:54

starters because you're going to be

6:56

spawning like 20 new starters every day

6:59

or probably more just to look at your

7:01

codebase and make changes. So that means

7:03

the map of your codebase needs to be

7:05

easily navigable and it needs to be

7:06

enforced by using these modules. Now

7:09

some languages make this easier than

7:11

others. For instance, in Typescript and

7:13

JavaScript, it's actually not that easy

7:15

to make these services make these

7:17

modules uh sort of boundaried in this

7:19

way. I want to give a quick shout out to

7:21

effect because uh I posted a video on

7:23

effect a few months ago. I'm actually

7:25

using effect way more than I did back

7:27

then and it makes this kind of um sort

7:30

of seeming modularizing of your codebase

7:33

really simple. The final thing I want to

7:34

say here is that you need to be thinking

7:36

about these modules and how you're

7:38

affecting them and how you're designing

7:39

the interfaces in every coding session

7:42

that you do. That means right from the

7:44

early planning stage when you're writing

7:46

your PRDs or when you're turning your

7:47

PRDs into implementation issues, you

7:49

need to be thinking about the modules

7:51

that you're affecting and the interfaces

7:52

and how you going to test them because

7:54

tests and feedback loops are essential

7:56

for an AI because of course they're

7:59

essential for a new starter joining the

8:00

codebase. If you want the new starter to

8:02

contribute effectively, you need a well-

8:04

tested codebase so they can see what

8:06

their changes do as they ripple out. So

8:08

that's my rant for today. your codebase

8:10

is probably not ready for AI because

8:12

you're not using enough deep modules and

8:14

instead you've got a web of

8:15

interconnected kind of shallow modules

8:18

like this which are really hard to

8:19

navigate and really hard to test and

8:22

really hard to keep in your head. Now,

8:24

if you dig this then of course you will

8:25

dig my newsletter where we go more

8:27

deeply into topics like this. Thanks for

8:28

watching folks. What else do you think

8:30

goes into making a great codebase for

8:31

AI? I really love this metaphor for deep

8:34

modules but I know it's not the only one

8:35

going. There are plenty out there.

8:37

Thanks for watching and I will see you

8:38

very soon. So, when you're thinking

8:40

about your codebase with AI, what are

8:41

you thinking about? What kind of

8:43

20-year-old books do you want to

8:44

recommend? Leave it in the comments.

8:46

It's the easiest way to keep up with all

8:47

of my stuff and the link is below.

Interactive Summary

The video emphasizes that most codebases are ill-equipped for AI because AI perceives code as a jumbled collection of modules, lacking the human developer's mental map of functional groupings. This inadequacy leads to slow AI feedback, difficulty in understanding and testing, and increased cognitive burden for developers. The speaker advocates for adopting "deep modules," a 20-year-old software design philosophy, where complex implementations are hidden behind simple, well-defined interfaces. By treating these as "graybox" modules, developers can control the interfaces, allowing AI to manage the internal implementation, supported by robust tests. This approach significantly improves codebase navigability for AI, reduces human cognitive burnout by simplifying the mental model, and aligns with best practices for creating "new-starter friendly" codebases for AI agents. The video concludes by stressing the importance of considering module design and rigorous testing at every stage of development.

Suggested questions

7 ready-made prompts