(Back) (Home)

What I Learned

I've been gone for months lmao

The 27th of next month (November) marks one year since I started development of Sonnet, and became the lead developer
In this past year I have learned alot about coding, how to make things efficient, how to handle user errors, how to handle end users

People say what all developers need is skill and knowledge
But they always forget, you also need experience

It's 2am, wake up, the bot is having an error on a command, it just doesn't work
Noone knows whats causing it
Get on the computer, get the error logs from the person running the bot, cause it only logs to the bot, and im not running it
I find its a variable I removed because it thought it did nothing
The previous dev had just copy pasted the same code twice and changed 2 things, instead of making a function

Python is a dynamic language, meaning it has a lack of compile time checks for correct types being passed around
It cant tell what variables exist until it looks them up at runtime and errors on you
I learned that the hard way

The solution? linters, alot of them.
I started a trip of adding type hints to all the functions, and putting mypy and pyflakes on at all times
It took months from that point, but the bot became alot more stable after then

The next solution was making error handling easier for me to get at
This removed having to ask people who run an instance to tell me the error in 3-5 business days
The bot now logs to the terminal, a file, and discord itself

Alot of time on the bot wasn't on coding, it was planning, thinking about things that could go wrong, about new features I wanted to add
Typing speed is generally high on programmers but it doesn't really matter, it was rare I could just type fast because I stopped to think about what was going on
There was one time I typed as fast as I could, I had planned out an entire feature, everything needed to implement it, all that was left was coding it
And that time was spent coding, as fast as possible, the scene you see in every hacker movie
That was once over currently 11 months, movies lie

Something you can never truly learn without experience is the importance of compile time > init time > run time
By pushing checks and errors closer to compile time you can prevent bugs reaching end users
One of the things Sonnet does for that is the database handler layers, the bot commands dont directly write any sql, or even work in a table context
They call a function that handles all the abstraction, preventing errors from writing bad sql or messing up the database structure
You will never get a true appreciation for compile time checks until you have had something crash on end users at runtime, repeatedly

Sonnet was built to maintain compatibility with its predecessor, Rhea, yeah that died really fast
Backwards compatibility is great and should be used, except when the backwards is truly backwards, and used by a total of one person

On that note, command API backwards compatibility has not changed since V1.0.1
Kernel API backwards compatibility has not changed since V1.1.0, the introduction of the kernel system

Dont break backwards compatibility, there is no justifiable reason to, just plan things out before you code them, and realize they are shit months into development
Sonnet regrettably has some of that, instead of removing it just slap a warning on it with what to do better, its not that hard

End users are 2 things: stupid and untrustable.
If you want people to know how to use anything you make you need to write things that are obvious to you, like that [] means optional arguments
Never pass complex control to them, they will hack it
Never mix metadata with data, they will hack it

Speaking of security through layers, build layers
Once there was a replacement function which allowed users to put the start and end contents and loop it over a list with sh syntax
Seems safe right? Wrong
Putting "&{1} &{1}" "&{2} &{2}" (repeated) made it replace the previous ones with the next ones and so on until you have exponential growth
This was a problem, but only a contained one, it grew worse when someone figured how to execute commands with those arguments
Ever wonder what 2^32 commands to warn a user looked like? alot of db pings and eventually the OOM killer

There were 2 stages of patching, making the replacer only accept the full placeholder name and not just a blind .replace
And limiting the amount of times the command they used could run to 1000 times, more than any end user would use, but much safer
Why wasn't it limited? "End users literally cant write more than 2k chars whats the worst that can happen?", never assume limits, define them.

This is just a small list of anecdotes from coding Sonnet
There are more stories, but I dont want to drag this blog on, so im leaving it off here

-- Ultrabear, Happy coding, always read documentation!