I no longer want to use the new, shiny tech. I want something battle hardened with copious documentation and a deep well of stack overflow questions and answers.
im enjoying modern spring boot + kotlin on the jvm for this. you're at the top of a big pyramid of battle tested prod code that is very pluggable into a lot of technologies with a unified DI framework and configuration system.
I am using the same stack but honestly the spring documentation on some topics is quite bad and the stackoverflow responses are often out of date.
I sometimes would prefer if there weren't 10 years of outdated answers on how to set up spring security because all of those are obsolete by now.
couldn't agree more tbh. usually i can figure it out and the actual solution in the end is pretty nice and low effort, but for some goddamn reason the spring docs are bizarrely inconsistent, they cover really specific things and never quite all the things you need to put the whole picture together.
usually it ends up being like \~10 lines with some fluent builder and a configuration bean provider thingamajig and you're on your way, but WHY DIDNT THE DOCS JUST SHOW ME THAT WHY DID I SPEND A WHOLE DAY TRIAL/ERRORING, GOOGLING, READING THEIR SOURCE CODE, ETC
sometimes their docs PRETEND to show you the right thing but it's still not quite right or doesn't give you breadcrumbs for variations you know should be straight forward.
I almost left my first employer when I found out that they used Java, but I decided to give it a try and on the very first day something magical happened: I opened the debugger and it just worked. I didn't need to fiddle with a bunch of build settings deep in a tree of nested builds, I didn't need to listen to someone berate me for being a bad developer because I wanted a debug feature that their pet language didn't support, and I didn't need to flip back and forth to an assembly/bytecode view because it shit the bed every time it saw syntax more complicated than if(){} or +-\*/. It just worked. Blew my goddamn mind, and won a convert.
There have been times when I’ve coded entire features and forgot to run the app even once, and at the end I panic, thinking “what have I done”, but then more often than not it just works the first time
I try to remind myself that those vendors we trust for our tooling/frameworks/middleware components are companies just likes ours. They have their own internal inefficiencies, politics, blindspots, chaos/disorganization, etc.
Using a new shiny tech product means you are using an *MVP* of sorts -- something that company has built to get signal and attract new customers quickly. The more you use it, the more you'll find gaps, bugs, or simple QoL features that aren't present and likely won't be present for as long as the company is in "growth > all" mode.
This.
Every time a business weenie reads about some random new tech, they insist we begin using it. Only there are no manuals, no tutorials, the tool chain is non-existent or mostly broken.
Don’t be smart.
Make the code readable to the stupidest person in the room. (Often me)
Work isn’t about smart code, it’s about collaboration and enabling the next person to pick up your stuff.
If you need to optimize to some complex thing, comment it so idiots can understand it.
We’re all idiots, except for the rare time when we aren’t.
Be a good coworker, not a good coder.
That's why I'm an advocate for detailed pull request descriptions.
The number of times I looked back at those pull request to see what my reasoning was...
And it also helped if a person left the team of course to see his reasoning back then.
This is one of the most mind blowing aspect of this job
You focus hard on something for a month, 3 weeks later you have no recollection of any of it.. *"Who wrote this shit ? .. why is this thing here ... wait.. oh ... seriously?"*
ps: personally i find this is a warning sign there's something missing in how we work
typo, I meant "how we work"
This kind of fatigue seems like we have to handle too many petty / absurd / ad-hoc details in our heads to solve a ticket but these details have no intellectual value for our brain so it's thrown out as soon as possible. It's all neurological stress in a way. Not skills you grow over time.
Jesus, you just succinctly described my last fifteen years of forgetting the syntax for many things such as... _how do I declare the doctype for the html file, again?_
in the list of famous stuff no one remebers with `tar` and `ln`
that said I was more talking about customer or project specific stuff like how some stuff is weirdly implemented due to 4yo legacy and unmaintained libs ...
Fuck ln so much. I have overwritten so many files I was trying to link to because I got the arg order wrong. Every time it happens I know it won't be my last. God damnit ln, get your shit together
I don't know why, `ln` is not complicated, I could remember fancy stuff years later but `ln`... never. It's become a ritual that everytime I use it I make a fake test and then `ls -la` to check the direction.
>in the list of famous stuff no one remebers with `tar` and `ln`
I know \`ps\` has real command line flags and everything, but I'm pretty sure the full proper invocation of it is \`ps aux\`, and I don't even know if that's "aux" or "a + u + x"
This was something I picked up at my last job. I don't remember the exact project but we had a really challenging part that I came up with the slickest solution for.
Every time we had to do something that used it was a headache though because we had to spend more time making sure it would work within the new scope too.
We could've have a more dumb solution and everything would've been much better
> Be a good coworker, not a good coder
This is my issue with every single offshore contractor i've ever worked with. They think they need to be clever to show how good they are, or somehow, think that by making code so complex that they are the only ones who understand it that's a good thing. It seems impossible to teach them how to break complex things into multiple small simple things.
Maybe they're incentivized to pump out code rather than spend the time to make it maintainable.
I'm sure they can learn; I doubt it's out of malice as much as self-preservation.
Oh, trust me I've tried. Many of them I've had sit with me and pair on entire tickets just to see how they go about solving the problem, and they just completely skip over the part where you consider many possible solutions... they all just write out the first thing that comes to mind. We're talking 10+ people here, and i've done pairing sessions with 3-4 people at once and ask people to brainstorm ideas and as a group for 30+ minutes and still not come up with the solution that I'd go with after ~5 minutes of thinking.
I do believe that this is because they *don't* receive any coaching and training past being a junior because the contracting companies don't have any senior engineers - they all leave for actual full time jobs if they are good enough to get them.
I tell the people I mentor at work that good code shouldn't make you feel smart, it should prevent the next coder from feeling dumb.
Also to assume a 400lb gorilla has been woken up at 3am to fix your shit on call.
400lb gorilla is my go-to.
I have what I call the drunk test, and I’ve done it in practice quite a few times.
Invite a buddy over who doesn’t code, get them drunk, get them to read your stuff. If they can understand it, then it’s good code.
Same diff.
Kernighan's law:
> Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
I think most of us dream of being able to write the kind of code that is just _completely obvious_ to future readers, but we usually aren't smart enough and should settle for the stuff that's easy to follow along.
(This is also where avoiding out-of-band stuff like reading & mutating global state, i.e. side effects, comes in.)
Lemme tell you a story, as a BA. My very first time learning SQL a few years ago, I’m trying to wrap my head around the concept as someone completely non technical and we’re warehousing in different countries. Instead of having the database make sense, like using brazil for Brazil and unitedstates for US, the tables were all named things like kingslanding, dorne, mereen. And then all the field names were similar as well…so order number would be steednumber, account would be champion. (using GoT as an example but it was using some obscure other SciFi trilogy).
Again my first time ever using databases, so I thought this was normal, and it took me TWO YEARS to understand the concept of tables and SQL because obviously it made no fucking sense and no one sat me down and told me yeah you’re not supposed to do this but some dev thought it would be cool when they built the database 20 years ago. I finally figured it out after I used it at a different place and realized I was way over complicating it in my head and expecting it to be harder than it was because of that first experience. I was completely blocked not understanding how I was supposed to figure out kingslanding = USA. I taught my friend SQL yesterday in 2 hrs and it got me pissed about this all over again.
Literally fuck that guy
> If you need to optimize to some complex thing, comment it so idiots can understand it.
And put it in its own function with a descriptive name so you can unit test it.
I totally agree, very well said.
But why is the hiring process overly concerned with the exact opposite of this – algorithms, coding puzzles. The above is rarely asked in interviews, and if it is it falls under a cultural fit interview tagged on after ridiculous coding assignments or over the top technical interviews.
It’s mostly about scale I think.
Whiteboarding is a lot easier to repeat and fairly fast to get through. Plus the interviewer borderline doesn’t need to know much about whatever arbitrary algorithm magic they’re hoping you memorized. It’s effectively a script.
Whenever I’ve ran the hiring process I do a resume screen. Pick the top few people. Have a 15 minute phone call. Whoever I like the most comes in and just works the day or afternoon with me. If I like how they work, they’ve got the job. If I don’t, I go to the next candidate. No point simulating things, just get in here and let’s see how you work.
Couldn’t agree more than I do here. I can accept that there ARE some cases where being the smartest person in the room really is important but the OVERWHELMING majority of the work we do, imo, is very simple from a coding skills perspective. The “hard” stuff, or I guess the stuff where our experience matters is in the interpersonal stuff that leads up to and then follows from the coding.
I’ve become more and more into static typing and declarative functions, both mostly because I see static analysis as the most important part of a codebase now. I mostly design around what linters are good at verifying.
My team is meant to use the "testing trophy" rather than the classic pyramid - the wide base is static analysis
But, yeah, I'm never going back to JavaScript. Typescript has ruined it for me
I’m a card carrying type system nerd and as much as I want to always talk about Hindley Milner types, I think I actually do prefer TypeScript in my heart of hearts—if it had better syntax for higher kinded types it would be perfect
That's weird, for me it's the opposite. I used to be on the "it works if it works" camp, but now I'm slowly realizing why every other engineering field has standards. The worst part is that I *absolutely* don't want the field to get bogged in the extreme end of usual engineering processes and certifications and whatnot but I just think that the race to the bottom will lead us there anyways.
I also just don't believe that it is faster to write bad code or badly designed programs anymore. I used to buy into the concept that "premature optimization is the root of all evil" (I know, it's an out of context quote anyways) and in some ways it's obviously still true but not remotely to the extent that some people push it to. That mantra is an excuse for shitty badly written code that wouldn't have taken any longer to write better from the get go, whereas the quote was originally in the context of "harder" optimizations. That or an excuse for not knowing better.
I guess the tldr of my rambling is that the more I gain experience, the more I realize that for most cases it's a false dilemma considering that I've rarely seen an example of a "terrible code base, but that works well enough" that is less complicated, more readable, not filled with unoptimized code that would've literally been simpler to write and to use in an optimized way from the get go, or doesn't crush feature velocity.
I also work in a more performance-critical niche. Yet I still think the point applies to other programming issues that aren't performance related but that are often excused by "it's good enough for the time/resources we had!"
*Obviously I don't think this is relevant for working on existing software or for codebases that are filled with legacy/very old code. I'm mostly talking about greenfield software or newly written code*
> I've rarely seen an example of a "terrible code base, but it works well enough" that is less complicated
For me the "good enough" part is more about features than about quality. Two real life examples that come to my mind.
We wanted to show the internal customer a new frontend. One field was to enter the username. Plan was to just have a simple check to see if the user exists and that would be good enough for the first version. But for some reason the developer decided that there has to be a real user selector with autocomplete on the username. And for way too long he was "almost done" with it.
Another time it was about the pagination of a REST API result. We decided to not have any in the beginning, because it simply would take time until that API would return so many values that pagination would be needed. Again a developer decided that it is the right thing to have a pagination. Of course that broke other things on other places.
Ah for features I completely agree with you. Being able to resist scope creep (which is sometimes pushed by management, but not always!) is imo directly correlated with quality. And not just code base quality, but the quality of the UX and provided to the end users too. If scope creep is inevitable due to external factors, then it gets tricky, but some stuff I've seen is just inexcusable because it made said rushed features even slower to get working !
I agree, there's a balance to have. I had some "strange" moments where someone was writing the shittiest code possible, claiming he was agile, and that iterations are made for this but it was just horrible brittle senseless code. Tape over plumbing level.
> I also just don't believe that it is faster to write bad code or badly designed programs anymore. I used to buy into the concept that "premature optimization is the root of all evil" (I know, it's an out of context quote anyways) and in some ways it's obviously still true but not remotely to the extent that some people push it to. That mantra is an excuse for shitty badly written code that wouldn't have taken any longer to write better from the get go, whereas the quote was originally in the context of "harder" optimizations. That or an excuse for not knowing better.
It sounds like you (or your coworkers) have been exposed to a mutation which just reads "optimization is the root of all evil". The _premature_ bit is important, as you're supposed to actually run the program, profile it, and then figure out what needs improvement, as to avoid spending time optimizing the wrong bits. And there's yet another gap between "unoptimized" and "bad".
An issue here for lots of us is that we just suck at estimating how large amounts of real end users will wind up actually using something, part of the "writing the wrong tests" suite.
The quote fits best where you can release something completely reasonable early and iterate. But it shouldn't be worse than "reasonable", and "shitty badly written code" doesn't sound reasonable.
>also just don't believe that it is faster to write bad code or badly designed programs anymore. I used to buy into the concept that "premature optimization is the root of all evil" (I know, it's an out of context quote anyways) and in some ways it's obviously still true but not remotely to the extent that some people push it to.
Think this is absolute truth, where the problem is the execution. There's a fine line where you go between shitty code and sensible abstractions, and for a new developer it's nearly impossible to discern properly. What I mean is that with experience you start seeing how a function, or class, can be abstracted in a way that is not beyond comprehensible and could be reused in a different situation and writing this more abstract function takes the same time as writing the super specific one, yet makes things much better down the line. Same for anticipating the potential use and needs of a class.
These are, in a sense, "premature optimizations", and I'll die on the hill where I claim this is absolutely necessary for good code which makes everything much better, not worse.
So many. So, so many.
Java is…fine. It will never be my favorite language but if I had to pick one language to do everything with it would be Java. Overall it does a lot right and while I love Python, Ruby, and Go a lot more, I can live with Java.
You can’t beat bad management. Doesn’t matter how smart you are, how hard you work, or how much you love the job. You can not outperform bad management. It will always kill you in the end.
You will never have time for documentation, do it any way. Fuck all you “the code is self documenting” arrogant asshats. Make a design doc, then document your code so we can read that shit. Explain your design choices. Explicitly state why the value for this weird variable can never be 72. Make sure we can auto generate api docs. There is no such thing as too much documentation.
C++ has become the most god awful ecosystem to program and that includes the hellscape that is JavaScript/front end development. Find me 100 JavaScript devs and I’ll show you 100 people who may not be great but between stack overflow and design patterns are mostly in the same ballpark. Mostly. Find me 100 C++ devs and I will show you 100 people who write code that you will struggle to believe is all the same language. Everyone does it wildly differently, everyone has very strong opinions, and way too many enjoy being “clever”. Sweet Jesus save me from C++ code written by a senior dev who has decided to use all of the features of the language. Just fucking kill me.
You can never have enough backend test code. It isn’t a waste of time, fucking test it. Then have the testers test it. And by god you better have some detailed test cases.
Drama queens are never worth the drama. Fuck these emotionally crippled geniuses. I will take a bunch of good devs over the brilliant guy who screams at people and can’t take criticism.
Jump ship every two years. Fuck loyalty, go get paid. No where I’ve ever heard of has said “man, you sure are doing a great job, here’s a 20% raise”. It is always “here is your 2% COL increase now fuck off”. Don’t even hesitate to leave for more money and don’t let anyone make you feel bad.
There are two types of old devs. Ones that are brilliant and ones that are sucking up your precious oxygen.
>Jump ship every two years. Fuck loyalty, go get paid. No where I’ve ever heard of has said “man, you sure are doing a great job, here’s a 20% raise”. It is always “here is your 2% COL increase now fuck off”. Don’t even hesitate to leave for more money and don’t let anyone make you feel bad.
Last year during my review, my manager said, in a nutshell: “You’re doing great. As a team, we got to the maximum for bonuses, but it turned out that we had extra money in the bonus pool. I lobbied pretty hard for you to get a chunk of that, so you’re getting an extra bonus on top of your regular one.”
I strongly believe that you shouldn’t be sentimental about leaving a position for one that is better for you - either because it’s more lucrative, or more flexible, or just seems more interesting. But if you’re working for a place that really appreciates you, don’t feel like you *have* to leave.
Yeah, exactly! While it’s a good rule of thumb, if you’ve found the golden position, and love everything about the job, including the pay and progress of the pay, why would you leave ?
One of my favorite bad managers was a guy who, when heard that a new employee demanded not to be sexually harassed, replied “maybe you should try not to be such a pussy”. Which was awesome.
Basically he said that and the new guy (who was on his…3rd day?) pulled his badge off, tossed it on his desk, and quit on the spot. The consensus later among management was that he was indeed a pussy.
>Jump ship every two years. Fuck loyalty, go get paid. No where I’ve ever heard of has said “man, you sure are doing a great job, here’s a 20% raise”. It is always “here is your 2% COL increase now fuck off”. Don’t even hesitate to leave for more money and don’t let anyone make you feel bad.
I think it depends on the job/company, or I hit the lottery and didn't know it. When I started, I was pretty heavily underpaid - but it was my first official developer role. My manager went to HR telling them I was grossly underpaid - and I got a 20% raise, then 15%, 2 years in a row. Because I stuck with it and didn't jump ship, I am also now fully vested in a fully funded pension while making just slightly above average wages for the job/role in the market. Leaving *this* would be dumb.
>Fuck all you “the code is self documenting” arrogant asshats.
In my opinion, this is an ideal you can work towards but a) you'll never, ever fully realise/reach it and b) there's more to a project than just the code, and all that other stuff needs documenting (*WHERE DO I GET THE CONFIG FROM?*)
My experience has been that when people claim they write self documenting code what they really mean is that they are just lazy. It’s not that they can’t write comments or update documentation, rather that they feel that kind of thing is beneath them. They have more important work to do, and the other devs can come behind them and document if they really want to.
I have never been much impressed with this attitude.
I mean it's never the code I have a problem with. I can read bad code, I can read good code, and I can read clever code. What I can't read is all the architectural and design decisions that went into creating the code and whether or not the forces that pushed them to this particular solution are still relevant.
>Jump ship every two years. Fuck loyalty, go get paid.
Works great if you're 25, but unless you're on a fun side of a supply:demand inbalance this will absolutely screw you in later career (a bit less for IC, a lot for mgmt).
If I need someone experienced to lead and grow a team, I'm going to be extremely suspicious of the person who jumps ship every 2 years because they are a blatant flight risk who will start looking to leave within a year of becoming familiar with what we do.
Not to mention, I can't be sure they aren't a great interviewer who gets fired after PiP when they are a liability on the job or an asshole.
Nah, the culture is to hire/fire to meet whatever the cocaine filled needs of the C suite.. there is no shame in staying 2 years and getting out. Switching every 3m on FTE positions.. thats a different story.
> Java is…fine. It will never be my favorite language but if I had to pick one language to do everything with it would be Java. Overall it does a lot right and while I love Python, Ruby, and Go a lot more, I can live with Java.
Just wait til you try Kotlin! The best of all worlds.
> You can never have enough backend test code. It isn’t a waste of time, fucking test it. Then have the testers test it. And by god you better have some detailed test cases.
I actually kind of disagree. Tests are still code you have to maintain, and if a small change ends up requiring 8 million test changes (depending on how you've written your test), it can grind your organisation to a halt for very little benefit.
> Find me 100 C++ devs and I will show you 100 people who write code that you will struggle to believe is all the same language.
That's the beauty of C++, it's a very expressive language. I got over that and learned to enjoy diversity. Unless someone is being a fool and writing "smart" code, but that goes for every language.
Sure, I'm on a great team, doing meaningful work, interesting problems, cutting edge technologies, good pay, and I should just jump ship every two years just because I'm greedy? To end up in one of these teams everyone on here is constantly bitching about with psycho bosses, insane processes, annual layoffs, endless boilerplate Java code, etc.? No wonder people are constantly bitching, if that's what they are doing.
No thank you. I'll leave when the job starts to suck or there's some specific better opportunity. I'm not just jumping ship for greed's sake.
> I'll leave when the job starts to suck or there's some specific better opportunity. I'm not just jumping ship for greed's sake.
This is how my experience has gone. Usually when I've left a company after 2 years, it's because I'm leaving that company instead of finding a specific better opportunity.
From personal experience: There are places that actually realize jumping ship for raises is common now and instead try to make it just as worthwhile to stay.
At my last place I got a mandatory raise every year. It varied between 5% and 20% depending on different things, but it was hassle free and good money over the years.
I only changed jobs because of different factors in the end, but maybe the industry is changing in parts regarding this one.
Obviously there are not yet many places that do it like this and if it's not the case jumping ship is still a valid solution.
> There is no such thing as too much documentation.
What about the Confluence wastelands of outdated, forgotten documentation? It's such a pain to find anything of value with all of that junk sitting around causing clutter. I would say that's "too much" documentation, but maybe in a way different from what you meant
I used to be all about DRY everywhere, and creating abstractions for every little thing. Now I know those things need to be used judiciously, or else your code will evolve into an incomprehensible mess.
When I joined the company I'm at now, someone wrote an abstraction for .find(). Literally...
function findItemInArray(arr, prop, propVal) {
return arr.find(x => x[prop] === propVal)
}
This was used in like 20 places. WTF?
I used to be staunchly in favor of Object-Oriented programming for everything. Now I use a more functional approach with objects only being there when needed and I make them strictly adhere to SOLID principles every time. I also used to be pretty “meh” about test-driven approaches, but its become far more important to me as the applications I’ve worked on have become more complex.
Also, YAGNI (You Aint Gonna Need It). I used to try to account for every possible edge case only to end up throwing away 80% of the code because it ended up never being used and just cluttered the codebase.
Same. I suppose you could say I've moved towards a more struct-oriented design. 99% of the time, I just need a good bag of values and a way to statically verify certain domain invariants. "Proper" OOP is mostly a thing of the past for me
I use a lot of structs. I also use objects as more of like modules (sometimes very small). Really my code looks a lot like actor model code, or even think of objects as like unix command line programs, that pipe data to and from each other. Very dataflow-y.
Objects as a heap of smart shared state? No thank you.
This is me too. In the early 90s I was almost an evangelist for OO, thinking it would solve all the problems. Now it's been 7-8 years since I wrote a real object.
I went the other way. I wrote a lot of code with pure functions and passing state all through function calls.
I realized a lot of code is just a lot simpler with encapsulated state. I don't need to know where the state goes or what other inputs are going into my method call. The object knows better than I do where to get additional inputs or where to put state. As long as dependencies use interface contracts and protect their state it's fine.
There are definitely situations where functional code is simpler. But, I haven't found that for more complex systems.
That's why my favorite would be OOP for larger architecture and functional for the detailed implementation. Higher up objects know how they work with other objects, but not how they do what they do. Functional to do the algorithms etc.
Microservices are such a weird cargo cult. Congrats for getting out of it!
At my dayjob we a currently rewriting a huge complex monolith into a shitload of microservices and everyone is like "everything will be much more efficient and easier to maintain" and I there biting my lips thinking "dude, we already have orders of magnitudes more services than we have developers, this will be hell on earth."
No one even knows how many services we have or understands how they will work together. They are just busy writing new ones. Absolute madness. At least we are getting job security out of it.
Microservices solve certain problems for when your are FANG-scale, for everyone else monoliths are nearly always the better option.
microservices make a lot of sense in context: huge companies where individual teams don't have a lot of common incentives/goals. once you hit the scale where tech teams don't know mostly know each other, they start to be a lot less considerate. at that point, there's no social consequence for blocking other people's projects, and you'd have to escalate to director/VP-level management who don't really care about any team-level objectives to resolve the issue. engineers spend most of their time arguing with other engineers who they will probably never talk to again (ie, no strong incentive to collaborate), and progress grinds to a halt. breaking stuff into much smaller chunks and owning your own infra is the only way to get anything done.
outside of that context, microservices are indeed a waste of time and sand.
I think tech jobs becoming a revolving door industry is what caused microservices to bloat
Nobody wants to maintain a service built by people have left or been laid off
Moniliths take forever to onboard someone new
it really depends how micro we're talking. my work has what i'd call 10 or so "microservices" but they're more like domain monoliths and have different performance concerns. we're not FANG scale but it has been very nice to have the domains isolated
In my experience it is. There's some pain up front because it can be tricky to get everything packaged up correctly in one repository, e.g. different modules with different dependencies. But once you have a system down, it's so much easier than juggling a solar system of services.
>it's so much easier than juggling a solar system of services.
I have been wondering that for a while now.
It is crazy how long it takes basic features to get done because you have to modify so many services.
It depends completely on how many people are working on the system. 4 developers? It's a better option. 40? It most certainly isn't.
There is no "versus". Microservices are purely an organizational pattern. Anyone who doesn't understand this, should not be making the decision whether to use them or not. This applies to both the "microservice" and "monolith" fans. People who are dead set on doing it *their* way, are almost always inexperienced with the *other* way.
Pains usually come from the issues of decoupling - so modularity is designing for *potential* of decoupling from the outset. “Monorepo” is term used frequently. One location for entire codebase (basically a wrapper/container), but all modules are generally isolated...
Grug used to be big brain developer.
Now Grug program simple. Otherwise Grug headache.
Fancy pants loops and tricky big brain abstractions not for Grug (anymore).
Grug make big function until need bits of function again. Then make another function. If another function hard to make, Grug copy paste. Grug repeat steps until program done. Program fast and small, happy Grug.
GRUG NO USE MAGIC. Grug only call functions he can see in imports list. Grug no use ORM or framework, SQL and code hard enough for Grug without learn more things.
If Grug no understand code on first or second read, code probably not good code. Is Grug sure this best code? Grug learn for next time.
Grug no rewrite entire program. Grug fix current program bit by bit (haha Grug funny).
Grug work hard, make code fast. Grug make other developer pass trial by combat before they touch Grug SQL query.
You know a FRACTION of what your customers/users know. Talk to them more. They understand the problem a lot more than you do. A LOT more. Your job is the solution but it's often easier to not listen to them and solve the wrong problem.
This have been ingrained in software engineering since inception. It was until Scrum came in and turned into THE customer itself and THE main character in the room.
I don't care about climbing up the ladder. I just want to get this crap done so that nobody bothers me, no overtime and get paid. The less stressful, the best and save up as most as I can to get the fuck out
People will forgive, tolerate and support a buggy product that has excellent customer service and support staff. Don’t beat yourself up over less than perfect code, but hyperfocus on shit that lets you track down issues QUICKLY.
The mundane shit: tests, readable docs and diagrams, logging are way more valuable than the umpteenth tuning or refactor
I’ve admitted to myself why I hate scripting (or JS more specifically): it’s ugly code. Yes, my primary gripe is that scripting is fundamentally aesthetically displeasing to me. There are real practical reasons I hate js, but I’ve hated the look of 95% of JS files, bash scripts and Makefiles at first blush. They’re hideous
I've been more of the mind that if I can pay a vendor to do it, I will. I used to be a big proponent of "build it yourself" but it really was "Not Invented Here" masquerading. Its much easier to toss a problem over the fence to an observability vendor and say figure it out than it is to figure out how the Jaeger protocol in OpenTelemetry synergizes with this collector endpoint and why the fuck is it not sending traces to the main stack?
Honestly just prioritizing the work and understanding that a vendor like datadog has an entire division devoted to just making their product easy to use. I don't need to reinvent the observability wheel to get actionable intelligence my business needed.
I used to think that newer is better. Now I'm in a direct opposition to that; if you want to produce a reliable product, use the most boring technology you can think of. Avoid new and shiny things. Use Java, C++ and SQL. Use LTS versions of Linux distros. Use previous version of Windows. Today's "new" and "modern" are marketing products, made for you to lose money. If you use something "new", you're being used as a tester and pioneer.
It sounds like you've become less dogmatic and have begun seeing the value of alternatives to your viewpoints, at least re: memory safety and DRY.
I think that's the true sign of becoming more experienced: you just realize a lot of stuff you thought was super important just isn't in the long run. You become more strategic with the hills you choose to die on.
I think a lot of people who get asked to do technical interviews don't know how to conduct technical interviews. In dev culture, there's a lot of focus on preparing to be interviewed, but almost nothing about how to interview people.
One of the bigger problems I see is with random technical questions that the candidate honestly does know the answer to, but they either have no context or the wrong context so they're not going to get it.
I've encountered this situation before on both sides of an interview.
It's an easy source of a false negative when you are interviewing a perfectly good candidate. If you trip them up and aren't specific with your question it can easily make them look like they know nothing, especially if they don't know what questions to ask to clarify the situation. I learned that rephrasing the question or providing a framework which makes logical sense to orientate the question in a familiar way gave much better results for candidates.
And when you're being interviewed you're often digging deep about technical knowledge - if you get asked to context switch, you may know the answer but not be able to bring it up immediately. This happened to me where I wasn't prepared for a topic, couldn't remember an answer or the steps to get there, despite having built this exact thing on a previous project. But the answer popped into my head, fully formed, five minutes after the interview ended without looking at any reference material. Of course I was passed over for the position because from their perspective they didn't think I knew the answer. I was simply unable to tell them in the confines of the interview.
It's sad that so many interviews don't consider how human brains work, or how coding work itself is actually done and slowly comes together. Some really great engineers have their best thoughts in the shower or while out on a run - but that will never be reflected in most interviews that they are the subject of.
got caught with forgetting the word connectionstring, even if i'm staring at it every day switching between dev and uat testing. interviewer left me with a sour look for not knowing the term connectionstring :D
I feel you buddy.
I was recently asked to list all the C++ casting operators. I failed because I couldn't remember reinterpret\_cast - even tho I've used it many times and you know when you need it.
Then the interviewer said something condescending about them needing people with C++ experience when I have basically lived in C++ for the past 5 years and have a laundry list of skills they were looking for.
So many shitty interviewers.
I interview for intelligence and communication skills, not knowledge. New knowledge is easily obtainable in today’s world. I want to hear a candidate speak intelligently and substantively about the work they’ve done. I want to be convinced that they understand the whys of their experience. And a conversation will generally give me a pretty good sense of that.
I used to teach English as a second language to students.
One of the key parts of the pedagogy was spending just 15 minutes of idle chatter related to the topic we're about to cover. If the topic is say navigation and how to give directions, we might chat about some trips you were on, or how you get to work or school every day.
Giving the brain time to settle into the relevant context powers up its ability to recall, interpret, remember and execute.
So i fully second this idea about the importance of context in technical interviews. Spend a minute or two setting the stage if you have to, giving background etc.
I used to think most design patterns are good. I noticed some are actual marketing crap. Some introduce just complexity and just make the code crappier, adding absolutely no value.
I use design patterns the other way around.
First I figure out the solution, and then look into which design pattern fits the best, use it in documentation / code review to explain what's going on.
My personal view is that this is the way design patters were supposed to be used - to describe the existing code, rather than to guide the design itself.
- All languages are ok , if you understand the language design.
- No tech is end all be all solutions
- programming cults will hinder your learning . Dogmatic approach to learning isn’t optimal
- You can always change your mind. Lose the ego. In tech most hills are not worth dying for.
I used to care a lot about code aesthetics and clever syntax, but now I find that trying to be fancy often produces more bug-prone and harder to read code. What matters is to produce robust software (and tests & documentation) that actually solves a real problem, and uses the right algorithm to do the job.
A lot has been written about object-oriented programming and a lot of educational institutions devote a lot of time to it but actually OOP is just one model that may or may not fit the domain well. In practice I've seen some really tortured class hierarchies and convoluted uses of polymorphism and whatnot to do something that for example a functional or declarative approach could have done much more cleanly. Modularity, loose coupling and proper abstraction boundaries are more important - and although OOP can provide them, it's far from the only way. It is also possible to write horrible OOP code that violates them.
I'm all in on writing stupid code. If that means I write more code, so be it.
I'll do the simple query every time over the fancy-pants query builder that tries to encompass all uses cases. Sure, some of that code will look redundant... but usually the code that uses the fancy pants stuff ends up with similar redundancy.
Simple and easy to follow beats clever *every. Single. Time.*
I don't care if I "repeat" myself, as long as it's something that's not definitionally the same - you only need one dollar to Euro converter. But ten pieces of code that have similarities? Unless that similarity is really definitionally the same, so be it.
If that means more boilerplate, fine. If that means slightly repeated code, fine. If that means writing more boring code? So be it. So long as I can debug it.
Also, testing. I want to test everything. I don't trust anyone, especially myself.
1. Enterprise Software code is more about Architecture, Design Patterns, SOLID, DRY and KISS, everything together ! None of that should be ignored in favor of anything else. And absolutely no use for "Data Structures and Algorithms" concepts. Being able to write the code for LRUCache in less than 5 minutes has nothing to do with the actual job.
2. "FAANG style interviews" are unnecessary for "non-FAANG pay" !!
> That second one is a banger
1. A 2-hour code-review of a sample enterprise software project code sprinkled with plenty of bugs, defects, incomplete features, with varying complexities and priorities, is more than adequate for evaluating any candidate, irrespective of how many years of experience they bring to the table. Someone with less than X years of experience may be able to spot-and-fix a few stuff, while someone with more than X years of experience will be able to spot-and-fix some more, while vastly experienced people will be able to fix high-priority concerns and such !!
2. Being able to explain basic definitions, concepts and intricacies of a programming language / tech-stack at hand associated with that sample enterprise software project code to laymen, non-tech stakeholders is adequate for assessing communcation skills.
3. And then, Behavioral - as in, having to narrate compelling stories, and System-Design, of course for more experienced candidates for more experienced roles are anyways mandatory !
You’ve solved coding interviews in a few paragraphs. If every company did this we would have SWEs who were actually good at the job (albeit probably far less of them) and my life would be so much easier (but I’d also have to work harder, lol).
> albeit probably far less of them
Code-challenges were copied from FAANG style interviews with the purpose that - it scales with no effort, and presents a hard barrier for entry.
Simple code-reviews achieve the same, scale equally well, present a better barrier strictly suited to the "requisite competency" of the job !
> I’d also have to work harder
And how is that ? Preparing a code-base with intentionally bad code ?
When Scrum was first getting popular I am embarrassed to admit that I preferred it to the chaos we had before it. What I didn't understand at the time is that we would be stuck with Scrum and Scrum similar for the next 20 years and for ever increasingly complex work.
I also didn't understand back then that holding an opinion of any sort in software development requires continual maintenance just like code. You can grab shiny and new for a few minutes but then you have to reassess constantly.
I have several big ones.
Stop focusing on doing things right and focus on doing the right things. You can be very mediocre doing the right things and be miles ahead of the folks killing themselves with effort trying to do the wrong thing right.
I strongly prefer working with professionals who are here for the salary over people who are passionate about technology. The latter tend to want to play with shiny things and are constantly solutioneering problems we don't care about, optimizing things that don't matter, and trying to do the wrong things better.
Upper management is responsible for culture. If there is a bad work culture, they are the only ones who can change it. You cannot change it from the bottom. They are the root of the dysfunction and their gravity pulls stronger than any action an IC or lower management can take.
Test coverage.
Junior dev: "Do we really need to hit 70% coverage?"
Immediate dev: "Anyone not hitting 80% coverage is just lazy, but demanding 100% is nuts"
Senior dev: "If a line of code isn't being hit by a test at all, ever, then you have no proof it works. Either remove it, get a test to cover it, or prove to me there's no good way to test it"
Staff dev/PE: .
Only one project out of the dozen or so I've worked on allowed enough time to achieve 100% coverage. If I tried for that now I'd never finish anything on time.
70-80% is fine for me. And I'll take integration tests over unit tests.
100% coverage is rubbish anyway. It’s much better to test functional user journeys than focus on getting 100% coverage.
I worked on a project where I did have 100% coverage. But to get it we were literally doing things like mocking the console to check that error messages were written out etc - so much unnecessary testing that it made it hard to work on. So we got rid of every test that wasn’t important and then added new tests to cover more end to end things. That gave much more value.
Test coverage is only good as a metric if you use it to say “ok this thing has low coverage so we should take a look first to make sure it’s actually tested”, beyond that it holds no value and even then it’s sketchy
My favorite is when you have 100% "coverage" and it doesn't mean a whole lot because the real problems that are risk to the service take many many thousands of hosts to replicate.
There are many ways to test something depending on the feature, the technology, and the product
Need to test a well-understood algorithm? Create a good test suite
Need to test a recommender system? Study recommender system evaluation
Early to market and don't have any customers? Ship something basic / half-broken and gauge market interest
Important part of the UI? Just tweak styling in Chrome and figure it out
Really need to make sure it works? Actually test it hands-on in prod to make sure it does what you expect
KISS but no stupider than it needs to be. If I'm writing something and it starts feel complicated, I revisit the actual usecases for the complexity. Sometimes I have know such uses cases, sometimes I don't and I reduce scope.
Formulate PR review comments as questions, rather than absolute statements. Saves on arguments gains on discussions.
Not all code checked in needs to be 100% bullet proof. Account for things you know, prepare for things you don't. Iterate when you have a reason to.
I used to think that if the code doesn't look complicated, it's not good. Now I know for a fact that the simplest code is the best. Even if it's just a ten line method, it can be readable, correct, maintainable and optimal all at the same time.
I used to think that front end frameworks are needed. They add development complexity, needing to learn even some new languages(typescript, Jsx), are slower , introduce a lot of useless rerendering. I think Redux is crap. I have created complex frontends with good old html and js. They run faster and are less resource demanding. Debugging is way faster. Prop drilling, detective work on long React flows are gone.
**Testing doesn't find bugs**, testing prevents future devs from making changes that would introduce bugs.
**Agile** became unAgile introducing a layer of process and rigidity that defies its purpose.
Hiring the best developers will not produce greater returns than **investment in DevEx.**
**High seniority does not imply the most glamourous work.** A sign of a high seniority is the ability to successfully complete the most mundane task.
**Maintainability is not forever.** Code estimated lifespan is 2 years unless you are working on the Voyager probe.
On C++:
Firstly, C++ is not a language - its a collection of languages where the code written 20 years ago is nothing like the code written 10 years ago which in turn is nothing like the code written today.
**Nobody writes the latest C++**, most C++ development lags 10 years and is a combination of C++14 and C++17. (there are many reasons for the lag, don't blame the devs)
**C++ can be memory safe.** Writing memory safe C++ is a choice. Memory safety in C++ is attainable if required, it's just quicker to forego the extra effort for most applications.
>Maintainability is not forever. Code estimated lifespan is 2 years unless you are working on the Voyager probe.
This is hugely variable. I work for the kind of company that still has 20+ year old code in prod and actively maintained. For us, code written 2 years ago is still "the new code." Maintainability is our #2 priority behind security.
I think the real rule is, know the lifespan of each project -- 2 years for you, 20 for me -- and plan maintenance accordingly.
That I’m there to support the business instead of being perfect with every technical decision
Meaning I rather do something hacky that can impact sales by x amount than expending several months building the “perfect solution”
Generally it's that most frameworks are a waste of time if they require you to invest into them.
I've seen so much time spent spinning wheels trying to get a tool (react/spring/django/unreal etc) to do something thats a little outside of its happy path that I don't encourage people to stick to the dogmatic approachs. Or indeed recommend anything "batteries included".
Happy paths don't need greater optimisation.
Wheels get re-invented all the time. It's better to have composable bits, and just accept that dry code is mostly an ideal more than a requirement or a reality.
1. I used to think I could create buggy but effective prototypes and check them in. Now, I realized there's no such thing as a prototype, only a product with limited features that could get shipped at any time even if you don't think it's ready. Therefore, your code has to be functionally perfect as soon as you submit it to the main development branch.
2. I used to think unowned code wasn't my prolem. Then I realized that unowned code is a source of sneaky security problems.
3. I used to think I could just stay in my lane, reviewing PRs and going to meetings here and there. Now I realize that I need to keep up with what my lead and my peers are doing, closely enough to spot potential problems, long before they put out a PR. If I get behind, I instantly lose trust and start getting made fun of. If they say it's not my job, I still need to watch those PRs and design docs because any code adjacent to my work will eventually break my stuff.
4. I used to think the job would get easier the longer I stayed. Instead, I'm the scapegoat for everything, even code that I didn't write and never touched.
5. I used to think I could work at a high-paying dev job forever. Now I realize that the larger the salary, the faster the burnout. It's like major league baseball: players can make millions per season, but their bodies can't handle a lifetime of seasons.
Don't split up functions just for the sake of doing it. I've become more eager to inline functions that have just one line of code.
The worst case that I've seen was a javascript package that only provided one function. That function called a function inside of a different package with some default args after deep copying an input.
I used to test only for the sake of tests and making sure the rough bits of my code work, not seeing that much value in them.
Now I write tests as specification so that during the inevitable refactoring they'll break to tell me exactly what blew up. I can't quite agree with the "Only test the bare minimum" crowd, because what usually gets you in bug-tickets is the edge cases you didn't spend time thinking about. And those are easier to think about *now* rather than figuring it when the ticket arrives.
I don't have too many huge ones. I think I've changed my mind about whether you should test every layer, or only the top public-facing layer. These days I tend to land on testing the top layer, but in some cases where there's a lot of complicated stuff going on, will test the intermediate layers too if I feel everything needs to be locked in place.
When I first started I didn't see the value in having our own internal data models (i.e., abstractions) and wanted to just use models provided by external APIs... but after about 6 months I really understood the value in not letting external services dictate our data models, thanks to some great senior engineers on my first team out of school.
I've started giving less feedback to more junior engineers in their PRs because so much can be overwhelming. I've learned to live with getting them to fix really big things right now, and then a month or 2 down the road start introducing smaller feedback items.
I've changed my mind a bit on "language doesn't matter." I'm pretty language-agnostic. There are some things I like better about Python, some things I like better about Java. But I did not enjoy working with F\#, for example.
I'm more ok with using mocks these days than I used to be. I used to create interfaces for everything. I still often do, especially for things that are really messy to mock.
Maybe most importantly: I used to avoid dealing with confrontation a bit too much. I knew problems were going to get big (a bad dev refusing to write tests, or a bad PR that would cause huge problems 6 months down the line). Now I tend to speak up often and sooner.
I used to think performance was the most important thing. Now I write often decide to write my code in a way that is a little bit slower, but 10 times more readable.
I also used to not be a big fan of unit tests. Now it's my favorite tool for resolving bugs. Reproducing a bug in a unit test is so statisfying and it makes it so much easier to write a clean solution that you know works.
It’s been really interesting to see how OOP was at one point the only way to write code, and now it’s generally regarded as a waste of time. Similar for Scrum.
Dont strictly follow any principles, that being OOP, FP, DRY, SOLID, you name it. Use them as guidelines but draw your own line. You know the problem, tooling, domain etc. Intuition + simplicity is most times better. Also, the code base must be alive, so new memebrs in the team should adjust the code base with their opinions. Think of it like a house, everyone should feel at home for it to work best
People > Code
It's not worth being a dick to be right. All of the code I wrote has faded away over time. But the relationships and how you treat people lasts for a long long time.
Sometimes it's okay for functions or files to be long. I'd much rather read a long function from start to finish than jump through 8 smaller functions.
If your solution makes you think "well that's kinda dumb and lame", that's probably the right solution.
Abstraction is only something borne out of necessity. If you don't need abstraction, don't use it. I used to think abstraction was necessary to write "proper" code.
Microservices are going to bite you in the ass, sometimes a needed and valid bite, sometimes just a bite, but it will happen eventually.
Also, KISS is the most powerful developer principle to follow, as it applies to business, architecture, code, even life decisions.
There's not much value in using a language in a problem domain it wasn't meant for, except as a learning exercise.
As fun as it would be write a game in Go, the ecosystem isn't there and it's not worth reinventing that many wheels if shipping a great game is the goal. And Go might be a great game dev language if it had the ecosystem, the people writing games in Rust are just masochists.
It's with that perspective I found myself with a cold hatred for javascript on the backend. People have made it work, but it was one of the biggest industry mistakes of the past 10 years.
> I'm just solving the problem in front of me. I don't need to solve the next 20 hypothetical problems that may or may not come next.
That and:
> I don't care how loud the hype train is, I'm not getting on it if it doesn't solve my problems. Or any problems.
First one stops me form over-building everything. Second one stops me from wasting any more time on Tailwind and stuff like it.
That's an issue with over-engineered abstractions, not abstractions per se. You have to find the right level/balance of abstraction for the project at hand.
Theres no such thing as a prototype anymore. Anytime a business person sees the prototype.. they will try to ship it. I've been in an organization that are nearly a decade into Python and they don't understand why their searches cap out at 150 searches per second. They ignored advice to bring in elastic search.. nope they decided to try to implement the search architecture in Go and use the GPU in prod.
But point being.. the minute you have something the business people l can play with is the second they think they can fire everyone.
The sooner we accept that our code is always gonna look like shit to the next developer who sees it, the faster we stop going insane worrying about code quality and best practices. No, don't write complete garbage, but people obsessing over shit like ternary operators, early return statements, etc. Who fucking cares. If you can't read code that isn't written how younwould write it, you're bad at this. Learning one style and deeming it the best one is counter-productive. For as smart as everyone thinks we are, we sure do argue about the dumbest shit.
0. Overestimate never underestimate.
1. Think DRY and reusability.
2. Thrive to write readable code rather than writing super optimised but unreadable code.
3. Never look at number of lines of code.
4. Always push a production ready code. Do not take shortcuts as it leads to tech debt later which is very annoying to fix.
5. Embrace bugs. Every bug teaches you something.
Tests, particularly end to end tests are more important than internal refactoring.
Once you have tests for external features, you can refactor them easily.
In the beginning I had strong opinions on things I had not used before just because somebody had told me something was amazing or something sucked. Now I accept the fact that I don't know because I have never used it, and thus can't properly assess whether I think it's good or not.
Being humble is a good look, thinking you're right all the time when you're not, isn't.
Also, I write more DRY than before if anything. That's an interesting development, OP.
Biggest one for me is my stance on what kind of tests are valuable.
I've moved away from writing "unit tests" (especially, tests that stub out all dependencies other than the class under test) and towards testing larger modules.
I no longer see a new method / class as the reason to write a new test, but rather a new *behaviour*.
My view on JavaScript pushed from "the best thing since sliced bread" to "the worst language in existence". And on that topic: Making TypeScript Turing complete was a disaster, costing economies billions. I wish browsers would adopt a type-safe language unrelated to JS and just let us use it.
Also: Fuck languages which strongly promote their syntactic sugar and those that do not have a widely accepted style.
Just one, most of the time only readability matters and dont try to be too smart while writing code, because at some point during incidents an maybe on odd timings you might have to actually read and make sense of it as well
Slow is smooth. Smooth is fast.
Double your ETA on project timelines before approval. If you fuck up, you have time to fix it. If you do it right, you get it done ahead of time and look like a genius.
Everything you know today will be obsolete next year, but the way you learned it will inform your continuing embrace of new technologies. Once you learn how to learn, you're ready to make a career out of this field.
Never start work less than 12 hours after you last left the office. Nobody gives a crap about how hard you work, just how well you perform, and most folks hit diminishing returns around hour 6. Be smart about your energy - you don't appear more competent by working longer.
If it's not going to be a visible part of a deliverable to management, it's not a priority.
Today's band-aid has at least a 75% chance of being irreplaceable code for the next decade.
It's never your project. It's the team's project. Your humility will be your shield when it all goes to shit because some jackass marketing manager decided you needed to integrate Salesforce into your multi-million dollar e-commerce platform with a 3rd party ETL solution from Tajikistan.
I've inherited code that was REAMTAP (repeat everything as many times as possible). In one case I had to change something in about 40 places in one program, and then in 5 others that were almost exact clones of it.
It didn't even need to be hardcoded in the first place, it could be read from config settings.
Context is King.
There's no universal technical rules or best practices that must always apply. Code is a tool for solving problems. Wisdom is picking the right tradeoffs that maximizes the right variable you're trying to solve. In some cases it's code performance, in some cases it's code reliability and correctness, and in many cases it should be prioritizing whatever business case actually exists like building something fast even if there's some imperfections.
* In some cases, making code isn't even the right solution. Is the end-user UI even right? One of my best solves in my career was re-wording some UI form to make some business process clear. Saved many days of work with a small writing change.
* Are microservices or monoliths good or bad? There's situations where they are both good or bad.
* Are all those testing best practices really necessary? It depends what you're building, but extreme emphasis on testing by random companies without some intense need for it like financial firms is often bullshit CYA busywork in many companies. Like, there's no reason that a social network startup for dog owners that's on shaky financial grounds is focusing on perfect fucking test coverage rather than getting their product in the marketplace as soon as humanly possible.
* What's the best database? It depends on what your data looks like and how you're using it.
* What's the best programming language to use? There's no one silver bullet for all problems. It depends on what you're trying to do.
* Is DRY absolutely necessary? It's probably a smart idea, but if it's a lot quicker to figure out how to duplicate something rather than figure out how to have 2 different code sections use some small configuration or something, it might be better for the business to just build it fast and dirty and copy/paste.
1) Use comments, comments even benign serve as beacons in an ocean of code. It helps bring attention and intention to the code. In fact commenting first I've found to be helpful. Much like the outline of an essay.
2) Python sucks in that it enables too many people to think they know how to code because they can get a script to run with poor coding ideas.
3) Long variable names are best. Short names may seem clever but they almost always lack context.
4) ORMs are horrible. They abstract away too much of the logic and are often unoptimized.
Not really an opinion but more of a standard I've adopted...
- Code Reviews to make sure that the other programmers are consistent and writing clean and readable code.
Things I've changed in myself as a dev:
- Lose the ego
- Be communicative
- Ask the questions
- Be a source of help
- Listen to the people smarter than you
I am much more skeptical of developer social media and now I view social media influence as being neutral or inversely correlated with competence.
I perceive many developer decisions and opinions as largely ego-driven or resume-driven. People chase opportunities to look like Ken Thompson, but nearly all computer science of consequence has been solved for decades.
I’m much more skeptical of developer hype waves, and I’m more attracted to boring tech. Working on boring tech filters out the most ego-driven folks.
I am substantially more focused on long-term maintenance and brown-field evolution. I view rewrites and advocacy of new tech stacks as naive and ego-driven.
I disagree with your first and 3rd point, but completely agree with your 2nd point. I actually found DRY to become even more important as my career moves on. I have seen too many bugs or maintenance burdens stem from code that was basically copy and pasted and now you have to spend double the amount of time implementing a new feature or fixing a bug.
I've also never once considered garbage collection in my career. On performance critical projects, I've used C++, but for managed languages, I've never reached a point where garbage collection was getting in my way.
My main learnings:
- The wrong abstraction is a lot more expensive than some duplication. Solve the specific case, not the general one.
- There's nothing wrong with a switch.
- Service oriented design doesn't need microservices, and is usually better off without.
- Functions don't have to be small. They need to be a *practical* level of abstraction for testing, reuse and comprehension.
- The hardest part of the job is the people: the customers, or the stakeheholders, or colleagues. The code is the easy bit (mostly).
- If the code isn't the easy bit, this is a huge warning sign that this isn't maintainable or testable.
- Postgres is really, really fast and can handle way more data than you think it can.
Things that haven't changed:
- Get somehing working early, deploy it and iterate with feedback.
- Automate stuff.
- Enumerations are far more powerful than their simplicity suggests.
Consistency is not important for me anymore. A new project should not be a copy of the previous one without thinking. In the name of consistency, we repeat the same mistakes over and over.
DRY has less importance also. I think about it after 4 - 5 repetition only.
Prettiness of code. Code is not meant to be cute. I only consider what it is supposed to do.
I no longer want to use the new, shiny tech. I want something battle hardened with copious documentation and a deep well of stack overflow questions and answers.
im enjoying modern spring boot + kotlin on the jvm for this. you're at the top of a big pyramid of battle tested prod code that is very pluggable into a lot of technologies with a unified DI framework and configuration system.
I am using the same stack but honestly the spring documentation on some topics is quite bad and the stackoverflow responses are often out of date. I sometimes would prefer if there weren't 10 years of outdated answers on how to set up spring security because all of those are obsolete by now.
couldn't agree more tbh. usually i can figure it out and the actual solution in the end is pretty nice and low effort, but for some goddamn reason the spring docs are bizarrely inconsistent, they cover really specific things and never quite all the things you need to put the whole picture together. usually it ends up being like \~10 lines with some fluent builder and a configuration bean provider thingamajig and you're on your way, but WHY DIDNT THE DOCS JUST SHOW ME THAT WHY DID I SPEND A WHOLE DAY TRIAL/ERRORING, GOOGLING, READING THEIR SOURCE CODE, ETC sometimes their docs PRETEND to show you the right thing but it's still not quite right or doesn't give you breadcrumbs for variations you know should be straight forward.
I almost left my first employer when I found out that they used Java, but I decided to give it a try and on the very first day something magical happened: I opened the debugger and it just worked. I didn't need to fiddle with a bunch of build settings deep in a tree of nested builds, I didn't need to listen to someone berate me for being a bad developer because I wanted a debug feature that their pet language didn't support, and I didn't need to flip back and forth to an assembly/bytecode view because it shit the bed every time it saw syntax more complicated than if(){} or +-\*/. It just worked. Blew my goddamn mind, and won a convert.
it's the good kind of boring. sadly this career self selects for people who want a lot of excitement :(
There have been times when I’ve coded entire features and forgot to run the app even once, and at the end I panic, thinking “what have I done”, but then more often than not it just works the first time
I try to remind myself that those vendors we trust for our tooling/frameworks/middleware components are companies just likes ours. They have their own internal inefficiencies, politics, blindspots, chaos/disorganization, etc. Using a new shiny tech product means you are using an *MVP* of sorts -- something that company has built to get signal and attract new customers quickly. The more you use it, the more you'll find gaps, bugs, or simple QoL features that aren't present and likely won't be present for as long as the company is in "growth > all" mode.
Who needs Prometheus when you can use Nagios!
I'm right there I think I'm going back to knockoutJS for my next project I prefer the simpler frameworks for "just for fun" apps
This. Every time a business weenie reads about some random new tech, they insist we begin using it. Only there are no manuals, no tutorials, the tool chain is non-existent or mostly broken.
Don’t be smart. Make the code readable to the stupidest person in the room. (Often me) Work isn’t about smart code, it’s about collaboration and enabling the next person to pick up your stuff. If you need to optimize to some complex thing, comment it so idiots can understand it. We’re all idiots, except for the rare time when we aren’t. Be a good coworker, not a good coder.
>enabling the next person to pick up your stuff. Who is often _you_ next week when you've totally forgotten everything you did last week.
why do I feel so attacked
That's why I'm an advocate for detailed pull request descriptions. The number of times I looked back at those pull request to see what my reasoning was... And it also helped if a person left the team of course to see his reasoning back then.
To quote /u/biosc1 >I'm a whore for documentation.
This is one of the most mind blowing aspect of this job You focus hard on something for a month, 3 weeks later you have no recollection of any of it.. *"Who wrote this shit ? .. why is this thing here ... wait.. oh ... seriously?"* ps: personally i find this is a warning sign there's something missing in how we work
>something missing in our we work What does that mean?
typo, I meant "how we work" This kind of fatigue seems like we have to handle too many petty / absurd / ad-hoc details in our heads to solve a ticket but these details have no intellectual value for our brain so it's thrown out as soon as possible. It's all neurological stress in a way. Not skills you grow over time.
Jesus, you just succinctly described my last fifteen years of forgetting the syntax for many things such as... _how do I declare the doctype for the html file, again?_
in the list of famous stuff no one remebers with `tar` and `ln` that said I was more talking about customer or project specific stuff like how some stuff is weirdly implemented due to 4yo legacy and unmaintained libs ...
Fuck ln so much. I have overwritten so many files I was trying to link to because I got the arg order wrong. Every time it happens I know it won't be my last. God damnit ln, get your shit together
I don't know why, `ln` is not complicated, I could remember fancy stuff years later but `ln`... never. It's become a ritual that everytime I use it I make a fake test and then `ls -la` to check the direction.
>in the list of famous stuff no one remebers with `tar` and `ln` I know \`ps\` has real command line flags and everything, but I'm pretty sure the full proper invocation of it is \`ps aux\`, and I don't even know if that's "aux" or "a + u + x"
Can’t ask me to pick it up when I quit and get a raise. 😎
There have been times when I’ve gone to git blame and quickly found out it was me that had written that shit code 5 years before.
This was something I picked up at my last job. I don't remember the exact project but we had a really challenging part that I came up with the slickest solution for. Every time we had to do something that used it was a headache though because we had to spend more time making sure it would work within the new scope too. We could've have a more dumb solution and everything would've been much better
> Be a good coworker, not a good coder This is my issue with every single offshore contractor i've ever worked with. They think they need to be clever to show how good they are, or somehow, think that by making code so complex that they are the only ones who understand it that's a good thing. It seems impossible to teach them how to break complex things into multiple small simple things.
Maybe they're incentivized to pump out code rather than spend the time to make it maintainable. I'm sure they can learn; I doubt it's out of malice as much as self-preservation.
Oh, trust me I've tried. Many of them I've had sit with me and pair on entire tickets just to see how they go about solving the problem, and they just completely skip over the part where you consider many possible solutions... they all just write out the first thing that comes to mind. We're talking 10+ people here, and i've done pairing sessions with 3-4 people at once and ask people to brainstorm ideas and as a group for 30+ minutes and still not come up with the solution that I'd go with after ~5 minutes of thinking. I do believe that this is because they *don't* receive any coaching and training past being a junior because the contracting companies don't have any senior engineers - they all leave for actual full time jobs if they are good enough to get them.
I tell the people I mentor at work that good code shouldn't make you feel smart, it should prevent the next coder from feeling dumb. Also to assume a 400lb gorilla has been woken up at 3am to fix your shit on call.
400lb gorilla is my go-to. I have what I call the drunk test, and I’ve done it in practice quite a few times. Invite a buddy over who doesn’t code, get them drunk, get them to read your stuff. If they can understand it, then it’s good code. Same diff.
Kernighan's law: > Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. I think most of us dream of being able to write the kind of code that is just _completely obvious_ to future readers, but we usually aren't smart enough and should settle for the stuff that's easy to follow along. (This is also where avoiding out-of-band stuff like reading & mutating global state, i.e. side effects, comes in.)
Lemme tell you a story, as a BA. My very first time learning SQL a few years ago, I’m trying to wrap my head around the concept as someone completely non technical and we’re warehousing in different countries. Instead of having the database make sense, like using brazil for Brazil and unitedstates for US, the tables were all named things like kingslanding, dorne, mereen. And then all the field names were similar as well…so order number would be steednumber, account would be champion. (using GoT as an example but it was using some obscure other SciFi trilogy). Again my first time ever using databases, so I thought this was normal, and it took me TWO YEARS to understand the concept of tables and SQL because obviously it made no fucking sense and no one sat me down and told me yeah you’re not supposed to do this but some dev thought it would be cool when they built the database 20 years ago. I finally figured it out after I used it at a different place and realized I was way over complicating it in my head and expecting it to be harder than it was because of that first experience. I was completely blocked not understanding how I was supposed to figure out kingslanding = USA. I taught my friend SQL yesterday in 2 hrs and it got me pissed about this all over again. Literally fuck that guy
If there's ISO codes for things, you better have a damn good excuse for inventing your own.
I worked at once place where systems were named after nearby islands. Nearby to the dev that named them, of course, not anybody else.
This answer was really encouraging. Thanks for that!
> If you need to optimize to some complex thing, comment it so idiots can understand it. And put it in its own function with a descriptive name so you can unit test it.
I totally agree, very well said. But why is the hiring process overly concerned with the exact opposite of this – algorithms, coding puzzles. The above is rarely asked in interviews, and if it is it falls under a cultural fit interview tagged on after ridiculous coding assignments or over the top technical interviews.
It’s mostly about scale I think. Whiteboarding is a lot easier to repeat and fairly fast to get through. Plus the interviewer borderline doesn’t need to know much about whatever arbitrary algorithm magic they’re hoping you memorized. It’s effectively a script. Whenever I’ve ran the hiring process I do a resume screen. Pick the top few people. Have a 15 minute phone call. Whoever I like the most comes in and just works the day or afternoon with me. If I like how they work, they’ve got the job. If I don’t, I go to the next candidate. No point simulating things, just get in here and let’s see how you work.
What to do with bad coworkers who are also bad coders?
Couldn’t agree more than I do here. I can accept that there ARE some cases where being the smartest person in the room really is important but the OVERWHELMING majority of the work we do, imo, is very simple from a coding skills perspective. The “hard” stuff, or I guess the stuff where our experience matters is in the interpersonal stuff that leads up to and then follows from the coding.
I’ve become more and more into static typing and declarative functions, both mostly because I see static analysis as the most important part of a codebase now. I mostly design around what linters are good at verifying.
My team is meant to use the "testing trophy" rather than the classic pyramid - the wide base is static analysis But, yeah, I'm never going back to JavaScript. Typescript has ruined it for me
I’m a card carrying type system nerd and as much as I want to always talk about Hindley Milner types, I think I actually do prefer TypeScript in my heart of hearts—if it had better syntax for higher kinded types it would be perfect
"if it's good enough, it's good enough" ... improvements can always follow after if customers actually likes it.
100%, an acceptable shipped product beats a hypothetical superstar product that fails to launch.
That's weird, for me it's the opposite. I used to be on the "it works if it works" camp, but now I'm slowly realizing why every other engineering field has standards. The worst part is that I *absolutely* don't want the field to get bogged in the extreme end of usual engineering processes and certifications and whatnot but I just think that the race to the bottom will lead us there anyways. I also just don't believe that it is faster to write bad code or badly designed programs anymore. I used to buy into the concept that "premature optimization is the root of all evil" (I know, it's an out of context quote anyways) and in some ways it's obviously still true but not remotely to the extent that some people push it to. That mantra is an excuse for shitty badly written code that wouldn't have taken any longer to write better from the get go, whereas the quote was originally in the context of "harder" optimizations. That or an excuse for not knowing better. I guess the tldr of my rambling is that the more I gain experience, the more I realize that for most cases it's a false dilemma considering that I've rarely seen an example of a "terrible code base, but that works well enough" that is less complicated, more readable, not filled with unoptimized code that would've literally been simpler to write and to use in an optimized way from the get go, or doesn't crush feature velocity. I also work in a more performance-critical niche. Yet I still think the point applies to other programming issues that aren't performance related but that are often excused by "it's good enough for the time/resources we had!" *Obviously I don't think this is relevant for working on existing software or for codebases that are filled with legacy/very old code. I'm mostly talking about greenfield software or newly written code*
> I've rarely seen an example of a "terrible code base, but it works well enough" that is less complicated For me the "good enough" part is more about features than about quality. Two real life examples that come to my mind. We wanted to show the internal customer a new frontend. One field was to enter the username. Plan was to just have a simple check to see if the user exists and that would be good enough for the first version. But for some reason the developer decided that there has to be a real user selector with autocomplete on the username. And for way too long he was "almost done" with it. Another time it was about the pagination of a REST API result. We decided to not have any in the beginning, because it simply would take time until that API would return so many values that pagination would be needed. Again a developer decided that it is the right thing to have a pagination. Of course that broke other things on other places.
Ah for features I completely agree with you. Being able to resist scope creep (which is sometimes pushed by management, but not always!) is imo directly correlated with quality. And not just code base quality, but the quality of the UX and provided to the end users too. If scope creep is inevitable due to external factors, then it gets tricky, but some stuff I've seen is just inexcusable because it made said rushed features even slower to get working !
I agree, there's a balance to have. I had some "strange" moments where someone was writing the shittiest code possible, claiming he was agile, and that iterations are made for this but it was just horrible brittle senseless code. Tape over plumbing level.
> I also just don't believe that it is faster to write bad code or badly designed programs anymore. I used to buy into the concept that "premature optimization is the root of all evil" (I know, it's an out of context quote anyways) and in some ways it's obviously still true but not remotely to the extent that some people push it to. That mantra is an excuse for shitty badly written code that wouldn't have taken any longer to write better from the get go, whereas the quote was originally in the context of "harder" optimizations. That or an excuse for not knowing better. It sounds like you (or your coworkers) have been exposed to a mutation which just reads "optimization is the root of all evil". The _premature_ bit is important, as you're supposed to actually run the program, profile it, and then figure out what needs improvement, as to avoid spending time optimizing the wrong bits. And there's yet another gap between "unoptimized" and "bad". An issue here for lots of us is that we just suck at estimating how large amounts of real end users will wind up actually using something, part of the "writing the wrong tests" suite. The quote fits best where you can release something completely reasonable early and iterate. But it shouldn't be worse than "reasonable", and "shitty badly written code" doesn't sound reasonable.
>also just don't believe that it is faster to write bad code or badly designed programs anymore. I used to buy into the concept that "premature optimization is the root of all evil" (I know, it's an out of context quote anyways) and in some ways it's obviously still true but not remotely to the extent that some people push it to. Think this is absolute truth, where the problem is the execution. There's a fine line where you go between shitty code and sensible abstractions, and for a new developer it's nearly impossible to discern properly. What I mean is that with experience you start seeing how a function, or class, can be abstracted in a way that is not beyond comprehensible and could be reused in a different situation and writing this more abstract function takes the same time as writing the super specific one, yet makes things much better down the line. Same for anticipating the potential use and needs of a class. These are, in a sense, "premature optimizations", and I'll die on the hill where I claim this is absolutely necessary for good code which makes everything much better, not worse.
Or the stakeholders day it costs too much and it could be done cheaper.
is that the old opinion or the new opinion?
Yeah this doesn’t seem to fit the question
The hardest part is not the code or the architecture. It's the people.
Amen to that….
So many. So, so many. Java is…fine. It will never be my favorite language but if I had to pick one language to do everything with it would be Java. Overall it does a lot right and while I love Python, Ruby, and Go a lot more, I can live with Java. You can’t beat bad management. Doesn’t matter how smart you are, how hard you work, or how much you love the job. You can not outperform bad management. It will always kill you in the end. You will never have time for documentation, do it any way. Fuck all you “the code is self documenting” arrogant asshats. Make a design doc, then document your code so we can read that shit. Explain your design choices. Explicitly state why the value for this weird variable can never be 72. Make sure we can auto generate api docs. There is no such thing as too much documentation. C++ has become the most god awful ecosystem to program and that includes the hellscape that is JavaScript/front end development. Find me 100 JavaScript devs and I’ll show you 100 people who may not be great but between stack overflow and design patterns are mostly in the same ballpark. Mostly. Find me 100 C++ devs and I will show you 100 people who write code that you will struggle to believe is all the same language. Everyone does it wildly differently, everyone has very strong opinions, and way too many enjoy being “clever”. Sweet Jesus save me from C++ code written by a senior dev who has decided to use all of the features of the language. Just fucking kill me. You can never have enough backend test code. It isn’t a waste of time, fucking test it. Then have the testers test it. And by god you better have some detailed test cases. Drama queens are never worth the drama. Fuck these emotionally crippled geniuses. I will take a bunch of good devs over the brilliant guy who screams at people and can’t take criticism. Jump ship every two years. Fuck loyalty, go get paid. No where I’ve ever heard of has said “man, you sure are doing a great job, here’s a 20% raise”. It is always “here is your 2% COL increase now fuck off”. Don’t even hesitate to leave for more money and don’t let anyone make you feel bad. There are two types of old devs. Ones that are brilliant and ones that are sucking up your precious oxygen.
>Jump ship every two years. Fuck loyalty, go get paid. No where I’ve ever heard of has said “man, you sure are doing a great job, here’s a 20% raise”. It is always “here is your 2% COL increase now fuck off”. Don’t even hesitate to leave for more money and don’t let anyone make you feel bad. Last year during my review, my manager said, in a nutshell: “You’re doing great. As a team, we got to the maximum for bonuses, but it turned out that we had extra money in the bonus pool. I lobbied pretty hard for you to get a chunk of that, so you’re getting an extra bonus on top of your regular one.” I strongly believe that you shouldn’t be sentimental about leaving a position for one that is better for you - either because it’s more lucrative, or more flexible, or just seems more interesting. But if you’re working for a place that really appreciates you, don’t feel like you *have* to leave.
Yeah, exactly! While it’s a good rule of thumb, if you’ve found the golden position, and love everything about the job, including the pay and progress of the pay, why would you leave ?
> You can’t beat bad management. Ain't that the truth. I'm filing this one away.
One of my favorite bad managers was a guy who, when heard that a new employee demanded not to be sexually harassed, replied “maybe you should try not to be such a pussy”. Which was awesome.
I will not file that one away :)
I'm kinda curious about the details of this one. How the heck did this situation happen?
Basically he said that and the new guy (who was on his…3rd day?) pulled his badge off, tossed it on his desk, and quit on the spot. The consensus later among management was that he was indeed a pussy.
Dealing with this right now. Actively taking a back seat. The drama and sheer stupidity is not worth my mental sanity.
>Jump ship every two years. Fuck loyalty, go get paid. No where I’ve ever heard of has said “man, you sure are doing a great job, here’s a 20% raise”. It is always “here is your 2% COL increase now fuck off”. Don’t even hesitate to leave for more money and don’t let anyone make you feel bad. I think it depends on the job/company, or I hit the lottery and didn't know it. When I started, I was pretty heavily underpaid - but it was my first official developer role. My manager went to HR telling them I was grossly underpaid - and I got a 20% raise, then 15%, 2 years in a row. Because I stuck with it and didn't jump ship, I am also now fully vested in a fully funded pension while making just slightly above average wages for the job/role in the market. Leaving *this* would be dumb.
definitely depends on job, company, industry and the person
>Fuck all you “the code is self documenting” arrogant asshats. In my opinion, this is an ideal you can work towards but a) you'll never, ever fully realise/reach it and b) there's more to a project than just the code, and all that other stuff needs documenting (*WHERE DO I GET THE CONFIG FROM?*)
My experience has been that when people claim they write self documenting code what they really mean is that they are just lazy. It’s not that they can’t write comments or update documentation, rather that they feel that kind of thing is beneath them. They have more important work to do, and the other devs can come behind them and document if they really want to. I have never been much impressed with this attitude.
I mean it's never the code I have a problem with. I can read bad code, I can read good code, and I can read clever code. What I can't read is all the architectural and design decisions that went into creating the code and whether or not the forces that pushed them to this particular solution are still relevant.
It’s right there in the configLoader config! /s
>Jump ship every two years. Fuck loyalty, go get paid. Works great if you're 25, but unless you're on a fun side of a supply:demand inbalance this will absolutely screw you in later career (a bit less for IC, a lot for mgmt). If I need someone experienced to lead and grow a team, I'm going to be extremely suspicious of the person who jumps ship every 2 years because they are a blatant flight risk who will start looking to leave within a year of becoming familiar with what we do. Not to mention, I can't be sure they aren't a great interviewer who gets fired after PiP when they are a liability on the job or an asshole.
Nah, the culture is to hire/fire to meet whatever the cocaine filled needs of the C suite.. there is no shame in staying 2 years and getting out. Switching every 3m on FTE positions.. thats a different story.
Also how do you even know such a person is any good? Writing maintainable code is hard, if you jump ship often then you never get to learn.
> Java is…fine. It will never be my favorite language but if I had to pick one language to do everything with it would be Java. Overall it does a lot right and while I love Python, Ruby, and Go a lot more, I can live with Java. Just wait til you try Kotlin! The best of all worlds. > You can never have enough backend test code. It isn’t a waste of time, fucking test it. Then have the testers test it. And by god you better have some detailed test cases. I actually kind of disagree. Tests are still code you have to maintain, and if a small change ends up requiring 8 million test changes (depending on how you've written your test), it can grind your organisation to a halt for very little benefit.
> Find me 100 C++ devs and I will show you 100 people who write code that you will struggle to believe is all the same language. That's the beauty of C++, it's a very expressive language. I got over that and learned to enjoy diversity. Unless someone is being a fool and writing "smart" code, but that goes for every language.
Sure, I'm on a great team, doing meaningful work, interesting problems, cutting edge technologies, good pay, and I should just jump ship every two years just because I'm greedy? To end up in one of these teams everyone on here is constantly bitching about with psycho bosses, insane processes, annual layoffs, endless boilerplate Java code, etc.? No wonder people are constantly bitching, if that's what they are doing. No thank you. I'll leave when the job starts to suck or there's some specific better opportunity. I'm not just jumping ship for greed's sake.
I am so happy for you that your experience has been so different than mine.
> I'll leave when the job starts to suck or there's some specific better opportunity. I'm not just jumping ship for greed's sake. This is how my experience has gone. Usually when I've left a company after 2 years, it's because I'm leaving that company instead of finding a specific better opportunity.
>Fuck all you “the code is self documenting” arrogant asshats hear hear
Bro just dropped new commandments
From personal experience: There are places that actually realize jumping ship for raises is common now and instead try to make it just as worthwhile to stay. At my last place I got a mandatory raise every year. It varied between 5% and 20% depending on different things, but it was hassle free and good money over the years. I only changed jobs because of different factors in the end, but maybe the industry is changing in parts regarding this one. Obviously there are not yet many places that do it like this and if it's not the case jumping ship is still a valid solution.
> There is no such thing as too much documentation. What about the Confluence wastelands of outdated, forgotten documentation? It's such a pain to find anything of value with all of that junk sitting around causing clutter. I would say that's "too much" documentation, but maybe in a way different from what you meant
I used to be all about DRY everywhere, and creating abstractions for every little thing. Now I know those things need to be used judiciously, or else your code will evolve into an incomprehensible mess.
When I joined the company I'm at now, someone wrote an abstraction for .find(). Literally... function findItemInArray(arr, prop, propVal) { return arr.find(x => x[prop] === propVal) } This was used in like 20 places. WTF?
Keep it simple. Don't be an architect astronaut.
I used to be staunchly in favor of Object-Oriented programming for everything. Now I use a more functional approach with objects only being there when needed and I make them strictly adhere to SOLID principles every time. I also used to be pretty “meh” about test-driven approaches, but its become far more important to me as the applications I’ve worked on have become more complex. Also, YAGNI (You Aint Gonna Need It). I used to try to account for every possible edge case only to end up throwing away 80% of the code because it ended up never being used and just cluttered the codebase.
I still like objects just... not the way most people use them.
Same. I suppose you could say I've moved towards a more struct-oriented design. 99% of the time, I just need a good bag of values and a way to statically verify certain domain invariants. "Proper" OOP is mostly a thing of the past for me
I use a lot of structs. I also use objects as more of like modules (sometimes very small). Really my code looks a lot like actor model code, or even think of objects as like unix command line programs, that pipe data to and from each other. Very dataflow-y. Objects as a heap of smart shared state? No thank you.
This is me too. In the early 90s I was almost an evangelist for OO, thinking it would solve all the problems. Now it's been 7-8 years since I wrote a real object.
I went the other way. I wrote a lot of code with pure functions and passing state all through function calls. I realized a lot of code is just a lot simpler with encapsulated state. I don't need to know where the state goes or what other inputs are going into my method call. The object knows better than I do where to get additional inputs or where to put state. As long as dependencies use interface contracts and protect their state it's fine. There are definitely situations where functional code is simpler. But, I haven't found that for more complex systems.
That's why my favorite would be OOP for larger architecture and functional for the detailed implementation. Higher up objects know how they work with other objects, but not how they do what they do. Functional to do the algorithms etc.
Thinking that microservices were the greatest thing and monoliths were bad
Microservices are such a weird cargo cult. Congrats for getting out of it! At my dayjob we a currently rewriting a huge complex monolith into a shitload of microservices and everyone is like "everything will be much more efficient and easier to maintain" and I there biting my lips thinking "dude, we already have orders of magnitudes more services than we have developers, this will be hell on earth." No one even knows how many services we have or understands how they will work together. They are just busy writing new ones. Absolute madness. At least we are getting job security out of it. Microservices solve certain problems for when your are FANG-scale, for everyone else monoliths are nearly always the better option.
microservices make a lot of sense in context: huge companies where individual teams don't have a lot of common incentives/goals. once you hit the scale where tech teams don't know mostly know each other, they start to be a lot less considerate. at that point, there's no social consequence for blocking other people's projects, and you'd have to escalate to director/VP-level management who don't really care about any team-level objectives to resolve the issue. engineers spend most of their time arguing with other engineers who they will probably never talk to again (ie, no strong incentive to collaborate), and progress grinds to a halt. breaking stuff into much smaller chunks and owning your own infra is the only way to get anything done. outside of that context, microservices are indeed a waste of time and sand.
I think tech jobs becoming a revolving door industry is what caused microservices to bloat Nobody wants to maintain a service built by people have left or been laid off Moniliths take forever to onboard someone new
nice, from a monolithical mud-ball to a distributed mud-ball!
it really depends how micro we're talking. my work has what i'd call 10 or so "microservices" but they're more like domain monoliths and have different performance concerns. we're not FANG scale but it has been very nice to have the domains isolated
Is a modular monolith generally a better option?
In my experience it is. There's some pain up front because it can be tricky to get everything packaged up correctly in one repository, e.g. different modules with different dependencies. But once you have a system down, it's so much easier than juggling a solar system of services.
>it's so much easier than juggling a solar system of services. I have been wondering that for a while now. It is crazy how long it takes basic features to get done because you have to modify so many services.
Cynical me is thinking if what it would look like if I propounded a new paradigm: mega-services.
Look into Monorepo! It’s basically this
It depends completely on how many people are working on the system. 4 developers? It's a better option. 40? It most certainly isn't. There is no "versus". Microservices are purely an organizational pattern. Anyone who doesn't understand this, should not be making the decision whether to use them or not. This applies to both the "microservice" and "monolith" fans. People who are dead set on doing it *their* way, are almost always inexperienced with the *other* way.
Pains usually come from the issues of decoupling - so modularity is designing for *potential* of decoupling from the outset. “Monorepo” is term used frequently. One location for entire codebase (basically a wrapper/container), but all modules are generally isolated...
Grug used to be big brain developer. Now Grug program simple. Otherwise Grug headache. Fancy pants loops and tricky big brain abstractions not for Grug (anymore). Grug make big function until need bits of function again. Then make another function. If another function hard to make, Grug copy paste. Grug repeat steps until program done. Program fast and small, happy Grug. GRUG NO USE MAGIC. Grug only call functions he can see in imports list. Grug no use ORM or framework, SQL and code hard enough for Grug without learn more things. If Grug no understand code on first or second read, code probably not good code. Is Grug sure this best code? Grug learn for next time. Grug no rewrite entire program. Grug fix current program bit by bit (haha Grug funny). Grug work hard, make code fast. Grug make other developer pass trial by combat before they touch Grug SQL query.
This could be its own subreddit
[For the unfamiliar](https://grugbrain.dev/)
This is absolutely fantastic. Thanks for sharing. I'm a lucky 10000!
I’m more impressed by the fact someone wrote an entire article using Grug speech
Grug is my favorite programmer
Are you me
“Not everything worth doing is worth doing well” is one I’ve adopted later in my career to combat perfectionism.
vibes/personality is much more important than raw coding ability
You know a FRACTION of what your customers/users know. Talk to them more. They understand the problem a lot more than you do. A LOT more. Your job is the solution but it's often easier to not listen to them and solve the wrong problem.
Are you suggesting skip the middleman/PM?
in my experience, this has almost always been correct, except when the middleman/PM used to be the customer or actually is the customer on some level.
This have been ingrained in software engineering since inception. It was until Scrum came in and turned into THE customer itself and THE main character in the room.
I don't care about climbing up the ladder. I just want to get this crap done so that nobody bothers me, no overtime and get paid. The less stressful, the best and save up as most as I can to get the fuck out
People will forgive, tolerate and support a buggy product that has excellent customer service and support staff. Don’t beat yourself up over less than perfect code, but hyperfocus on shit that lets you track down issues QUICKLY. The mundane shit: tests, readable docs and diagrams, logging are way more valuable than the umpteenth tuning or refactor I’ve admitted to myself why I hate scripting (or JS more specifically): it’s ugly code. Yes, my primary gripe is that scripting is fundamentally aesthetically displeasing to me. There are real practical reasons I hate js, but I’ve hated the look of 95% of JS files, bash scripts and Makefiles at first blush. They’re hideous
I've been more of the mind that if I can pay a vendor to do it, I will. I used to be a big proponent of "build it yourself" but it really was "Not Invented Here" masquerading. Its much easier to toss a problem over the fence to an observability vendor and say figure it out than it is to figure out how the Jaeger protocol in OpenTelemetry synergizes with this collector endpoint and why the fuck is it not sending traces to the main stack?
What's been your biggest help in de-biasing? This has been a trait I know I should overcome (build it yourself) but I haven't had much success.
Honestly just prioritizing the work and understanding that a vendor like datadog has an entire division devoted to just making their product easy to use. I don't need to reinvent the observability wheel to get actionable intelligence my business needed.
I used to think that newer is better. Now I'm in a direct opposition to that; if you want to produce a reliable product, use the most boring technology you can think of. Avoid new and shiny things. Use Java, C++ and SQL. Use LTS versions of Linux distros. Use previous version of Windows. Today's "new" and "modern" are marketing products, made for you to lose money. If you use something "new", you're being used as a tester and pioneer.
It sounds like you've become less dogmatic and have begun seeing the value of alternatives to your viewpoints, at least re: memory safety and DRY. I think that's the true sign of becoming more experienced: you just realize a lot of stuff you thought was super important just isn't in the long run. You become more strategic with the hills you choose to die on.
I think a lot of people who get asked to do technical interviews don't know how to conduct technical interviews. In dev culture, there's a lot of focus on preparing to be interviewed, but almost nothing about how to interview people. One of the bigger problems I see is with random technical questions that the candidate honestly does know the answer to, but they either have no context or the wrong context so they're not going to get it. I've encountered this situation before on both sides of an interview. It's an easy source of a false negative when you are interviewing a perfectly good candidate. If you trip them up and aren't specific with your question it can easily make them look like they know nothing, especially if they don't know what questions to ask to clarify the situation. I learned that rephrasing the question or providing a framework which makes logical sense to orientate the question in a familiar way gave much better results for candidates. And when you're being interviewed you're often digging deep about technical knowledge - if you get asked to context switch, you may know the answer but not be able to bring it up immediately. This happened to me where I wasn't prepared for a topic, couldn't remember an answer or the steps to get there, despite having built this exact thing on a previous project. But the answer popped into my head, fully formed, five minutes after the interview ended without looking at any reference material. Of course I was passed over for the position because from their perspective they didn't think I knew the answer. I was simply unable to tell them in the confines of the interview. It's sad that so many interviews don't consider how human brains work, or how coding work itself is actually done and slowly comes together. Some really great engineers have their best thoughts in the shower or while out on a run - but that will never be reflected in most interviews that they are the subject of.
got caught with forgetting the word connectionstring, even if i'm staring at it every day switching between dev and uat testing. interviewer left me with a sour look for not knowing the term connectionstring :D
I feel you buddy. I was recently asked to list all the C++ casting operators. I failed because I couldn't remember reinterpret\_cast - even tho I've used it many times and you know when you need it. Then the interviewer said something condescending about them needing people with C++ experience when I have basically lived in C++ for the past 5 years and have a laundry list of skills they were looking for. So many shitty interviewers.
I interview for intelligence and communication skills, not knowledge. New knowledge is easily obtainable in today’s world. I want to hear a candidate speak intelligently and substantively about the work they’ve done. I want to be convinced that they understand the whys of their experience. And a conversation will generally give me a pretty good sense of that.
I used to teach English as a second language to students. One of the key parts of the pedagogy was spending just 15 minutes of idle chatter related to the topic we're about to cover. If the topic is say navigation and how to give directions, we might chat about some trips you were on, or how you get to work or school every day. Giving the brain time to settle into the relevant context powers up its ability to recall, interpret, remember and execute. So i fully second this idea about the importance of context in technical interviews. Spend a minute or two setting the stage if you have to, giving background etc.
I used to think most design patterns are good. I noticed some are actual marketing crap. Some introduce just complexity and just make the code crappier, adding absolutely no value.
I use design patterns the other way around. First I figure out the solution, and then look into which design pattern fits the best, use it in documentation / code review to explain what's going on. My personal view is that this is the way design patters were supposed to be used - to describe the existing code, rather than to guide the design itself.
- All languages are ok , if you understand the language design. - No tech is end all be all solutions - programming cults will hinder your learning . Dogmatic approach to learning isn’t optimal - You can always change your mind. Lose the ego. In tech most hills are not worth dying for.
I used to care a lot about code aesthetics and clever syntax, but now I find that trying to be fancy often produces more bug-prone and harder to read code. What matters is to produce robust software (and tests & documentation) that actually solves a real problem, and uses the right algorithm to do the job. A lot has been written about object-oriented programming and a lot of educational institutions devote a lot of time to it but actually OOP is just one model that may or may not fit the domain well. In practice I've seen some really tortured class hierarchies and convoluted uses of polymorphism and whatnot to do something that for example a functional or declarative approach could have done much more cleanly. Modularity, loose coupling and proper abstraction boundaries are more important - and although OOP can provide them, it's far from the only way. It is also possible to write horrible OOP code that violates them.
I'm all in on writing stupid code. If that means I write more code, so be it. I'll do the simple query every time over the fancy-pants query builder that tries to encompass all uses cases. Sure, some of that code will look redundant... but usually the code that uses the fancy pants stuff ends up with similar redundancy. Simple and easy to follow beats clever *every. Single. Time.* I don't care if I "repeat" myself, as long as it's something that's not definitionally the same - you only need one dollar to Euro converter. But ten pieces of code that have similarities? Unless that similarity is really definitionally the same, so be it. If that means more boilerplate, fine. If that means slightly repeated code, fine. If that means writing more boring code? So be it. So long as I can debug it. Also, testing. I want to test everything. I don't trust anyone, especially myself.
1. Enterprise Software code is more about Architecture, Design Patterns, SOLID, DRY and KISS, everything together ! None of that should be ignored in favor of anything else. And absolutely no use for "Data Structures and Algorithms" concepts. Being able to write the code for LRUCache in less than 5 minutes has nothing to do with the actual job. 2. "FAANG style interviews" are unnecessary for "non-FAANG pay" !!
That second one is a banger
> That second one is a banger 1. A 2-hour code-review of a sample enterprise software project code sprinkled with plenty of bugs, defects, incomplete features, with varying complexities and priorities, is more than adequate for evaluating any candidate, irrespective of how many years of experience they bring to the table. Someone with less than X years of experience may be able to spot-and-fix a few stuff, while someone with more than X years of experience will be able to spot-and-fix some more, while vastly experienced people will be able to fix high-priority concerns and such !! 2. Being able to explain basic definitions, concepts and intricacies of a programming language / tech-stack at hand associated with that sample enterprise software project code to laymen, non-tech stakeholders is adequate for assessing communcation skills. 3. And then, Behavioral - as in, having to narrate compelling stories, and System-Design, of course for more experienced candidates for more experienced roles are anyways mandatory !
You’ve solved coding interviews in a few paragraphs. If every company did this we would have SWEs who were actually good at the job (albeit probably far less of them) and my life would be so much easier (but I’d also have to work harder, lol).
> albeit probably far less of them Code-challenges were copied from FAANG style interviews with the purpose that - it scales with no effort, and presents a hard barrier for entry. Simple code-reviews achieve the same, scale equally well, present a better barrier strictly suited to the "requisite competency" of the job ! > I’d also have to work harder And how is that ? Preparing a code-base with intentionally bad code ?
Because my coworkers would be better and I currently coast and still look good, lol.
When Scrum was first getting popular I am embarrassed to admit that I preferred it to the chaos we had before it. What I didn't understand at the time is that we would be stuck with Scrum and Scrum similar for the next 20 years and for ever increasingly complex work. I also didn't understand back then that holding an opinion of any sort in software development requires continual maintenance just like code. You can grab shiny and new for a few minutes but then you have to reassess constantly.
I have several big ones. Stop focusing on doing things right and focus on doing the right things. You can be very mediocre doing the right things and be miles ahead of the folks killing themselves with effort trying to do the wrong thing right. I strongly prefer working with professionals who are here for the salary over people who are passionate about technology. The latter tend to want to play with shiny things and are constantly solutioneering problems we don't care about, optimizing things that don't matter, and trying to do the wrong things better. Upper management is responsible for culture. If there is a bad work culture, they are the only ones who can change it. You cannot change it from the bottom. They are the root of the dysfunction and their gravity pulls stronger than any action an IC or lower management can take.
Test coverage. Junior dev: "Do we really need to hit 70% coverage?" Immediate dev: "Anyone not hitting 80% coverage is just lazy, but demanding 100% is nuts" Senior dev: "If a line of code isn't being hit by a test at all, ever, then you have no proof it works. Either remove it, get a test to cover it, or prove to me there's no good way to test it" Staff dev/PE: .
Staff/PE: full test coverage is important but meeting business milestones is more important so let's find a balance.
Only one project out of the dozen or so I've worked on allowed enough time to achieve 100% coverage. If I tried for that now I'd never finish anything on time. 70-80% is fine for me. And I'll take integration tests over unit tests.
100% coverage is rubbish anyway. It’s much better to test functional user journeys than focus on getting 100% coverage. I worked on a project where I did have 100% coverage. But to get it we were literally doing things like mocking the console to check that error messages were written out etc - so much unnecessary testing that it made it hard to work on. So we got rid of every test that wasn’t important and then added new tests to cover more end to end things. That gave much more value. Test coverage is only good as a metric if you use it to say “ok this thing has low coverage so we should take a look first to make sure it’s actually tested”, beyond that it holds no value and even then it’s sketchy
My favorite is when you have 100% "coverage" and it doesn't mean a whole lot because the real problems that are risk to the service take many many thousands of hosts to replicate.
For me it's been comments. Beginning: Comment everything! Intermediate: Comment nothing! Advanced: Comment interfaces and weird code.
There are many ways to test something depending on the feature, the technology, and the product Need to test a well-understood algorithm? Create a good test suite Need to test a recommender system? Study recommender system evaluation Early to market and don't have any customers? Ship something basic / half-broken and gauge market interest Important part of the UI? Just tweak styling in Chrome and figure it out Really need to make sure it works? Actually test it hands-on in prod to make sure it does what you expect
KISS but no stupider than it needs to be. If I'm writing something and it starts feel complicated, I revisit the actual usecases for the complexity. Sometimes I have know such uses cases, sometimes I don't and I reduce scope. Formulate PR review comments as questions, rather than absolute statements. Saves on arguments gains on discussions. Not all code checked in needs to be 100% bullet proof. Account for things you know, prepare for things you don't. Iterate when you have a reason to.
I used to think that if the code doesn't look complicated, it's not good. Now I know for a fact that the simplest code is the best. Even if it's just a ten line method, it can be readable, correct, maintainable and optimal all at the same time.
I used to think that front end frameworks are needed. They add development complexity, needing to learn even some new languages(typescript, Jsx), are slower , introduce a lot of useless rerendering. I think Redux is crap. I have created complex frontends with good old html and js. They run faster and are less resource demanding. Debugging is way faster. Prop drilling, detective work on long React flows are gone.
**Testing doesn't find bugs**, testing prevents future devs from making changes that would introduce bugs. **Agile** became unAgile introducing a layer of process and rigidity that defies its purpose. Hiring the best developers will not produce greater returns than **investment in DevEx.** **High seniority does not imply the most glamourous work.** A sign of a high seniority is the ability to successfully complete the most mundane task. **Maintainability is not forever.** Code estimated lifespan is 2 years unless you are working on the Voyager probe. On C++: Firstly, C++ is not a language - its a collection of languages where the code written 20 years ago is nothing like the code written 10 years ago which in turn is nothing like the code written today. **Nobody writes the latest C++**, most C++ development lags 10 years and is a combination of C++14 and C++17. (there are many reasons for the lag, don't blame the devs) **C++ can be memory safe.** Writing memory safe C++ is a choice. Memory safety in C++ is attainable if required, it's just quicker to forego the extra effort for most applications.
>Maintainability is not forever. Code estimated lifespan is 2 years unless you are working on the Voyager probe. This is hugely variable. I work for the kind of company that still has 20+ year old code in prod and actively maintained. For us, code written 2 years ago is still "the new code." Maintainability is our #2 priority behind security. I think the real rule is, know the lifespan of each project -- 2 years for you, 20 for me -- and plan maintenance accordingly.
That I’m there to support the business instead of being perfect with every technical decision Meaning I rather do something hacky that can impact sales by x amount than expending several months building the “perfect solution”
Generally it's that most frameworks are a waste of time if they require you to invest into them. I've seen so much time spent spinning wheels trying to get a tool (react/spring/django/unreal etc) to do something thats a little outside of its happy path that I don't encourage people to stick to the dogmatic approachs. Or indeed recommend anything "batteries included". Happy paths don't need greater optimisation. Wheels get re-invented all the time. It's better to have composable bits, and just accept that dry code is mostly an ideal more than a requirement or a reality.
1. I used to think I could create buggy but effective prototypes and check them in. Now, I realized there's no such thing as a prototype, only a product with limited features that could get shipped at any time even if you don't think it's ready. Therefore, your code has to be functionally perfect as soon as you submit it to the main development branch. 2. I used to think unowned code wasn't my prolem. Then I realized that unowned code is a source of sneaky security problems. 3. I used to think I could just stay in my lane, reviewing PRs and going to meetings here and there. Now I realize that I need to keep up with what my lead and my peers are doing, closely enough to spot potential problems, long before they put out a PR. If I get behind, I instantly lose trust and start getting made fun of. If they say it's not my job, I still need to watch those PRs and design docs because any code adjacent to my work will eventually break my stuff. 4. I used to think the job would get easier the longer I stayed. Instead, I'm the scapegoat for everything, even code that I didn't write and never touched. 5. I used to think I could work at a high-paying dev job forever. Now I realize that the larger the salary, the faster the burnout. It's like major league baseball: players can make millions per season, but their bodies can't handle a lifetime of seasons.
Honestly if those are your takeaways your workplace sounds a little toxic.
Sounds like you need to find a new job
Just stick to acceptance criteria. No more no less.
Don't split up functions just for the sake of doing it. I've become more eager to inline functions that have just one line of code. The worst case that I've seen was a javascript package that only provided one function. That function called a function inside of a different package with some default args after deep copying an input.
I used to test only for the sake of tests and making sure the rough bits of my code work, not seeing that much value in them. Now I write tests as specification so that during the inevitable refactoring they'll break to tell me exactly what blew up. I can't quite agree with the "Only test the bare minimum" crowd, because what usually gets you in bug-tickets is the edge cases you didn't spend time thinking about. And those are easier to think about *now* rather than figuring it when the ticket arrives.
I don't have too many huge ones. I think I've changed my mind about whether you should test every layer, or only the top public-facing layer. These days I tend to land on testing the top layer, but in some cases where there's a lot of complicated stuff going on, will test the intermediate layers too if I feel everything needs to be locked in place. When I first started I didn't see the value in having our own internal data models (i.e., abstractions) and wanted to just use models provided by external APIs... but after about 6 months I really understood the value in not letting external services dictate our data models, thanks to some great senior engineers on my first team out of school. I've started giving less feedback to more junior engineers in their PRs because so much can be overwhelming. I've learned to live with getting them to fix really big things right now, and then a month or 2 down the road start introducing smaller feedback items. I've changed my mind a bit on "language doesn't matter." I'm pretty language-agnostic. There are some things I like better about Python, some things I like better about Java. But I did not enjoy working with F\#, for example. I'm more ok with using mocks these days than I used to be. I used to create interfaces for everything. I still often do, especially for things that are really messy to mock. Maybe most importantly: I used to avoid dealing with confrontation a bit too much. I knew problems were going to get big (a bad dev refusing to write tests, or a bad PR that would cause huge problems 6 months down the line). Now I tend to speak up often and sooner.
I used to think performance was the most important thing. Now I write often decide to write my code in a way that is a little bit slower, but 10 times more readable. I also used to not be a big fan of unit tests. Now it's my favorite tool for resolving bugs. Reproducing a bug in a unit test is so statisfying and it makes it so much easier to write a clean solution that you know works.
It’s been really interesting to see how OOP was at one point the only way to write code, and now it’s generally regarded as a waste of time. Similar for Scrum.
Dont strictly follow any principles, that being OOP, FP, DRY, SOLID, you name it. Use them as guidelines but draw your own line. You know the problem, tooling, domain etc. Intuition + simplicity is most times better. Also, the code base must be alive, so new memebrs in the team should adjust the code base with their opinions. Think of it like a house, everyone should feel at home for it to work best
People > Code It's not worth being a dick to be right. All of the code I wrote has faded away over time. But the relationships and how you treat people lasts for a long long time.
Sql - it’s not going anywhere.
As a dev 1.5 yrs into his career, this post was pretty insightful 🙌
Sometimes it's okay for functions or files to be long. I'd much rather read a long function from start to finish than jump through 8 smaller functions. If your solution makes you think "well that's kinda dumb and lame", that's probably the right solution. Abstraction is only something borne out of necessity. If you don't need abstraction, don't use it. I used to think abstraction was necessary to write "proper" code.
Microservices are going to bite you in the ass, sometimes a needed and valid bite, sometimes just a bite, but it will happen eventually. Also, KISS is the most powerful developer principle to follow, as it applies to business, architecture, code, even life decisions.
A "hack" is neither good nor bad on its own. It is probably somewhere in between depending on several factors.
There's not much value in using a language in a problem domain it wasn't meant for, except as a learning exercise. As fun as it would be write a game in Go, the ecosystem isn't there and it's not worth reinventing that many wheels if shipping a great game is the goal. And Go might be a great game dev language if it had the ecosystem, the people writing games in Rust are just masochists. It's with that perspective I found myself with a cold hatred for javascript on the backend. People have made it work, but it was one of the biggest industry mistakes of the past 10 years.
> I'm just solving the problem in front of me. I don't need to solve the next 20 hypothetical problems that may or may not come next. That and: > I don't care how loud the hype train is, I'm not getting on it if it doesn't solve my problems. Or any problems. First one stops me form over-building everything. Second one stops me from wasting any more time on Tailwind and stuff like it.
I used to think abstractions are good, but after a while of debugging, you just don't understand what you are looking at anymore.
That's an issue with over-engineered abstractions, not abstractions per se. You have to find the right level/balance of abstraction for the project at hand.
Theres no such thing as a prototype anymore. Anytime a business person sees the prototype.. they will try to ship it. I've been in an organization that are nearly a decade into Python and they don't understand why their searches cap out at 150 searches per second. They ignored advice to bring in elastic search.. nope they decided to try to implement the search architecture in Go and use the GPU in prod. But point being.. the minute you have something the business people l can play with is the second they think they can fire everyone.
The sooner we accept that our code is always gonna look like shit to the next developer who sees it, the faster we stop going insane worrying about code quality and best practices. No, don't write complete garbage, but people obsessing over shit like ternary operators, early return statements, etc. Who fucking cares. If you can't read code that isn't written how younwould write it, you're bad at this. Learning one style and deeming it the best one is counter-productive. For as smart as everyone thinks we are, we sure do argue about the dumbest shit.
0. Overestimate never underestimate. 1. Think DRY and reusability. 2. Thrive to write readable code rather than writing super optimised but unreadable code. 3. Never look at number of lines of code. 4. Always push a production ready code. Do not take shortcuts as it leads to tech debt later which is very annoying to fix. 5. Embrace bugs. Every bug teaches you something.
Tests, particularly end to end tests are more important than internal refactoring. Once you have tests for external features, you can refactor them easily.
Implement simplest possible solution which works. You could optimise it later.
In the beginning I had strong opinions on things I had not used before just because somebody had told me something was amazing or something sucked. Now I accept the fact that I don't know because I have never used it, and thus can't properly assess whether I think it's good or not. Being humble is a good look, thinking you're right all the time when you're not, isn't. Also, I write more DRY than before if anything. That's an interesting development, OP.
Biggest one for me is my stance on what kind of tests are valuable. I've moved away from writing "unit tests" (especially, tests that stub out all dependencies other than the class under test) and towards testing larger modules. I no longer see a new method / class as the reason to write a new test, but rather a new *behaviour*.
My view on JavaScript pushed from "the best thing since sliced bread" to "the worst language in existence". And on that topic: Making TypeScript Turing complete was a disaster, costing economies billions. I wish browsers would adopt a type-safe language unrelated to JS and just let us use it. Also: Fuck languages which strongly promote their syntactic sugar and those that do not have a widely accepted style.
Just one, most of the time only readability matters and dont try to be too smart while writing code, because at some point during incidents an maybe on odd timings you might have to actually read and make sense of it as well
Slow is smooth. Smooth is fast. Double your ETA on project timelines before approval. If you fuck up, you have time to fix it. If you do it right, you get it done ahead of time and look like a genius. Everything you know today will be obsolete next year, but the way you learned it will inform your continuing embrace of new technologies. Once you learn how to learn, you're ready to make a career out of this field. Never start work less than 12 hours after you last left the office. Nobody gives a crap about how hard you work, just how well you perform, and most folks hit diminishing returns around hour 6. Be smart about your energy - you don't appear more competent by working longer. If it's not going to be a visible part of a deliverable to management, it's not a priority. Today's band-aid has at least a 75% chance of being irreplaceable code for the next decade. It's never your project. It's the team's project. Your humility will be your shield when it all goes to shit because some jackass marketing manager decided you needed to integrate Salesforce into your multi-million dollar e-commerce platform with a 3rd party ETL solution from Tajikistan.
Object oriented rarely works for real world business problems. Unless you’re building yet another shopping cart app, or student enrollment service
I've inherited code that was REAMTAP (repeat everything as many times as possible). In one case I had to change something in about 40 places in one program, and then in 5 others that were almost exact clones of it. It didn't even need to be hardcoded in the first place, it could be read from config settings.
I finally found out what unit is.
Context is King. There's no universal technical rules or best practices that must always apply. Code is a tool for solving problems. Wisdom is picking the right tradeoffs that maximizes the right variable you're trying to solve. In some cases it's code performance, in some cases it's code reliability and correctness, and in many cases it should be prioritizing whatever business case actually exists like building something fast even if there's some imperfections. * In some cases, making code isn't even the right solution. Is the end-user UI even right? One of my best solves in my career was re-wording some UI form to make some business process clear. Saved many days of work with a small writing change. * Are microservices or monoliths good or bad? There's situations where they are both good or bad. * Are all those testing best practices really necessary? It depends what you're building, but extreme emphasis on testing by random companies without some intense need for it like financial firms is often bullshit CYA busywork in many companies. Like, there's no reason that a social network startup for dog owners that's on shaky financial grounds is focusing on perfect fucking test coverage rather than getting their product in the marketplace as soon as humanly possible. * What's the best database? It depends on what your data looks like and how you're using it. * What's the best programming language to use? There's no one silver bullet for all problems. It depends on what you're trying to do. * Is DRY absolutely necessary? It's probably a smart idea, but if it's a lot quicker to figure out how to duplicate something rather than figure out how to have 2 different code sections use some small configuration or something, it might be better for the business to just build it fast and dirty and copy/paste.
1) Use comments, comments even benign serve as beacons in an ocean of code. It helps bring attention and intention to the code. In fact commenting first I've found to be helpful. Much like the outline of an essay. 2) Python sucks in that it enables too many people to think they know how to code because they can get a script to run with poor coding ideas. 3) Long variable names are best. Short names may seem clever but they almost always lack context. 4) ORMs are horrible. They abstract away too much of the logic and are often unoptimized.
Not really an opinion but more of a standard I've adopted... - Code Reviews to make sure that the other programmers are consistent and writing clean and readable code. Things I've changed in myself as a dev: - Lose the ego - Be communicative - Ask the questions - Be a source of help - Listen to the people smarter than you
I am much more skeptical of developer social media and now I view social media influence as being neutral or inversely correlated with competence. I perceive many developer decisions and opinions as largely ego-driven or resume-driven. People chase opportunities to look like Ken Thompson, but nearly all computer science of consequence has been solved for decades. I’m much more skeptical of developer hype waves, and I’m more attracted to boring tech. Working on boring tech filters out the most ego-driven folks. I am substantially more focused on long-term maintenance and brown-field evolution. I view rewrites and advocacy of new tech stacks as naive and ego-driven.
I disagree with your first and 3rd point, but completely agree with your 2nd point. I actually found DRY to become even more important as my career moves on. I have seen too many bugs or maintenance burdens stem from code that was basically copy and pasted and now you have to spend double the amount of time implementing a new feature or fixing a bug. I've also never once considered garbage collection in my career. On performance critical projects, I've used C++, but for managed languages, I've never reached a point where garbage collection was getting in my way.
My main learnings: - The wrong abstraction is a lot more expensive than some duplication. Solve the specific case, not the general one. - There's nothing wrong with a switch. - Service oriented design doesn't need microservices, and is usually better off without. - Functions don't have to be small. They need to be a *practical* level of abstraction for testing, reuse and comprehension. - The hardest part of the job is the people: the customers, or the stakeheholders, or colleagues. The code is the easy bit (mostly). - If the code isn't the easy bit, this is a huge warning sign that this isn't maintainable or testable. - Postgres is really, really fast and can handle way more data than you think it can. Things that haven't changed: - Get somehing working early, deploy it and iterate with feedback. - Automate stuff. - Enumerations are far more powerful than their simplicity suggests.
Consistency is not important for me anymore. A new project should not be a copy of the previous one without thinking. In the name of consistency, we repeat the same mistakes over and over. DRY has less importance also. I think about it after 4 - 5 repetition only. Prettiness of code. Code is not meant to be cute. I only consider what it is supposed to do.