Unlike guidelines, these are not enforcements. They are suggestions and advice for writing performant, maintainable and scalable code. You should follow these to have a great degree of control over the code you write, avoid unnecessary abstraction and technical debt in the code base.
1. Write Atomic Code
It is easy to keep bundling functionality into a single block of logic in our code. We must avoid this and write code that is decoupled, isolated and reusable.
Say, we have to implement a function renderPDFAndUploadToS3
that has to:
- render some template HTML into a PDF
- upload it to AWS S3
- patch the URL of the file into database and return it
It’s not uncommon to see an implementation like this:
Not only is the code difficult to read and understand it is also hard to test, maintain, and reuse. By bundling multiple responsibilities into a single function, we’ve violated the Single Responsibility Principle (SRP). Each step in the function handles a distinct concern: rendering the PDF, uploading it to S3, and updating the database. This tight coupling makes debugging and extending the functionality unnecessarily complex.
Instead write all the separate logic as independent and self-contained functions.
Now each function can scale, change and handle errors in it’s own scope. This implementation not only makes it easy to read and understand the code but delegates responsibility to separate functions making them independent to change in other functions, easy to debug and reusable.
2. Usage of AI
It would be easier to ask you to use AI judiciously but I will (try to) list everything you should choose to do (and not do) with all the amazing LLMs out there.
A general fact - to learn and write great code you must go through frustrating, anxious, confusing, self-doubting, blood-boiling, hair-pulling, banging-head-on-your-keyboard and about-to-cry hours in front of your computer. That’s the best way to do it. That’s the best way to learn.
It’s easy to find ‘quick’ solutions to complex problems using AI but that comes with it’s side effects. When we brute force our way out of problems using AI, it general looks like this:
- GPT a solution
- use the subpar solution
- face bottlenecks, roadblocks and errors in the subpar solution
- GPT the solution again
We keep doing this until the code becomes a mix of generated code that looks fancy, code we have some vague idea of and code that operates on very low confidence levels. This not only makes you more dependent on AI for the next steps but introduces abstraction that was never needed.
How you should use them so they support you:
- Don’t copy-pasta generated code unless it’s test data, complex database queries/aggregations/regular-expressions, repetition of code you fully understand or a refactor of code you originally wrote.
- Use it to understand errors, not bypass them.
- Read documentation to understand usage of a technology before asking an LLM.
- Understand how to implement something you have no idea about.
3. Approach To Roadblocks
You will inevitably hit roadblocks.
Try to:
- Read official documentation of the technology
- Find solutions in blogs/articles/forums
- Ask a peer or senior
- Ask an LLM
- Go through the source code
In order, from the top.
4. Blueprint Before Writing
‘Figuring out as you write’ is the surest way to write code that could have been written better. You should have a mental or physical (scribble on a page as much as you can) blueprint of the system/sub-system you are going to write.
Know what you are writing before you write.