The Joy and Pain of Coding with AI When You Suck at Coding
Or How I Made a Complex Program with Terrible Coding Skills
I wanted to see if AI could write me a complex program.
Not some crappy little script, but something hard. A real program.
I'm not talking about some single file Python throw-away that shuffles some files around or dedupes some data in two CSV files. AI is already masterful at writing little bash and Python scripts for those easy tasks. You can just tell GPT to dedupe the files with instructions on how you want to filter them and it will do it. You don't even need to review the code. It will write the code, run it and return the new file to you.
But that's not what I wanted. I wanted a real program.
Is this even possible with today's AI? The TLDR is yeah, it is, but it's...complicated. More on that in a bit.
If you're curious/impatient, you can check out the Github code from the completed project right here.
So why was I doing something like this anyway?
I've got a new partner person starting at my company and I wanted to make it easier for her to research companies by building a web crawling GPT-4 agent that would power through a list of potential partners, go to their website, read their home page, summarize what they do and get me all their pricing information.
To get it to work it means the program has to use a headless browser, read the text on the website, keep all the text while stripping out all the images and video and HTML code, process it into chunks to fit an LLM context window and effectively summarize what it read without hallucinating or making a bunch of stuff up. It also needed to navigate to a pricing page and find all the pricing info and grab that too. It's also got to scale, meaning it has to process multiple URLs instead of going one by one, at once or it will take forever.
Doing all that manually is really, really time consuming and boring. You have to go out to 10s of thousands of websites and read them one by one. We're talking weeks or even a month of work. So getting this right means we save a lot of time.
Now this isn't me coding up a major platform like Replit or Shopify from scratch (something absolutely outside current AI platform coding capabilities), but it's still complex stuff that is much more than a single file Python script and it's basically outside my current coding capabilities.
We are still not anywhere close to where AI can come up with something that's never been done before and create new algorithms from scratch to do it. It's coming but not it's not here yet and I don't know when we get to that level even though everyone on Twitter thinks it's coming next week (it's not.)
(Source: Satirical fake post by Author)
I wanted to understand the state of the art by giving myself a hard problem that was also really useful to me. But what is the state of the art? That's not clear and the only way to make it clear, just like anything in life, is to do it.
In short, I wanted to know was it even possible to get AI to code something like this for me or is it totally outside the realm of what me and AI working together are capable of right now?
To start off I have some real disadvantages doing this project. Number one, I'm just not a good coder. I've studied a smattering of C/C++/Java/Bash and Python over the years. Coding always felt very brittle, arcane and frustrating to me after I got past early tutorials. I just can't think in code.
But I've also got some strong advantages too, especially over someone with no technical expertise whatsoever.
What I discovered quickly is that if you're coming to coding from painting houses, it's going to be too much of a leap. But if you're an engineering manager who coded in a former life or a systems engineer like I was when I was younger than it's possible.
I've also run tech teams as a CIO, been a lead systems architect on big projects, and worked on super complex infrastructure setups as an IT consultant for over a decade. In short, I know how programs work and scale and run.
I'm also a writer and a clear thinker. That means I know how to ask for what I want in crisp, precise language. Prompt engineering really ain't nothing but good writing and that's a big advantage in the age of asking machines to do things for us. In a way, taking to machines is critical thinking at scale.
What is happening? Why? How can I get it to do what I want? How can I explain it better? What's missing?
The more of this kind of internal thinking you can do the better in the coming age of AI.
So did AI do all the work for me?
Oh my God, no.
If you believe the Twitter hype masters it means we're super close to having superhuman AI come up with complex logic and brand new algorithms in a flash. The great and powerful Oz of LLMs will come up with the architecture, write the code, test it, fix bugs, write the documentation, deploy it and monitor it for you.
All we have to do is show up and ask like we're Scotty in Star Trek and it is done.
Like magic.
Well, it turns out not so much.
Coding with AI is equal parts "holy shit, it fucking works" and utterly frustrating drudgery/pain and back again. It's still mostly the second part. It's a wave of emotional highs and lows. Don't get me wrong. It's incredible that I can get a program ex nihilio, like the old testament God magicking up the Universe from the Word, but it's still not easy. It's fucking work. Hard work.
Anyone who tells you different is selling something.
Did I get a complex program written?
Yup.
I sure did. And I'm going to walk you through parts of it and what I learned along the way.
But getting there was not easy. It took a lot of the old me to get it done and by that I mean the sys admin me.
The sys admin me was a bulldog.
I just kept ramming my head against a problem until it was solved, no matter how long it took or how much pain I had to endure. If I had to stand in the freezing datacenter for 36 hours straight then I did it and that Exchange server would be back up and running with all its data restored before anyone came in on Monday.
But it's a part of my life I'm happy to leave in the past.
But it took me about 5 full days scattered over two weeks to get it done and it was a lot of grinding my head against it and wanting to quit. I kept thinking, maybe it's just not possible?
(Source: Sad & Useless Humor)
It's especially frustrating when you're hitting against programming concepts you just don't understand all that well.
At one point, I asked my CTO, a veteran coder, to look at something and it took him two minutes to see what was wrong. It had taken me a few hours and I was stuck.
There's a lot of blind spots when you don't know what you don't know.
It's amazing that I can get a working program up and running with the help of my digital buddies we've got a ways to go. Star Trek this ain't.
Anyone who thinks coders are going away is hallucinating.
If anything skilled coders who know how to ask for what they want clearly will be in even more demand as AI does more of the coding for us. Systems engineers who understand good architecture and security will be needed more than ever as more insecure code and bad coding practices get pushed to production. Coding managers who've left coding behind and "can't code" will soon be the folks coding again instead of waiting for their coders at every step.
Coding with AI is like talking to a brilliant child with short term memory loss and no context for anything outside of the immediate now.
Maybe that will get much better with bigger context windows and integration with models like Gemini 1.5 (come one, Cursor, let's do it!), with its 1 million token context window, but for now coding with AI feels like coding with a form of AI based amnesia.
Still, if you know what you're doing, it can help. If you don't, it probably can't.
So let's dive in and take a look at the joy and pain of coding with AI in 2024.
The Journey Begins
I started off simple.
I started off Sublime.
In other words, I used the Sublime Text editor to start coding until I found something better. More on that in a moment.
Many coders like to work with simple text editors to code or simple code formatting text editors like Sublime. It feels hardcore. It also means the code takes front and center and the interface fades to the background.
George R.R. Martin is famous for still writing his books in Wordstar 4 on a DOS computer not connected to the internet. I understand. It does exactly what he wants and nothing else. If you're an amazing coder, you don't need the program popping up and annoying you with unhelpful suggestions and fixes every five seconds.
I also have an affinity for text. As a long time Linux admin, the command line was my friend and I don't want my notes all formatted. I want plain text so I can copy and paste commands exactly. I don't want commands getting bungled up by unhelpful spell checkers that mangle things.
Sublime is basically a glorified text editor. A very nice text editor but a text editor nevertheless.
And I quickly learned that this was a very bad choice for AI coding.
Sublime is fine if you know exactly what you're doing in code but I don't know exactly what I'm doing so it was exactly the wrong choice for me.
It meant a lot of cutting and pasting into GPT chats to get answers. It was slow, boring and frustrating.
Okay, now I am getting this error, what does it mean?
Cut and paste new code and try again.
If you look closely at that screenshot, and you know the OpenAI API, you'll see it hallucinated. It told me that it believes the new version of the function is:
openai.Completion.create
It's not. It just made that shit up.
There is nothing in the error message to indicate the correct call. You have to click the link and go to the API reference to learn it. But GPT doesn't do that by default.
So what did it do?
It just made up an imaginary new way of calling the function that does not work.
Coding with AI often feels more like being a QA engineer than a coder.
When it came to errors, I quickly learned that Perplexity was better at troubleshooting errors, because it can search the web. That means it can find much more timely answers. The Pro version is basically GPT4 or Claude Opus with RAG. Plain old GPT or Claude are hamstrung by having outdated knowledge of libraries in Python or even its own OpenAI API calls. They are going to make mistakes because they just don't have up to date info and actively maintained coding libraries are changing all the time.
So the answer to getting answers it to use a combo of Perplexity and going to the API documentation examples yourself to give the model context on how to use the updated library. In other words, code by example. Same as it ever was.
This works.
Mostly.
But sometimes even when you show GPT the correct reference code it just doesn't know how to use that code and defaults back to old hallucinations.
Even worse, it's still all a lot of copy and pasting.
I needed something better than a text editor. My COO, a long time coder, saved me a lot of trouble by letting me know I should switch to Cursor AI, a fork of VS Code that uses AI natively throughout the app.
Cursor is brilliant.
You can pay for their service or plugin GPT and Claude API keys directly and pay OpenAI and Anthropic. I went the second route as I knew I would have a lot of calls and run up some bills so I didn't want any monthly limits but their service has some nice extras you probably want to consider.
The AI is woven right into it, so it's very easy to talk with GPT/Opus, copy snippets right into the dialogue with a single click and more. It feels next gen.
It also has incredibly important features like "use with code base" when you ask a question, which helpfully feeds the codebase in as a reference.
It even has a life saving feature where you can press "Continue" when GPT runs out of space to finish its answer. This happens because GPT has a limited token response output so it sometimes fails to finish outputting the updated code. The button basically instructs GPT to finish right where it left off and it works every time.
You can also use Command+K to write code right in the file itself and accept the changes or reject them.
You can even have it browse 3rd party libraries as a reference so that it understands them better, a feature I wish I had noticed before completing this project. I discovered it late in the project. It would have potentially saved me a lot of grief, especially with the OpenAI API.
But sadly, in my quick testing while writing the article it mostly doesn't mitigate hallucinations any better than copying and pasting exact examples, probably because I am not using the Cursor AI RAG service? Others will have to check it out for themselves. You mileage may vary.
A neat alternative trick is to create various documentation text files and paste lots of examples from the API docs into it and let Cursor reference them. You can remind the LLM in the prompt that it needs to reference those examples every time. This worked well with coding a Vertex based Gemini bot that I am working on now. Originally GPT used the OpenAI API calls and I had it remember that it need to use Gemini and Google Vertex and that it can use the GEMINI_DOCUMENTATION.txt file as a reference.
Okay so now I had my coding setup. I have Cursor, Perplexity and subscriptions to Anthropic's Claude Opus and OpenAI's GPT-4 and API keys to access them.
Now the fun really begins.
From Crap to Useful Program
When you start out, the AI is going to give you a big single file program. It will inevitably be called main.py.
As you add features it's going to get really, really unwieldy and unmaintainable.
If you don't ask for modularity right away you won't get it.
Even worse, GPT will really struggle as main.py gets bigger and bigger and bigger. It chokes on it as it struggles to fit it into its context window.
This is a good moment to point out that AI can and will happily saddle you with atrocious coding practices. If you have no history in coding, systems, IT, or software you will have no idea that what you just created is just plain wrong.
It's insecure, unmaintainable and filled with things you never want to see in production code. In short, whatever AI you use today is going to use every single bad programming habit known to man.
It will write quick and dirty code that is insecure, doesn't scale and will cause you major headaches later on.
Here's just a few of the things it did with my program:
Set the OpenAI API key right in the file like so: OPENAI_API_KEY=abc123
This is absolutely terrible practice because it's super easy to leak that key in hundreds of ways. Much better to put it in an environmental variable (not perfect but better) or in a secrets storage system like HashiCorp Vault (much better).
Created a list of outputs in memory and then flushed them all to a file at the end
My script scrapes competitors or potential partner web pages and summarizes what they do and gets their pricing information. Keeping them in memory is fine for a few URLs but if you have 1,000, or 10,000 or more, it's going to balloon memory and if the program crashes you lose all your work. Much better to write to the file as you go.
No state.
Since the original script did not keep track of its state, that means it has to run completely end to end, processing every URL. If you have to start over because of a crash all your work is lost and you start over from scratch.
No error handling.
Crappy modularity.
When I asked it to start breaking out functions into new files, it did it in a half-assed way with no real logic and left most of the functions in main.py
Made the app single threaded.
It spidered each URL one by one, which is slow and takes a long time.
Made calls to the OpenAI API synchronously, which is super slow because the calls have to happen and then you have to wait for an answer.
Much better to make the calls asynchronously because your program can then make calls to the API and then does other things while waiting for those answers.
No rate limiting for the OpenAI API.
OpenAI and most other APIs out there have rate limits to ensure that you don't just bash away at it. OpenAI's rate limits are really low because LLM inference is expensive so you have to deal with it in code or you just get error after error. If your program is not equipped to deal with the rate limits you could quickly find your web scraper fills your output file with "error, error, error" instead of information about your competitors and partners.
The list goes on and on. And if you don't understand these things from your own experience you won't even know to look for them or to ask the AI to fix it.
Want to know the best part?
After I got the program working I wanted to refactor it to make it even more modular and easier to maintain. I wanted to create classes, split out functions into different files, etc.
This was not fun.
During this process, instead of porting over the good security and scaling practices I painstakingly built into the code through iterating with the AI, it brought back all the same fucking problems again!
It undid everything and reverted back to the old way of doing it.
Writing to the output file at every step? Nope. Back to storing it in memory.
Posting my API key right in the settings file? You got it. No more environmental variable for you.
I had to re-prompt the system to re-add all these features and go through the same painful debugging steps all over again.
When you refactor code, the code often reverts to earlier stupid mistakes that it made, like swapping out gpt-4-turbo for the gpt-3 davinci model because that's what it's memorized from its training days. You often have to recorrect the same errors.
GPT is particularly bad at using its own API. It absolutely loves to call outdated functions and revert to old GPT models. It desperately wants to hallucinate back to its own cut off date knowledge of the OpenAI API. (The new gpt-4-turbo model with a cutoff date of Dec 2023 came out after I wrote this article in a particularly funny twist.) No matter how many times you give it updated code from the API reference it often inserts little hallucinations of old ways to call that code.
One of the biggest errors it makes over and over and over again, is using an old version of chat completions:
openai.ChatCompletion.create()
The problem is this:
'As of my knowledge cutoff in April 2023, the OpenAI Python client library uses openai.Completion.create()
for synchronous calls and openai.AsyncCompletion.create()
for asynchronous calls when working with completions."
But there's a new way to call it in the latest version of the API, which helpfully introduces breaking changes, aka adding another period and getting rid of capitalization for the same damn call, aka not helpful:
client.chat.completions.create()
The part of coding that I always hated the most was tracking down tiny little typos. As a long-time author I find the idea of a single semi-colon or period destroying the ability of the code to function totally absurd.
If I spell something wrong you can still read it and understand what I meant.
But have one bracket out of place in code and the program just won't run!
Tracking down these little mistakes is a horrible pain, even with a good IDE (although they've made it a lot easier). But tracking down bugs like this is now made infinitely worse by AI because you don't write the code yourself, so you don't even know what kinds of typical typos it makes.
When you write the code, you at least eventually learn your own common misspellings and errors (oh I always miss a bracket in a big nested loop, I always replace - for _ ) but you have to learn AI's tendencies. It's like learning another coder's mistakes.
Even when it is given examples of the correct call it often screws it up still.
Take a look at this repeated typo/hallucination that GPT-4 makes again and again and again. Here is the incorrect line:
client.chat_completions.create()
But the correct call is this:
client.chat.completions.create()
Can you spot the error? It's putting in an underscore for a period. My best guess is that it comes from the fact that a lot of the code examples on forums and blogs do something like this:
def get_gpt_response(messages):
chat_completion = client.chat.completions.create(
model="gpt-3.5-turbo-1106",
messages=messages,
functions = functions,
function_call="auto",
)
return chat_completion
It learns that chat_completion is just as likely a set of words to predict as chat.completions and it alternates between them.
This kind of stuff is absolutely maddening to track down! I can't see someone with zero understanding of code fixing this kind of bug. They just wouldn't know where to start. It's like finding a needle in a haystack in a big file.
GPT is also tremendously fond of putting in older versions of the model with its hallucinations.
Want to use gpt-4-turbo-preview? Nope, you're getting text-davinci-003
a deprecated model that isn't even GPT-3 anymore. Now it's gpt-3.5-turbo-instruct
.
You'll often find that GPT just randomly changes that model on you or rewrites your prompts and you're running a test before you realize it.
I ended up having to do a lot of old school troubleshooting, aka pasting error files into google/Perplexity and reading through forum posts to try to understand what the hell was going wrong in the scripts after the models just completely failed to fix a bug after a dozen iterations.
Eventually you just have to understand the problems yourself and find the solution.
I'm very used to that old grind. As a sys admin I lived on the net hunting down answers when things went wrong. It's one of the parts of my old job that I hated more than anything else. It hasn't gone away.
As of today, AI can't magically fix everything. Remember that Devin, the AI software coding assistant, is considered state of the art because it can fix 13.86% of bugs on its own. That is not a lot. It's awesome but it is not a lot.
It means you have to understand your code well enough to fix the other 86.14% of bugs.
The biggest problem with coding with AI at this point is really context and by context I mean human context here. As humans, we reference a file we just saw or an idea we just heard about all the time as we work or complete any complex task. GPT is like a big dumb child that completely forgets about the things it just saw and heard. So you have to loop and loop and loop through the same freaking mistakes multiple times because it reintroduces problems that it solved in the original code.
The second biggest problem is context windows, which are nothing but a glass ceiling on how many tokens you can give it before it barfs. The biggest problem with context windows is they're just too short for doing anything useful. To understand context the models are going to need to remember a lot more and be able to reference that knowledge easily. They just can't do it right now no matter how many RAG tricks you throw at it.
So that is the shit part of it.
What did it get right?
A lot.
This is the magic part.
I eventually got fully working code that I could never have written myself.
The Magic of Coding Without Coding
Take something like Playwright. It's a modern framework written by Google to orchestrate a browser headlessly to run tests on websites.
I have zero idea how to use Playwright or where to even begin.
Yet out of the primordial soup of the LLM's weights I got this:
import asyncio
from playwright.async_api import async_playwright
from urllib.parse import urljoin
import logging
from gpt_summarizer import GPTSummarizer
from file_manager import FileManager
from utils import exponential_backoff
from settings import BROWSER_EXECUTABLE_PATH, BROWSER_ARGS
from content_processor import ContentProcessor
class WebScraper:
def __init__(self, gpt_summarizer: GPTSummarizer, file_manager: FileManager):
self.gpt_summarizer = gpt_summarizer
self.file_manager = file_manager
self.content_processor = ContentProcessor()
async def process_url(self, name: str, url: str, output_file: str, state_file: str, max_retries: int = 3):
if url in self.file_manager.get_processed_urls(state_file):
logging.info(f"Skipping {url}, already processed.")
return (name, url, "Already processed", "N/A")
async def scrape_and_summarize():
try:
async with async_playwright() as p:
browser = await p.chromium.launch(executable_path=BROWSER_EXECUTABLE_PATH, args=BROWSER_ARGS)
page = await browser.new_page()
await page.goto(url, timeout=60000)
content = await page.content()
logging.info(f"Content extracted from {url}.")
clean_text = self.content_processor.clean_content(content)
safe_chunk_size = 119000 # Adjust this value based on your specific prompt size and needs
processed_text_chunks = self.content_processor.chunk_text(clean_text, safe_chunk_size)
results = []
for chunk in processed_text_chunks:
summary = await self.gpt_summarizer.summarize(chunk, purpose="summary")
results.append(summary)
combined_summary = " ".join(results)
pricing_link = await self.find_pricing_link(page, url)
if pricing_link:
logging.info(f"Navigating to pricing page: {pricing_link}")
await page.goto(pricing_link, timeout=60000)
pricing_content = await page.content()
clean_pricing_text = self.content_processor.clean_content(pricing_content)
processed_pricing_chunks = self.content_processor.chunk_text(clean_pricing_text, safe_chunk_size)
pricing_results = []
for chunk in processed_pricing_chunks:
pricing = await self.gpt_summarizer.summarize(chunk, purpose="pricing")
pricing_results.append(pricing)
combined_pricing = " ".join(pricing_results)
else:
combined_pricing = "No pricing information found."
await browser.close()
return (name, url, combined_summary, combined_pricing)
except Exception as e:
logging.error(f"Error processing {url}: {str(e)}")
await browser.close()
return (name, url, "Error in processing", "Error in processing")
for attempt in range(1, max_retries + 1):
result = await scrape_and_summarize()
if result and result[2] != "Error in processing":
# Write the result to the CSV file asynchronously
await self.file_manager.write_to_csv(output_file, result)
self.file_manager.update_processed_urls(state_file, url)
return result
else:
logging.error(f"Attempt {attempt} failed for {url}. Retrying after delay...")
await asyncio.sleep(exponential_backoff(attempt))
# If all attempts fail, write the failure result to the CSV
failure_result = (name, url, "Failed to process after retries", "N/A")
await self.file_manager.write_to_csv(output_file, failure_result)
return failure_result
async def find_pricing_link(self, page, base_url):
pricing_texts = ["pricing", "price", "cost", "plans", "subscriptions"]
links = await page.query_selector_all('a')
for link in links:
link_text = await page.evaluate('(link) => link.textContent.toLowerCase()', link)
href = await page.evaluate('(link) => link.getAttribute("href")', link)
if any(pricing_text in link_text for pricing_text in pricing_texts):
return urljoin(base_url, href)
return None
This is one of those awe inspiring moments where you can hear the choirs of angels sing.
Originally I started off with a different headless browser orchestrator library called Puppeteer but kept running into crashes and bugs. Eventually I switched to Playwright and that code mostly worked right out of the box after I figured out the perfect set of switches to make headless Chrome run right.
Headless chrome is a bit of a sys admin nightmare, especially if you're running a container that is running 64 bit AMD or Intel code on a Mac Arm processor.
I managed to install Chrome myself instead of letting Python install an instance and painstakingly figured out what switches to set to make it run and work stably.
Again, that is old school sys admin work. I was well suited to it but it still sucked. It was old fashioned trial and error.
Eventually I hit on the right combo of switches:
# Playwright browser settings
BROWSER_EXECUTABLE_PATH = "/usr/bin/google-chrome-stable"
BROWSER_ARGS = [
"--no-sandbox",
"--disable-background-networking",
"--disable-default-apps",
"--disable-extensions",
"--disable-sync",
"--disable-translate",
"--mute-audio",
"--safebrowsing-disable-auto-update",
"--ignore-certificate-errors",
"--ignore-ssl-errors",
"--ignore-certificate-errors-spki-list",
"--no-zygote",
"--disable-gpu",
]
Next I faced other unexpected problems. Originally the code was written to just shove all the content sucked from a website into GPT's gullet but since it was stuffed with images and tons of HTML code it just quickly overflow the context window.
I needed something to read the HTML, grab the text out of it and then chunk it up to fit the context window.
Enter Beautiful Soup and Langchain, two packages I'm familiar as a concept with but also have no idea how to use.
Here's the content processor class in the file called content_processor.py that the program calls in other scripts.
from bs4 import BeautifulSoup
from langchain_openai import OpenAI
import os
class ContentProcessor:
def __init__(self):
self.openai_api_key = os.getenv('OPENAI_API_KEY')
if not self.openai_api_key:
raise EnvironmentError("OpenAI API key not found. Please set the OPENAI_API_KEY environment variable.")
self.llm = OpenAI(api_key=self.openai_api_key)
def clean_content(self, html_content):
"""Clean and extract text from HTML content using BeautifulSoup."""
soup = BeautifulSoup(html_content, 'html.parser')
for script in soup(["script", "style"]):
script.decompose() # Remove these two elements and their contents
text = soup.get_text(separator=' ', strip=True)
return text
def chunk_text(self, text, max_length):
"""Chunk text into parts with a maximum length."""
chunks = []
while text:
if len(text) > max_length:
space_index = text.rfind(' ', 0, max_length)
if space_index == -1:
space_index = max_length
chunks.append(text[:space_index])
text = text[space_index:].lstrip()
else:
chunks.append(text)
break
return chunks
Again, another choirs of angel moment. That code mostly just worked right away and again I have zero idea how to work with either package.
That's amazing stuff.
In the end I had a fully functional program that I am adding to all the time.
I decided to create a new module today that can score companies based on heuristics I developed. So I will have a new module that will add a few new lines to my CSV. One is a general vibe based assessment from the model and the other is a hard score based on my rules.
I suddenly got access to Gemini 1.5 Multimodal with its 1M token context window and its incredibly promising. Many of the problems I faced boil down to context window limits. RAG just doesn't solve it. You still run up against context windows even if it can search a vector database.
With Gemini I was able to paste in all my code and have it outline a plan to add heuristics and scoring and create the new files step by step. It understood ALL of my code. That's a massive improvement just since I began writing this article.
Other new modules await.
I'm already starting to dream up new programs and that's tremendously exciting.
The Future of Coding
So is AI about to put everyone out of a job?
Hell no it's not.
If anything, top notch coders who can think in code and define problems clearly are going to be more in demand.
If you can think about thinking you've got a tremendous advantage in the coming world.
All this reminds me a lot of past developments in tech. Right now I can use Webflow to make a fantastic web site even though I don't know a ton about React and cascading style sheets. But great web developers still exist and they get the most out of Webflow.
Before Webflow I used Wordpress and that continues to be my clearest analogy to the present day. In the early days, it was hard to make good looking websites. You had to write all the HTML yourself and learn to use Photoshop and other tools and stack it all together. Then along comes the LAMP stack and suddenly it's a lot easier to create higher quality websites. You still needs skills but the barrier to entry dropped. Then Wordpress comes along, built on top of the LAMP stack. Even easier. After that you get plugins to Wordpress like Divi that let me drag and drop together a beautiful website and pull from extensive templates made by awesome designers.
Each time we move up the stack, abstracting away a lower level of problems, we enable more people to make a great website. Each new abstraction makes it easier to do something complex.
The same thing happens with every new technology. It brings more people into the fold.
We benefit tremendously from the breakthroughs of the people who came before us. Each new tool makes it easier to do bigger and better things. We can make a mud hut without tools but once we get hammers and nails and standard wooden board sizes we can build big houses and grand buildings. Once we get steel girders and cement we can stack skyscrapers into the clouds.
We stand on the shoulders of giants every day.
A lot of people make the mistake of believing that because more people can do something that was once restricted to artisans, nobody needs amazing designers and website builders. That's just wrong. That's gatekeeping and fear-mongering from people who have a monopoly on doing something right now. They don't want anyone else getting into the game.
There are examples in history of jobs going away. Lots of them. But it never happens overnight. And usually technology is iterative. The electric light eliminated the need for lamp lighters and whale oil candles but lamplighters still worked for many decades because old technologies tend to live right next to new ones for a long time.
We've already destroyed all the jobs multiple times in history. You didn't tan leather to make your clothes today or hunt the water buffalo for food. But we've always replaced those jobs with new and more varied jobs. And no, this time is not different.
Most technology is incremental. AI will be revolutionary and transformative but it's also incremental as well. It makes things more accessible.
Everyone can make a cool website now.
The big web development teams haven't gone away. They've multiplied. The big websites have only gotten more complicated and powerful in what they can do. Amazon is not making their website with Wordpress and drag and drop editors.
We always get new capabilities at the top and the bottom of the chain.
People who embrace AI and work closely with it will displace people who refuse to work with it. Film editors who refused to switch to digital editing don't have a job anymore but there are more editing jobs than ever. That's because making films got easier with digital tools and that meant more films, which meant more jobs.
We're about to have a lot more programs. Right now if you can dream up a program that doesn't exist, it's still hard to create with AI but it can be done.
Your engineering manager to can get things built now. So can the coder who spent two decades coding but needs to learn a new language or a new set of design patterns. Now they can adapt to new technologies faster with the help of AI and leverage their twenty years of wisdom along the way.
It will get easier and easier to whip up good programs as the years go by. Maybe there's no commercial reason for anyone to build the program you want because it doesn't have the potential of a massive market and big sales, but it might be just the program you need.
Now you can have it. Before AI you couldn't have it because nobody would build it.
At the top of the chain, apps will get more powerful and more complicated as AI enters the workforce alongside traditional coders. At the bottom of the chain, small development teams will be able to do a lot more. And soloists will be able to create personalized programs and that will lead to some great one and five person companies.
We're entering an area of personalized coding. Dream up an app and build it for yourself, even if nobody else needs it. It doesn't matter if nobody else wants it because the barrier to entry will get so much lower.
People who can critically think, plan, strategize, reason and imagine will have a massive advantage in the coming world. Because I know what I want and I know how to ask for it, I can get a program I want out of AI.
Don't get me wrong. It's still a pain in the ass. But this is the worst it will ever be and it will only get better from here.
If someone is out there telling you not to study computer science or IT or system engineering don't listen to a word they say. The more you know about great architecture and scalability and security the better off you'll be because you'll know what to ask the AI to do. Even better, you'll know how to judge the output. You'll look at it and know if it's right or wrong better than someone with no skills.
Traditional artists sometimes worry that image generating programs make it too easy for anyone to create art and that they'll all be out of a job. But the best results from AI come from people who already have great art skills. A great artist gets more from a paintbrush and watercolors than someone who's a dabbler like me. Great artists get more out of AI too.
AI is just another tool. I'll say that again because people seem to not understand it. AI is just another tool.
It's not a God. It's not sentient. It's not all knowing and all powerful. It's a tool.
Skilled people always get more out of tools.
I can do wonders with Photoshop and decent work with Figma and Webflow. But a great designer can work those programs like magic.
And a great programmer will know how to get the best out of coding AI.
Keep studying. Don't listen to fools. Keep learning. Keep updating your skills. Adapt. Grow learn. Always. That's the way forward in the future where AI is your constant companion and friend.
I'm already dreaming up so many new programs that would never get built. I can build them now.
The only limits are my imagination.
And my patience.
Want an insightful journey, thank you for documenting and writing this up!
"The more you know about great architecture and scalability and security the better off you'll be because you'll know what to ask the AI to do. Even better, you'll know how to judge the output. You'll look at it and know if it's right or wrong better than someone with no skills."
As someone who is not technical in any way, what resources would you recommend to get a good baseline understanding of these concepts, their capabilities & limitations, enough to succesfully communicate and collaborate with technical teams?
Thanks!