Leveraging A Poor Memory In Engineering
senrigan.io
senrigan.io
I used to assume that the "10x engineer" was 10x faster at the programming/typing part, but it turns out it's more like identifying the 1/10th of the work that actually matters and just do that efficiently. It is also true that there's a lot of experience in both the identification of that 10%, and the efficient execution of it though.
Side note: I have also met a few flat out amazing, natural programmers. These people can also be 10x as productive, but it's in a pretty specific way that should probably just be considered an outlier. My feeling is that the main way for the rest of us to achieve that level of productivity is gain experience, do things simply and efficiently, and learning how to focus on the things that matter.
the 10x programmer is by definition an outlier
1. There usually are just a few critical pieces to any project. You should try to start with those and get them locked down first. These can be critical because they are either technically unproven or just plain difficult. Once you know the hard stuff is handled then you can fill in the easy stuff from there on out. (You'll also feel less inclined to fancy-up the easy stuff, in my experience. That's another source of trouble).
2. Use quality tools, become an expert with them, and hold on to them as long as you can. What does quality mean? To me: reliability, stability, and efficiency of both my time and the machine's time. Knowing how to do something because you've done it before, seen the problems and worked through them, and come out the other side, is _huge_. Rarely rarely rarely, a new technology comes along that overwhelms the advantages that hard won experience provides, but it's super rare. This is a whole topic in itself, but in my 20 years the list of situations in which something new clearly brings enough benefits to switch are surprisingly rare. Off the top of my head (and just to make everyone mad in one easy sequence): moving to Java from C/C++, Hibernate ORM instead of endless hand crafted SQL, S3 instead of a probably-about-to-be-full attached volume, Heroku instead of running my own machine, Unity instead of my bad custom game engine, and most recently Flutter instead of native Android/iOS (although this one is still early days).
3. Be honest about what you're actually spending your time on, and optimize for that. A lot of the fancy programming languages of recent years have been spending huge amounts of time optimizing what, for me, weren't big usages of my time. I realize this is vague, but an example for me might be Scala. The stuff that they were improving looked fancy in examples, but it didn't make a material difference to me (as a Java programmer) in what I actually spend time on. It also came with a bunch of downsides, which is itself worth an entire post.
4. Don't be afraid of simple looking code. It might be slightly embarrassing to check in, but it's probably going to be clear how it works to you any other other person who needs to read it in the next few years. The urge to appear smart in the way your code looks can be deadly.
5. Be specific about the upsides you expect when examining a new technology. Are you looking to work faster, are you looking for performance in a specific category, etc. Failure to properly define your criteria leads to adopting things that are a bad fit for your situation (helllooooooo microservices) or at least provide minimal benefit in return for the _huge_ expense of throwing out experience in another technology.
I'm pretty sure there's lots more examples, but that's all I got at the moment. I will add more if I think of it. I guess this should all be a big blog post at some point as well, if it's something people find interesting.
Point 2 (and 5) is probably one of the biggest things I think about a lot these days. Most of my tech stacks are relatively tried and true, with the exceptions of Netlify and GCP. Where it's possible, I will generally try to put a $10-20 dollar SaaS product instead of code. That comes with counter-party risk, but I trust Pingdom more than I would my own notification servers.
When I wrote this article, I struggled with explaining how my thoughts of what a 10X engineer changed over the years. I recognized people would yell 10X != memorization, but the compound effect of working (and learning) without friction (in this case, human memory. in many other scenarios, technical debt) leads to exponential advantages.
- Getting the requirements right. This by far has the most impact on effectiveness
- Reducing friction. Simple things like proficiency with high quality tools, smooth and fast builds, clean logs, easy ways to generate and analyze core dumps, accumulate to produce an outsize effect on productivity.
- Uninterrupted, substantial blocks of focused time. It is staggering how easily chat, email and meetings can destroy productivity.
Quick tip: For people who work in a company where they don't necessarily have control over their own time: schedule the living out of your calendar. Book endless meetings with other programmers, then just sit there and do work. "Q2 Backend Architecture Review: 4 hrs" can just be a few people sitting in the meeting room programming. It's crazy the power of blocked out time on your calendar to a manager who otherwise sees an empty day.
Another way I've tried to tackle this is on day 1 of a job - I've blocked out a huge chunk (4 hours) of my daily calendar of "Coding Time - No Meetings, No Slack, No Email" before anyone could tell me no.
Open plan, with 2nd line support talking to customers right next to developers.
My team has coordinated it so we spend mornings working independently on the most important things we need to get done. Only the afternoon is open for meetings. In those meetings we often identify things that we will each work on independently the next morning. This better planning leads to more focus and the reduction in distractions leads to more productivity.
Emergencies are exceptions, but it's amazing how rare those can be if everyone has a decent amount of time to handle their most important things every day. Also, many people are not well organized and this small amount of organization makes a massive difference.
I don't think I quite captured everything, I might take another shot at this again sometime.
The way the author managed to reduce the impact of this habit was to remove the cue for wasting time by memorizing syntax. Congrats on that! This seems like a pretty demanding solution, though.
Perhaps a very simple way forward would be to employ a site blocker on distracting sites during work hours.
Beyond that the author might regulate their work hours so that they have limited time to get things done and avoid burnout from long days.
They also might consider using a pomodoro technique, so that their brain can alternate between focused and relaxed attention. Setting boundaries around when it’s time to focus and introducing a purposeful schedule of relaxing breaks helps keep one from falling victim to bad habits when your brain needs a moment to relax.
Why? There is a sharp divide between "interacting with the internet" and "not." There is no one site (or set of sites) to block that can help. If I visit SO I now am one step away from an effectively infinite number of interesting things.
The key behavioral difference is removing the need to interact with the general net.
Burnout and tiredness are also not root causes in this situation they are a symptom of repeated failure to accomplish a goal. Pomodoro doesn't help much there.
Burnout and tiredness are definitely factors that keep people in a cycle of distraction because our brain is ready to be distracted in those states. If unproductive work leads to excessive work, this is a vicious cycle with tiredness as both cause and effect. You can’t regulate your attention optimally unless you are well rested.
I would say the “root cause” in this situation is the need for sustained attention on the intended task and the lack of a system to achieve it. The strategies I’ve listed are well known ways to achieve this. The author found a different way and was pleased with the results.
You can still get into flow while looking up syntax you haven't committed to memory, but know how to find in 2 min.
I have a habit not to commit anything to memory that I could Google in 2 min, saving on RAM.
One way I've found to mitigate this is to not try to write things that that would definitely work on the first draft. Instead, whenever I need something I don't remember, I just write enough of it to note what I'm trying to do and keep going. The details of whether it would be more convenient to use slice or substring here aren't important when I'm trying to write things down before I forget them.
- Famous sax guy
I'm doing a lot of Kotlin right now, where simple, useful extension functions are an autocomplete away. I don't need to memorize how to get a slice of an array; I know it's going to be named something like .slice(), and I can jump right to the documentation from my IDE.
When I run into something not in the standard library, I write a little extension function of my own. And then I remember it the next time I run into that problem, and get to reuse it, just like it were part of the language.
For any programming language, I consider the following pretty essential APIs that you are going to use over and over:
1. Details of primitives and built-in "base" objects and related functions (e.g. strings, numbers, object literals, dates, etc.) 2. Collection libraries (arrays, dictionaries, sets, etc.) 3. Details of async libraries (e.g. in JS everything in Promise, how that applies to async/await). 4. Streaming libraries. 5. For OO languages, details around class creation/construction 6. Language specific details that are important (e.g. for Javascript I would put things like which values are falsy, Function prototype values like apply, bind, etc.) 7. Default common 'util' libraries, like lodash for JS and Apache commons for Java (not necessarily saying you know every single function, but you generally know which functionality groups are there).
Yes, you can look those up, but if you have a good memory for what the slice() function is and what you can do with it you will be faster than someone who has to look up the details every time you want to use it. In addition, knowing the general API surface means you know instantly what tools are available to you vs. what you'll need to create or get from an alternate library.
'CPU-bound' I would say is where you have all the pieces you need to solve a problem, but the precise solution is tricksy or math-heavy. Such problems are relatively rare in day-to-day programming. So I would say that on the contary, most programmers are I/O bound most of the time.
More time should be spent thinking than typing; specifically, reasoning through the problem domain and appropriate solutions. Having surface APIs memorized is going to save less time than having a well of experience to draw upon thinking through correct or best solutions.
Beyond that, you identified a ton of areas of APIs that are useful to know, but if you understand the fundamentals behind the ideas (i.e. how to use arrays to solve problems, when to get a subset from them, how promises and futures differ from streams, etc) you're 90% of the way there. I think it's less about memorizing the API specific words and knowing the language of the paradigm.
I might be splitting hairs a bit on that last point, since they're pretty closely related. But, I think a 10x developer is going to be better distinguished by knowing when to use a future vs. a stream, rather than simply knowing the API method names and signatures for a particular library / language.
Every time I need to write something in a new language, I grok it and write on it with a handy syntax /API/SDK reference.
For me, The things worth remembering are the patterns used to solve stuff, not how the patterns are implemented in a specific language
I do follow the same approach.
As Nicklaus Worth stated, knowing algorithms and data structures is more relevant as specific language features.
no-clobber
note: existing files or objects at the
destination are not overwritten, and are
reported as being skipped.
note: makes an extra GET request before
uploading an item. this may adversely
impact small transfers, or save data if
large transfers can be avoided.
For the second example I'd simply adjust the code sample as: var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = /* ??? */;
with only the `fruits.slice(1, 3);` part on the answer side.Now, math equations or the minute details of data structures and algorithms.. Those can be hard to internalize and knowing them well is very helpful when reading papers or other diving into open source projects which make critical use of advanced, specialized knowledge.
Some interviews, maybe. As you say, it doesn't matter much for day-to-day work -- and so I put no weight on it when rating interviews either. If the candidate remembers the right method names, great. If they don't, who cares.
I always make a point of explaining that I'm not testing them on API memorization.
1) a good man is a good man and thus equal to other good men
Or
2) you proceed through so many qualifications and “but what if this guy was prettier or had nicer tone of voice than the other good man all else equal” etc until you admit that you include minute details like the exact placement of every hair follicle on some dudes head in your proposed total ordering of humanity
In particular, I'm not convinced the evaluation must extend from arguably relevant features to obviously irrelevant features. Even if I'm ultimately wrong, I can mount a defensible argument that memory is relevant to programming ability. I do not see a way to mount a defensible argument that (for example) facial features are relevant to programming ability.
Studying API trivia to show off in interviews is about as far off as it gets. So probably I’d choose the candidate who hadn’t done that. I’d rather risk a lazy coworker than one who fixates (even if competently) on the wrong problems. I’ve seen coworkers with that trait seriously drag down a team with low-signal nitpicking on others’ pull requests and designs, for example.
API knowledge is ideally a consequence of familiarity with the craft. Sort of like how vocabulary is a consequence of reading, writing, and interacting with well-read people. I’d rather have a conversation with someone who reads a moderate amount than with someone who decided to memorize the dictionary. The former knows fewer words, but I expect they’ll have more interesting things to say, even if none come across in the first 30 seconds.
Let's use your example of memorizing dictionary in some foreign language x. This person will be able to read faster and more efficiently without having to stuck on some unknown word and looking up dictionary every 2 minutes. At this state this person is just simply reading and focusing the brain on the content itself.
Likewise with memorizing programming stuff, the person can now just simply code and freeing the brain to just focus on the problem. Consequently more time to code moderate amount and ensure familiarity with the craft. I think this so called the 10x engineer that the author mentioned.
I have never actually gotten a job where the interview had a variation of that question.
on edit: changed explain to exclaim, don't think it significantly changed the meaning in context however.
I also give a problem that doesn't use a lot of library functions.
At this point I can sit down and bang out entire Ansible roles (hundreds of lines of YAML) without having to reference the docs or even use auto-complete for 95% of it. It's really a joy when you can just focus on getting what you want down in code and have it work in the end -- without interruption.
I'm with the author here in that I am very jealous of anyone who can memorize things like that without putting in years of practice. It's not just a speed boost, but you feel good about yourself being able to just hack on something for 20 minutes without having to look a single thing up. It takes a LOT of repetition for me to get to that point.
http://www.jackkinsella.ie/articles/janki-method
https://www.jackkinsella.ie/articles/janki-method-refined
https://drive.google.com/file/d/1JCHkqVoX598Ob_111khrGoJ5cpe...
Derek Sivers also has written on memorising a programming language using SRS software: https://sivers.org/srs
One important thing in the original article is about flow, or the feeling of being in the state of flow if you don't need to remove yourself from the task for looking up documentation. I think that is a worthy goal to aim for but I am amazed at the amount of cards he has created, nearly 10,000 over a period of three years. He has put in lot of effort and reaped the reward.
I'd say things like "why would I spend time memorising facts when computers can do that for me?" I thought there was a stark difference between "memorisation" and "understanding how things work". The former was for people who wanted to pass tests, and the latter was what smart people dedicated their time to.
What using spaced-repetition software has taught me, however, is that memorisation and understanding are tightly coupled. Storing facts in my brain increases the amount of connections I can make, which greatly improves my ability to think.
Echoing another commenter, every line of code you don't code is coded infinitely-faster, doesn't need testing, and you'll never have to review or maintain it. Programming should be the art of surgically using just the right amount of code in just the right spot to provide lasting value, not filling out forms, wiring interfaces together, or thrashing around online searching for other lost souls. Yes, we all end up doing that kind of work -- but that's a fail, not a win. The more we horse around with our tools, the less we're helping people.
Video games took over the world. That is, everything became a video game, with a sexy UI, enthusiastic community, cheat videos (and classes), and outward signs that you've leveled up.
This makes sense, I guess, if you're goal is to play the game. And whatever you're doing with computers should definitely be fun. But when interacting with the computer is a tool you're using to provide something to somebody else, the longer you spend with the computer providing that value the less efficient you are. The best code is no code.
Somehow this author seems to think that being a great programmer is due to mechanically-interacting with the programming environment. The 10x types faster, remembers more, and has mad skills at the IDE. This would be utterly silly if we were talking about great novelists -- how many words they type per minute, for instance -- but somehow it seems to make sense for coders.
Myself I wish to not remember things of this nature. My IDE can autocomplete my code with API references. My terminal history is set to infinite so I can grep for whatever command I found useful in the past.
I instead want to spend my time and memory on deepening my understanding of certain topics, or on brushing up on concepts and techniques I've known in the past but have come close to forgetting.
If you’re working in an IDE you’ll also have a realtime hint on whether your guess was the correct one.
For me its wasn't about becoming a 10X developer but proving that I was already 10X because I was facing a salary cap of 120K CAD where I saw friends working as long as me 180K+ CAD and some 250K+ CAD. The last job I attempted we had a 55 year old developer being paid the same as me doing the same rot work and I said thats not going to happen to me.
I've always been a person that gets things done but when you asked me how I did it I could never regurgitate the factoids.
Interviewers or other developers thought I was stupid/faking because their probing of my knowledge came down to superficial factoids and not evaluating the past work as a whole where I literally have 30+ projects. Hiring is broken and instead of getting upset about it you just have to meet the checklist.
I have Cracking the Coding Interview and I've been through that book 3x and I can not remember the contents of it because that book has been more more useful to me to prompt up my monitor than in my in the day to day work.
I feel when you're a developer 10 years in you'll be forgetting things as quick as you learn them but proving you have in-memory knowledge is super important.
I use Anki and Mnemosyne but found their UIs clunky and so I built my own Space Repetition Learning flash card system. I was studying for AWS Certifications and I wanted a way to tied practice exam questions I wrote to flashcards so when I got questions wrong it would reload my deck, and one I memorized all the factoids via space repetition learning I could go back and attempt a practice exam.
Now when people ask me whats the different between RAID 0 vs RAID 1 I know which is stripping or mirroring.
I got so carried away building my study system it because my own startup called ExamPro: https://exampro.co
Its really nice to have something you can build where you actually have domain knowledge and its the first time independently where I was successful building a startup that has generated revenue.
I could build anything but without domain knowledge I could never sell what I could build and now I can and its wonderful.
Space Repetition Learning changed my life. Who knew?
I keep hearing how the interviews at Google are really tough, but then a lot of the people who actually get through quit in the first weeks. It can't be that great of a job.
Speaking of which, "it can't be that great of a job"...no, of course not, it's a job. But a job is a job (roughly speaking), and a $300k/year job is to many/most people twice as good as a $150k/year job.
How much experience do you have and what city are you from? What employers offer $180k+?
I’m in Montreal with 4-5 years “fullstack” experience. Seems jobs are rarely going above 100K around here. I barely make 100K right now.
The important thing is that these cards aren't static. As your knowledge improves, as you gain practice, you'll notice the cards that aren't written in a way that are conducive to flash card learning and (ideally) you end up pruning and refining the process until it works. This requires a non-insignificant amount of dedication though.
I just can't imagine using flash cards, or a similar product, to learn anything in-depth about a language. Maybe API specific problems, but nothing more.
I have cards like asking what a closure is or how to use one, or what an IIFE is or how to use one. Or what IIFE stands for. How to deconstruct an array or an object. What's the scope of a variable defined with "var"? How does it differ from "let"? How do I list all the properties of an object? How do you access the properties of an object? When should you use bracket notation to access a property of an object? I have a bunch of syntax ones or basic ones ones like what's the equivalent of a Python forEach.
Somebody else might decide to have completely different questions. I tried to codify every little thing I learned while using Javascript, where others would consider it overkill. I've already deleted plenty of cards where I I felt I'd internalized the knowledge in a way that I don't need a flash card for it.
Another source of flash cards from any books or articles you are reading: any key point that is new to you, or you had forgotten, might go on a flash card. It's more effective than bookmarking or highlighting (when starting on a topic that is completely new, you might want to limit your notes to those points where you had to pause to think about what you just read.)
I'm a software engineer and I feel like I'm forgetting a lot of things that I learned during university and during my carreer (algorithms, architecture models, design patterns, etc.). This feeling is very frustrating. I never thought about using Anki professionally and I'm gonna start to add some algo-related cards to Anki right now.
Note: I also recommend "learning how to learn", https://www.coursera.org/learn/learning-how-to-learn/ - give some simple techniques and tips to be better at learning (spaced repetitions is one of them, learn by chunks, force yourself to recall, etc.).
I did an implementation of a skip list a long time ago (and I found the algorithms to insert, search, etc. quite simple and elegant). Recently I had a chat with someone and I was struggling to explain them.
I could design a few cards for skip lists:
- Question "ELI5 skip list" Answer "the actual ELI5"
- Question "What sort of problems are solved by skip lists?"
- Question "How to make a skip list indexable"
- Question "How to insert the element 123 in a 3 levels skip lists [1, 4 - 4 - 4, 43, 120, 210 - 210, 302]" <- make a better ASCII scheme. etc...
Answers can be quite long. For the french motorcycle license, some answers can be very long (2 or 3 pages) and it works pretty well for me (see https://ankiweb.net/shared/info/1156061502).
When you train: after reading the question try to recall the answer in your head and then read the answer. Then you evaluate how good you were recalling and you pick the Anki "score" (bad, hard, good, too easy).
However, I agree that it's more useful to memorize/internalize concepts than syntax. One of the limitations with anki/supermemo's flashcard-based design is that it's hard to break down complex ideas because you're limited to the flashcard format. I've built a new tool that lets you generate flashcards right from your notes to make it easier to break down new ideas. It's called RemNote: https://www.remnote.io/.
My memory was pretty terrible before I started using this and that problem is now largely solved :)
Better Tools
He talks about having to google things all the time, and memorize how to do things in his language. But that's the IDE's job.
Good tooling knows everything about the language you're using, and everything about your codebase and everything about every library you've ever used. If you want to do something with a File, you shouldn't ever need to remember anything more than the word "File". Type that, then ctrl+space, and the IDE will get you to the point where muscle memory can take over.
For other things, I just cheat. I have "\r\n" written in felt marker in the corner of my keyboard, because (since I'm also a bit dyslexic) I can never get the slashes in the right direction first try. This isn't my dev laptop, so I just got them wrong typing them out above, and had to google to verify. Despite having used them on a daily basis for 20 years.
But anyway, back to the point: Tools can and should replace nearly all the memorization that most people in this gig seem so proud to have done. So long as you're good at the problem solving bit, a bad memory won't hold you back.
P = ( U * O / F * C ) + S
P Productivity
U Understanding of the codebase
O Ownership - degree to which you feel you can make significant changes to code with minimal approval
F Fear - degree to which you are concerned about mistakes costing you your job
C Complexity of codebase
S Your actual skill set
Yes I think Skill is not a multiplier in almost all cases
I suspect ownership and fear are actually exponents as well.
Tip for people looking to use it: you can find premade decks (collections of flashcards) on various topics on the Anki website. For example, here are decks that are available under the 'Programming' topic: https://ankiweb.net/shared/decks/Programming
Not all of these decks are great, but there's a rating system, and this can sometimes be a helpful starting point for your own decks.
However, the next gap is learning to reason about these things from first principles. It’s the “10x” commonality and I believe it can be learned, but it takes a different set of tools.
(My book will come out one day. ;)
https://github.com/Ziinc/gsheets_importer
It basically scrapes a published Google sheet that has a list of links. Each link needs to be a Web page with a html table. The plugin then scrapes each link, using the left side of the table as the front of the card, and the right side as the back of the card. All formatting is converted into inline css, so you can write code formatting as well. Though if you were writing actual code, I suggest writing it in markdown and then publishing it then adding it to the sheet, instead of using a published Google doc.
I use it for university and it reduces the time spent formatting each card individually into Anki.
So far it's the most efficient workflow to creating Anki cards that I know of.
Writing less code requires extensive knowledge of frameworks, patterns and best practices. Memorizing programming syntaxes and paradigm makes getting in the flow easier because of reduced context switching, makes work more fun and hence greater productivity (10x days). But at the heart of it, being productive requires understanding of the problem domain in depth, knowing what matters and what doesn't (YAGNI and pareto-ing mercilessly).
I'd be interested to hear what your problems with Dash were.
I also have the problem of an extremely bad memory (and I feel the more time I've spent thinking about abstract concepts the last years, the worse it got), but I've never really felt that this held me back. Looking up API documentation makes up a negligible portion of my time working, and especially with Dash, that has been reduced to a non-issue.
It helped me a lot! Lot of my co-workers said that I learned faster than others in the same timespan, and I think it was partly because of Anki.
I have a One Note for frequent queries.
If I have to google "how do i amend my git commit" five times every month, that's actually the best use of my time. If I only need it five times a month, spending ten seconds to look it up is more efficient than making it part of some sort of spaced repetition learning scheme.
I would say the same is true for virtually all of programming. If you really need it all the time, you automatically learn it by looking it up all the time. No flashcards required. If not, just look it up. The guy with the photographic memory will always win, he'll remember it the first time. Again, no flash cards required.
.slice(1,3) will give you elements two and three. You're looking for .slice(0,3)
[1,2,3].slice(1, 3)
> [2, 3]