I personally know some developers who are very talented and can create wonderful pieces of software with no or little struggle. Because of these gifted individuals, our industry is full of high expectations. But the sad truth is: not everyone is a ninja/guru/rockstar developer.
And that's exactly who I am: a mediocre developer. This article will guide you through surviving in the industry if you are not a genius.
I google the simplest things all of the time
I fail to remember a lot of the things. Like functions and methods from the standard library, arguments positions, package names, boilerplate code and so on.
So, I have to google it. And I do it on a daily basis. I also reuse code from old projects. Sometimes I even copy-paste answers from StackOverflow or Github. Yes, it is actually a thing: StackOverflow Driven Development.
But I am not alone. A lot of other developers do it too. There's a popular twitter discussion which was started by the creator of
Ruby on Rails.
But why is that bad in the first place? Well, there are several disadvantages about it:
- It allows you to copy bad design decisions or vulnerable code from other people
- It forms a specific mindset: if we can not google something up, then "Houston, we have a problem"
- When the internet will go down, we won't be able to work
But, I don't think that it is a big problem. It even may serve as your secret weapon. I have some pieces of advice to follow to decrease negative effects.
How to survive:
IDEto get autocompletion and suggestions, so you won't have to google the language basics
- Remember where (not how) you have already solved this problem. So you can always look there for the solution
- All code you paste into the project should be analyzed, refactored, and reviewed later. This way we won't harm the project with the bad code, but help it with the fast solution
I keep things straight simple
Machines always do what they are told. Sometimes they are just told to do the wrong thing. So, the main problem in software development is not machines, but developers' mental capacity. It is very limited. So, we - mediocre developers - cannot waste it to create complex abstractions, obscure algorithms, or unreadable long code blocks. Just keep it simple.
But how can we tell that this code is simple and that one is complex? We need to use
WTFs/Minute method to measure code quality.
The principle is very easy and clear to understand. Whenever you find something in the code you do not understand - it is too complex. What can you do?
- Rewrite it to have cleanner design
- Provide documentation
- Add comments to the most tricky parts. But remember, that comments are the code smell themselves
How to write simple things from the beginning:
- Use correct names for variables, functions, and classes
- Make sure that every part of your program does only one thing
- Prefer pure functions over regular functions
- Prefer regular functions over classes
- Fallback to classes only in a strong need
I do not trust myself
Some developers proved to deliver high-quality code. Like this woman: Margaret Hamilton, lead software engineer of the Apollo Project. In this picture she is standing next to the code she wrote for the moon mission:
But, whenever I write any code - I do not trust myself. I can screw things up really badly even in the easiest parts of the project. This may include:
- Language errors
- Logic errors
- Design errors
- Style errors
- Security errors
- WTF errors (my all-time favorite!)
And there is no magic book about "learn how to write bug-free code". And it is perfectly normal. All software has bugs. Except this framework though. Deal with it.
The thing is: anyone should not be allowed to write code with obvious errors. At least, we should try. But how can I protect the project from myself? There are multiple ways to do it.
How to survive:
- Write tests. Write a lot of tests. Starting from integration tests down to unit tests. Run it in the
CIbefore each pull request. This will protect you from some logical errors
- Use static typing or optional static typing. For example, we use
- Use automated style checks. There are tons of the style checkers for every language
- Use quality checks. Some tools run some complex heuristic algorithms on your code base to detect different problems like this line has too many logics inside, this class is not needed, this function is too complex
- Review your code. Review it before merging to
master. And sometime after the merge
- Pay other people to audit your code. This technique has a huge positive influence! Because when developers look at your code for the first time it is easier for them to spot inconsistencies and bad design decisions
It should work not only on my computer
When my team has developed our first big software project almost ten years ago, we have shipped it as
java source files. And it failed to compile on the target server. That was several hours before the presentation to the client. This was a big failure! Somehow we have managed to get it up and running, but it was a life-changing experience.
That happened because there was a lot of configuration and a lot of complexity in the build pipeline. And we could not properly manage the complexity of this system. Since that day to reduce the complexity on this step I try to pack my programs in isolated environments. And to test them in this environment before the actual deploy happens.
In the last years with the rise of
docker (and containers in general), it became as easy as ever.
docker allows you to run development, tests, and production in the same isolated environment. So, you would never miss any important things along the way.
Wound't you? Talking about myself, I always forget something while creating servers, initially configuring them, or linking them together. There are so many things to keep in mind! Hopefully, we can still automate it. There are different awesome tools to automate your deployment process. Such as:
packer. Read about them to find which one do you actually need for your tasks.
I also try to set up
CD as soon as possible. So I will be reported if my build failed in testing or in deployment.
How to survive:
- Automate anything you use for deploy
dockerfor application development, testing, and deploying
- Use deployment tools
After the application is deployed, I still do not trust myself
Oh, at last, my application is in production. It is working now. I can have a short nap, nothing is going to break. Wait, no! Everything is going to break. And yes, I mean it: everything.
Actually, there are some tools to make finding and fixing existing problems easier.
Sentry. When an error happens for any of your users - you will be notified. Has bindings to almost any programming language
- Different services and tools to collect logs from multiple processes and servers into one place
- Server monitoring. That's the place where you can configure monitors for CPUs, disks, networks, and memory. You can even spot the time to scale before the users will actually break your service
To put it shortly, we need to monitor our application in production. We sometimes use all of these tools, sometimes only the most required parts.
Wow, that's a lot of things to learn. But that's how it works. If we want to write good software we need to constantly learn how to do it. There are no short ways or magical tricks. Just learn how to be better every single day.
In conclusion, we need to understand two basic things:
- Problems happen to everyone. The only thing that matters is how ready we are for these problems
- We can reduce the sources of the problems to some acceptable rates
And it has nothing to do with your mental capacity or mindset.
Top comments (79)
Excellent post, in the spirit of Albert Einstein's quote: "A true genius admits that he/she knows nothing."
The admission is itself the prerequisite for genius.
To add on, I believe we are seriously lacking a culture and the mechanisms in the software industry to view and support each other as learners. Mentorship and apprenticeship are virtually non-existent and when they are, they are often in name only.
The suck thing about "experience" and learning is, that the more you truly learn/know, the more it reveals what you don't yet know. It often feels like for every one thing I master, I also see that there's at least two more related thing's I've yet to master. It's like a geometric curve of relative-ignorance.
...More, it puts you in a position where you realize "I have expertise, but I am not an expert — and I have no idea what that self-proclaimed expert is because he very clearly has less expertise than I do."
This is related to the Dunning-Kruger effect
Yes and no. People that display DK tend to never really ever reach a point of "huh... I guess I didn't actually know as much as I thought".
I guess I was lucky then: I was able to find a really good mentor early on in my career. Changed my life, and then happened to be friends with my current manager at my job (didn't know that when I used him as a reference).
10/10 would recommend a mentor, but they're hard to find and often just come out of nowhere.
You're lucky man! I just wrote a post here about this problem when you just start your career and don't find the right company with the right projects and mentors, you really feel disappointed.
I too was lucky enough to have had a couple of mentors early in my career that, IMO, changed everything. Because of this I have taken it on myself to be a mentor when and where I can. I find myself, at this point in my career, managing a large team of UI devs and have the opportunity to help them grow and learn. I feel it is my responsibility. Kind of a "pay it forward" mentality. It's also personally very rewarding.
In the end, I feel that we are all responsible for mentoring each other, and believe we all have something we can share and learn from one another. As practice lead, it's something I expect from my team and have zero tolerance for those that feel they are above others and not willing to share and mentor.
Thanks! Mentorship is a big problem indeed.
My company also tried to create a mentorship program inside.
But we failed twice. Since it requires a lot of time and money, which we could not afford at the time.
So, for now I don't know how to break this vicious circle.
I think some comments are missing on the sarcasm of the post here. I don’t think the author thinks themselves bad programmers, but rather is poking at those “Star devs” who claim their talent is wasted in writing unit tests and such.
Excellent post !!
I think you put yourself down way too much. Judging from the article and what I see in my industry, you're already better than 90% of the developers. Integrating different pieces of technology and code, and writing new code is pretty much what software developers are meant to do. Knowing that you have to do CI/CD, myriad of testings, and knowing how to go about doing it and all the options available to do it shows you know what you're doing. That's already better than most teams I see.
Also, many devs have different focus.
I met people who can get up and running with new stuff quickly, and others who know older stuff in and out. Both having their struggles with the other side.
Some are also simply good with talking to non-technical people.
I can't count how many super-devs I got introduced to by some non-tech folk that turned out to be barely junior.
Compared to some pros working at Facebook or Google, I'm probably mediocre.
Compared to some hacks working at some no-name company I'm doing rather fine I think.
And there are more of the last kind, hehe
You are not a mediocre developer, you are simply a DEVELOPER.
If people expect you to be a "programming encyclopedia", then that's their problem. You don't have to remember everything, you just need to be AWARE that there's such function or such class.
I know a 20+ years experienced man who can build advanced systems with raspberry pi and stuff like that and integrates them with his own code. The man is clearly on very advanced level, but he still googles lots of stuff that he faces on a daily basis.
If programming is not your 24/7, if you have your personal life, hobbies, whatever else you wanna do with your life, then it is OK to do what you are doing.
There's few rockstars in the world but millions of musicians. Not everyone wants to be famous. Not everyone wants to be a super nerd. Those times have passed. In 2018, people value LIFE more than WORK.
Enjoy your life and you will enjoy your work as well!
One of my favorite posts of all time. I feel that I am no rock star developer either, but the one advantage I have is learning from my mistakes. I have already spent a long time figuring out what DOES NOT work. I have arrived at many of the same conclusions as you. Still learning too.
The same for me!
I’m totally moved by ur post. As a former developer, I quitted working as developer now, I had thought about this “medicore developer” things for long time. and always the conclusion was I was not a competitive developer. And ur post let me think about those things and courage me to being a developer again.
and if u don’t mind I’d like to translate ur post in Korean and post it on my blog(blog.meeta.io) with original link.
By the way, thx for nice post and inspiring me!! ;)
I am really glad I have inspired you to be a developer again! Please, feel free to translate this post. And, also, please send me a link, I would be very honored.
I just finished translation and post it on my blog!! (blog.meeta.io/15)
These are habits of any successful developer. If a rockstar devleper thinks this stuff is unnecessary then they are dillusional and setting themselves up for failure.
I look up functions, syntax, and algorithms all the time. Sure, as I get into a project I'll start remembering the common stuff, but it's not ingrained in some permanent memory somewhere. I'll lose it when I move projects.
What I tend not to look up are paradigms, patterns, and structure. This stuff is universal and difficult to search for. It's the type of question they close on StackOverflow. How much of this stuff you can keep in your head will impact your overall ability. It's a huge part of what must be "learned".
I don't trust my code either. It's not just my code, I don't trust the framework, I don't trust the OS, I don't trust the user, the environment, everything. I assume everything will break because it eventually will. I focus on test/use-driven development. I consider code reviews hugely beneficial. Defensive programming is a must.
Some people may think this slows you down, but I consider it speeds me up. By following a checked development practice I can be assured I'm not spewing out crap, nor do I need to second guess myself. Good practices help free my mind from clutter.
A side-note to the WTF/Minute: I believe one should develop a coder empathy. Don't judge your code from your viewpoint, but from others. There's plenty of code I've written that I have no problem understanding, but I know will confuse others, and probably even me in a few months time. Though it's not always easy to make the distinction between necessary and needless complexity.
I've always been the same way regarding trust. It seems the minute I trust that something will work as it is supposed to, it doesn't.
Dovetailing with this idea, my first boss often complained that things took "longer than they should" when I worked on them. But then when it came time to discuss my performance for the year I would be pretty much with everyone else in terms of completed items. What he was initially missing was not only that I would dig to ferret out the real problems rather than treat a symptom but I would also go over it a few times and think about edge cases, etc... That made it rare for a ticket to come back to me after I had completed it where many of the other "faster" devs would end up revisiting the same ticket 5 or 6 times because they were trying to work fast. Sometimes we would joke when a dev would hit a rough patch where it seemed nothing they did was passing QA calling the offender "Captain Rework".
Also, we shouldn't fool ourselves into thinking "a user would never do that". We had an end user that would literally wait for an update to come out and then he would actively try to break it. We'd literally get tickets where he'd say something like "I put 55 question marks in this field and tried to submit the form, my browser became unresponsive and crashed. When I put in 54 or less it works fine, please fix." I mean really, who does that? lol
Despite the title and your take on the issue, a great many of the things you list are what I would ascribe to high-quality developers, i.e. the ones that are dependable, performant, and that make the project and the team better.
In fact, lots of those points I recognize in myself, and count among my most important and valuable skills.
Beginner programmers write simple code.
Mid Level programmers write complicated code, abstracting an abstraction of an abstraction, mostly trying to be clever.
Senior programmers write simple code.
Having seen the light, senior programmers know that humans are flawed, keeping things as simple as possible is more valuable than bragging about your latest "hello world" that took only 173 lines of code.
BTW. Googling simple function names etc. only means that you don't waste memory capacity, rather saving it for higher level thoughts. Especially these days when most of us have to learn so many different languages and tools inside each project.
I'm pretty sure every developer does this for anything that hasn't been beaten into memory by recent or frequent use. You can make the process a lot faster by using an offline docs browser like Zeal (Linux/Windows) or Dash (OSX) though.
Ctrl-Alt-Space to focus the Zeal/Dash window and a few keystrokes to find a method, guide, etc for a particular language is way faster than Googling, and I use it frequently every day.
I didn't know Zeal/Dash exist and you are an absolute legend. Thank you! ❤
My GOD I love this article. Sorry I'm late to the party but thank you for soothing a gigantic insecurity of mine! I've lost significant sleep over not being a "real" developer and it's good to know that I am not alone there!
Great article, but I think you're being a bit hard on yourself.
Although I have to 100% disagree with this statement:
Why? Unless youre using higher-order logic to write decoupled functional code (functions that take functions, combining or composing them), then functions are IMO a bad idea
That's because I spend a lot of time using functional languages (
elm, a lit bit of
And it seems to me that functions are much easier to compose, extend, and reuse.
Think of it as a personal preference.
Makes sense. I've been using Kotlin which is as close to functional as you can get on the JVM without breaking from the stdlib, so it was a bit rough learning to mix and match OOP and functional. I definitely prefer functional style but can be dangerous when trying to use libs and frameworks which are often just wrappers around java classes, if at all.
One of my personal best practices to protect against my own overconfidence: For every PR I write up the comments to include the testing I did. And I write down all the testing I should do. Sometimes I discover testing I didn't actually do, so I go back and do it. And more than once, I found bugs when I did!
@sobolevn Generated an audio version of this using Blogcast!
If you want to add this 👆 player to your article, just add the following code at the start:
Thanks, btw your domain is blocked in Russia: isitblockedinrussia.com/?host=http...