28 karma · joined November 16, 2023
Sometimes it came up with very funny stuff, but mostly non-sense.
The other ceremonies (like sprint planning/review and retro I find mostly a waste of time and don't go unless I am forced to).
JIRA tickets, I can create them if needed but I can pump out way more code if I don't need to waste time on those :D
If the interruptions happen early in the morning so I never have the 2-3 hours boot up time, then that day is pretty much a zero from lines of code produced perspective.
Note: if it's some trivial boilerplate code then I can even be productive without booting up and with constant interruptions, this only applies to things I don't know how to do and need to research/think
But anyway, good job, Postgres is quite a DBA unfriendly system (although better than it used to be still pretty bad)
In my experience it is generally wise to avoid abstractions and copy/paste things a couple of times, once the code base matures good abstractions will be more obvious. Even then it's good to think about future changes, will these 2 things want to evolve separately in the future? If the answer is YES, then maybe coupling them is not a great idea. I think there was a really good Kent Beck talk about coupling vs cohesion somewhere.
Another thing to think about is breaking things, if changes are local to one single endpoint then any changes there can only break that endpoint, edge cases and scenarios to consider are only relevant to that endpoint. When changes to a core abstraction are required then hundreds of use cases/edge cases need to be considered - why are we creating so many core abstractions in our systems in the name of DRY?
I've also found that the more moving parts you add the harder a system becomes to learn, the S in SOLID is probably to blame for that. The only single responsibility principle is useful for is unit tests (easier to mock), but many times harder to understand. If the actual functionality is not local to the file things become ungreppable via code search, understanding the entire system requires an IDE and jumping around to each and every beautiful lpad() implementation and trying to piece what is happening one 3 line function at a time.
Then there is also layering to consider, if 2 pieces of code look somewhat similar but belong to different layers (example controller and DAO layer, then also care must be taken to not make an abstraction that couples these together, or to couple 2 unrelated modules together that could otherwise have their own life cycle).
These are just some aspects I could think of that I think about when creating abstractions, but somehow I see engineers focus too much on DRY. Maybe they got burned so bad some time in the career by forgetting to change something in 2 places?
Then to handle any load we need to build autoscaling and spin up the toaster to medium potato and 20 instances (this costs 60k a month, but no worries we only pay for what we use so we will only run this for 27 minutes during our big sale).
Oh what wonderful world we live in and the pain we inflict on ourselves.
GJ Shopify for running a sane (tm) tech stack :)
(btw of course Rails scales it's shared nothing setup, spin up infinite app servers as long as the db can handle it. It's pretty expensive for compute though)
If you really need to use JWT-s then store the refresh (just normal UUID looking token that is validated on the backend) token in a httpOnly cookie and JWT in local/session storage, use 10-15 minutes expiration and you are somewhat OK on logout= (the XSS is still maybe exploitable). On logout make sure to invalidate the refresh token.
In my opinion a better way is to just use a good old encrypted/signed/httpOnly/sameSite UUID=123 cookie, convert that to a JWT in your APIGW/BFF when talking to backends.
I would not try to cram JWT-s into cookies they are too big, but maybe these days nobody cares about the extra bytes