This is a bit of a long ramble, so apologies for that. This is why I don't blog often (:
There's one aspect which, in my opinion, makes some developers (and people!) stand out above the rest.
It isn't raw skill. It's not necessarily what they know. It's definitely not what tools they use or what framework they build stuff in. It's not their race, gender, height, orientation or any other attribute -- though there are people who are going to face hurdles because of those things, these do not define their capabilities.
Rather, it's a mindset, an approach to coding (and, most often, life) which affords them the ability to learn at the fastest pace, to build things that others just dream of, to fix things that others consider to be unfixable. These are the people who you call when you're stuck, whom you might observe and wonder "how did they get so good?" or even: "how do I become like them?".
But let's start by setting the record straight:
HACKERS ARE EVIL
Long ago and far away, the word "hacker" was born, describing "Someone who is brilliantly persistent in solving technical problems". Somewhere along the way, people who didn't know any better ascribed that term to what are more honestly known as "crackers": people who "crack" systems, usually for their own gain.
Whilst good crackers would have definitely come from good hacker stock, despite what the media ascribes to the term, it's a good thing to be a hacker. It doesn't connotate sneakiness or lawlessness beyond the desire of the individual to question everything and find ways around obstacles. So, more of an "internal" or "harmless" lawlessness. We'll circle back to this later.
So what does it mean then to be a "hacker"?
As the original definition states:
- smart
- persistent to the point of being tenatious
Smart? I'm not smart enough!
Anyone who thinks they are, probably isn't.
Don't confuse "smart" with "knowlegable" or "experienced". Don't confuse "smart" with "qualified" (in the sense of having academic qualifications). Think more "smart like a fox". This smart refers to your ability to think about things, formulate ideas, test those ideas, reject the ones that fail and build on the ones that work. It refers to being able to gather and stitch together knowlege which is pertinent to your current endeavour.
Truly smart people realise that they know only a tiny fraction of All The Things, that they have much left to learn, and that they can learn from anyone, because even the mose n00b person out there has different experiences which lead to different perspectives, which lead to different conclusions. Some of those conclusions will be bombs, sure, but some will be absolute winners that no-one thought of.
When two people have very different perspectives on life, they may determine very different conclusions about a situation and solutions for it. We do our best when we consider all available solutions and pick the most optimal, not when we just stick to what we know, or an idea simply because it's ours.
Persistent? Tenacious?
Tenacity refers to the quality of an individual to keep on trying, no matter what. When a tenacious person hits a wall, they look for a crack in that wall. When they seem to have run out of options, they stop, and think, and try crazy ideas! Tenacious people will eventually seek assistance from others, but not before having tried every possible thing they could think of, not before they've added enough breakpoints to make the IDE unhappy, not before they've decompiled and googled and read everything they can get their hands on.
Tenacious people are not above getting help from others -- they assume that they will have to, at some point, but would prefer to get that help by reading an existing article than by disrupting someone else. Tenacious people have also oftened discovered that they learn best when they work through problems, allowing them to move forward faster when they encounter similar problems again.
Smart and Tenacious!
These people will ask for help when truly stumped, but get a thrill out of solving a problem themselves -- and an extra thrill out of sharing that solution with others, and learning of alternative solutions from others. These people will often seek to understand alternative solutions just to learn more about how things work. These people become the ones other look to and say "I'd never be able to do that", though the ones saying that are mistaken: for we can all adopt the hacker mindset. It's almost like it's part of our DNA -- we just have to unlock it.
Systems thinking
Everything around you is a system of some sort. Whether that's a car, computer or cookie. A computer is a good starting point to illustrate this though: there are multiple layers of systems as we travel downward from pixel to electron:
- what you see was displayed by a screen of some kind
- supported by individual pixels
- rendered by some software (like a web site)
- supported by more software (operating system, drivers)
- supported by firmware
- supported by hardware components (graphics, networking, the cpu)
- supported by electronics principles
- supported by physics principles
Each layer represents one or more systems. There are more below this. Each of the above could be broken into sub-systems too.
There are more above the pixel:
- physics of light transfer
- the optics of your eye
- the workings of your brain to interpret that information
- which is used to further the goals of yourself and/or your organisation
Of course, there are more layers and systems above that.
The point I'm trying to make here is that part of the hacker mindset is recognising that everything is made up of layered, interacting systems. At any point, you can break that down into simpler parts than initially meet the eye. To the 19th century poet who sees BioShock playing out on your screen, it's all unfathomable magic. To begin to understand, we need to stratify (identify layers of systems). Then we simply have to:
Eat the elephant
There's an old joke:
Q: How do you eat an elephant?
A: One bite at a time.
Once you realise that everything is made up of componentised systems, that everything can be broken down or assembled to reveal new systems, the next step to understanding is being able to pick a slice of this layer-cake and work at it, acknowleging that the rest exist, but for the purposes of your current discovery or journey, they are irrelevant.
You pick off a small piece that looks relatively self-contained and start there. If that piece is still too large, you set to work identifying the systems that make up that piece, and pick it all apart again.
There are some tools that are really good for helping with this. One of them is your trusty debugger. If you don't know how something works, try set a break-point at the place where it last looked like it made sense and, with the system running and breaking there, step into that breakpoint to follow the logic all the way down.
Sometimes your debugger won't step in, but rather over, normally because it's determined that for most intents and purposes, the code you've asked to step into isn't your problem -- it's another encapsulated system. We have ways to deal with that too:
- Use an IDE which allows debugging external code (like Rider or use the DotPeek symbol server for Visual Studio). These tools will decompile the code you're running through, with the help of debug symbols provided with the library, if available.
- Get the symbols for the library you're trying to step into, and try again (often .pdb files)
- Use your browser's "pretty-print source" button (often looks like
{}
). You may find that there are no source mappings for the code you're looking into, and that that code has been minified so that functions and variables all have names likea
ando
. This doesn't make it impossible -- just a little trickier.
Sometimes it's hard to find the right place to put a breakpoint. In this case, I like to write code specifically designed to be easy to break into and a unit test which exercises the system I'm trying to figure out.
A concrete example: a library that I wrote some time ago facilitates duck-typing in the .NET world. A collegue was trying to gain insight into the workings of this library by placing a breakpoint at a line of code where a property was being set on a duck-typed object, to see how that value made it back into the underlying data, but the IDE just refused to allow him to step into that code. So I suggested that he create a specific type with one property and backing fields, place breakpoints on the field sets, and duck-type an instance of that, so that he could get a stack trace once the breakpoint within his property set was hit.
There's always a way!
Remember that the compilation (or, in the case of JavaScript/TypeScript, transpilation) process is a bit like encoding a .wav file to .mp3. For all the young 'uns out there, there was a time when people used to rip their own CDs to mp3s instead of just buying them! No, really, it's true! Anyways, when you do this, you create what's called a "lossy" copy of the original source: some information has been lost in the process. A good encode will leave only the information that your ears care about. Similarly, when we compile source code, the resultant artifact is a binary or compressed script file with only the information that the machine cares about -- none of your pretty comments or fancy names -- just the logic.
It's possible to reverse the wav-to-mp3 process, though the sound file you'll get back out again will be larger and not of the original quality. But, just like code decompilation without symbols, or applying "pretty-print source" to minified code, there will be the essence of the logic there. Certainly it's enough to figure out what's going on!
And this is the "internal lawlessness" that I was talking about earlier: the mindset that affirms that there's always a way to figure out what's going on and there's always a way to solve a problem. Sure there are some math problems that have remained unsolved for centuries -- there are others which remained that way until they were solved. That's how it goes: I fully believe that everything is, in some way, soluble -- but some things are not soluble right now.
Similarly, every ability you could possibly aspire to achieve, is possible, in some way or another -- but many will take a lot of work and effort to get there. Everyone will find some skills easier to develop than others. Everyone has inherent strengths and weaknesses. Play to what you have, work hard at what you want to become -- none of it is out of your reach, especially if someone has done it before you.
There's an adage I heard once that it's far easier to ride in second position on the Isle of Man TT than in first. I've never ridden Isle of Man, but I have ridden way too fast on a bike, and I can tell you this is true: if I can see that someone else is making the corner ahead of me at some crazy speed, then I know it's possible for me too. The same applies to my yoga -- there are plenty of super-skilled yogis out there doing amazing things (just check out Dylan Werner). I can't do a lot of the things he can, and when I started yoga, I couldn't do any of them. But I can do some now. How good I get at that depends more on my tenaciousness and the amount of work I put in than where I am now or where I started. The same goes for you on your dev career.
If you can see talented people like Emma Wedekind, John Carmack, Jessie Frazelle, Evan You, Paige Bailey (and many, many others!) doing All The Amazing Things, then that just means that it's possible for you to do them. Perhaps you can't do them yet, but the only hurdle between where you are now and where you want to be is your tenaciousness.
Enough blathering!
True. So here's some final tips:
- Read!
- code
- articles
- documentation
- perspectives of other people
- Learn!
- learn a language outside of your wheel-house
- if you do OO (eg C#), learn a functional one, eg F#
- learn about another build system
- strive to understand the nuances of languages, frameworks and apis that you use daily -- don't just accept that "it's done this way".
- learn about memory allocation
- learn at least rudimentary C to get an understanding of the low-level stuff
- try another operating system
- if you want to learn about how your computer works, install Gentoo from the Handbook (there's no guided installer! and yet this has been the most rewarding distro I've used in 20 years!)
- learn a language outside of your wheel-house
- always ask "why"
- challenge the status quo
- when encountering a problem, ask "why"
- when finding a solution, ask "why"
- never give up
- if what you're facing seems tough, break it down into smaller pieces and tackle one of them. Do that until there's a piece that is small enough for you to master, then move on to the next one
- you don't have to understand every system from the pixel down to the electron, but you do have to understand that none of it is magic, and all of it is discoverable. The trick is to stop when you've learned enough to solve your problem, but don't dismiss learning more. The more you learn about the underlying systems, the more control you'll have over the higher-level ones.
- be prepared to be wrong
- and when you are:
- apologise if necessary
- take on new learnings
- don't fear failure
- we learn best by failing
- and when you are:
Top comments (0)