A colleague of mine recently shared a metaphor with me about two software engineer archetypes, “The Conjurer” and “The Scribe”
The Scribe is diligent and methodical; her code is clean and organized; she can describe each line’s purpose with perfect clarity; she has read the manual from cover to cover.
Scribes have a tendency towards detailed research and won’t implement anything until they are confident they understand the code they are about to write. Imagine a historian in a library of primary sources saying, “I only need 20 more corroborating primary sources to be confident that Arthur was King of the Britons.” The scribe needs evidence to proceed.
The Conjurer, on the other hand, seems to have the ability to pull a working app out of thin air; cutting code blocks from three Stack Overflow posts and pasting them into his own code. Blood magic is not forbidden territory, say the forbidden words, ‘Monkey Patch,’ and shazam:
“The app has video chat.” declares the conjuror. “Oh and … by the way what is a ‘production server’ anyway?”
Conjurers are biased towards action, preferring to understand something after it’s working. Research for conjurers involves scanning a few docs until they find a promising code sample. A conjurer may not fully understand why their solution works until long after the code has been written. Imagine a charismatic traveler in a strange land — they aren’t sure what anyone is saying but somehow a smile and the words for “thank you” are all they need to make friends and find the coolest local spots. The conjurer trusts their instincts.
While the two approaches to problem-solving are very different, it is essential that programmers be comfortable acting in both roles. In a fast moving environment like the technology sector companies often need results quickly which put huge pressure on teams to conjure up a solution and ship it now.
While that approach works just fine for the ecommerce web app’s of the world when you’re working on self-driving cars or cancer detection algorithms human lives are on the line. In this context, conjuration would not be appropriate; to be comfortable stamping our algorithm as ‘production worthy’ when there is a very real cost for failure we need a stronger degree of academic rigor.
“Scribe Out on Nets, Girl!”
I began my career in programming with a bachelor’s degree in computer science. My path through the curriculum took me deep into the theoretical underpinnings of programming: discrete mathematics, data structures, algorithms, hardware design, and so much more. The theory was sometimes coupled with more practical work, but the focus was on getting to the heart of computation not on building consumer products. I was training to be a computer scientist, not an application developer.
A result of this distinction was that I built a number of things that I never rebuilt in my daily work as a web developer: I wrote several programs in assembly language, I built a compiler, I learned the minutia of different binary encodings, I implemented a version of malloc. In Advanced Algorithms, I didn’t write a single line of code. The assignments and exams were all formal proofs; the algorithms we created were at the level of pseudo code. Despite the fact that I did not write any actual code, Advanced Algorithms was by far my most challenging course in college, and one of the most intellectually rewarding.
The scribe is at their best when embracing a strong sense of curiosity, a perpetual need to understand things even more thoroughly. Visualizing something like the call stack is just a step on the path to assembly language. Hash functions are just a step towards collision attacks or bloom filters. Linear algebra is just the start of amazing algorithms like neural networks, linear regression, and other machine learning tactics.
Every skill a scribe learns is simply a step towards something deeper.
By being constantly guided to the next question in college, I gained a deep appreciation for how everything is connected, all the way down to the transistors. I also learned to evaluate code for efficiency, elegance, and security by understanding these deeper concepts. Yet none of this fully prepared me to perform the rituals of conjuration that are necessary to survive as an application developer. I had all the pieces, but it was still hard for me to picture how they would all fit together in the wild.
“Conjure Up Another Auth Integration, Dude!”
Since graduating I’ve sampled several flavors of the programming industry. I’ve laid my hands on a number of different technical fields (front end application development, web server engineering, record reconciliation, image processing & clustering, database administration) in a number of different industries (medical textbook publishing, B2B catering, residential and commercial electricity, and technical education). Under pressure to deliver results quickly on systems far bigger than I had ever seen before, I learned how to conjure up a “Minimum Viable Product” through the fire and the flames of necessity.
In my second job, I was on an engineering team of three. Everything was everyone’s responsibility. We all built the Python/Django server. We all contributed to the database. We all took turns deploying the code. We all wrote features in Angular. All of these things were my responsibility, and while I had worked with Python and Postgres before, I had exactly zero experience with our web frameworks: Angular and Django. Nevertheless, there were always features to ship, and I still had to justify my salary to my boss!
In college my priority was to gain a deep understanding of each component and process; to gain that level of understanding at Chewse would have taken months or years. I had to learn to trust the underlying systems to work. Building something new meant gleaning just enough to understand the input and output of each component in order to quickly build out new features or fix bugs. I had to intentionally forego the level of understanding that made me a good student in order to keep up with the pace of the business.
An Unconventional Journey for a Female Scientist to Web Developer
I learned when to trust code samples found in documentation and on Stack Overflow. I learned how to play with new technologies without getting too deep into the weeds. I learned how to prototype projects and how to throw out those prototypes as soon as I knew they wouldn’t make it to production. Unfortunately for everyone involved, I learned the dark art of the Monkey Patch.
With rapidly changing business requirements and a relatively limited grasp of the total scope of software engineering, I had to embrace the fact that I wouldn’t know how to do everything I was going to be asked to do. I also learned to stop trying to get everything just right; sometimes my solution was going to be a bit of a hack, and that’s okay. Crucially, I also learned to ask for help.
Mentorship matters when conjuring perhaps more than for scribery: when you are playing around in unknown territory having someone to catch your mistakes and establish best practices is an incredible asset. I’ll always remember panicking when I accidentally deleted several records from our production database at Amirsys. My then bosses-and-mentors Brian and Steve helped me restored the records from an automated backup. My employment at Amirsys was not terminated, and I learned some very valuable lessons about database transactions and deployment environments. Left unsupervised my conjuration might have had very serious consequences for both Amirsys and for me.
Teaching to Learn
Receiving mentorship is obviously wonderful, but it’s also important for your own growth to be a mentor. Sharing your experience is a proven way to better retain the knowledge yourself. Teaching helps us practice, and puts a capstone on our own skills in a variety of ways. By setting aside time to be a mentor you can dramatically improve your own retention, and even expand your own knowledge and understanding of the topics you teach.
One of the reasons teaching is so beneficial is that students ask great questions. Frequently students ask my favorite question: “Why is that?”
Giving satisfying answers to a student who keeps asking “why,” requires a scribe with deep roots in the topic at hand. Jumping into any student’s project and debugging it requires an instructor to facilitate the use of packages, API’s, and SDK’s that they might have never used personally — the bread and butter of a conjurer. Being a teacher helps you dynamically switch between these two skills.
I have been lucky throughout my life for opportunities to teach: I’ve been gainfully employed as a math tutor, a computer science TA, a debate coach, and now a web development and computer science instructor. Each time I’ve had the opportunity to teach a familiar topic I extend my own mastery of the topic. Student’s help me find my own holes by asking insightful questions, and repeating what I’ve already learned extends the shelf life of my knowledge through spaced repetition.
My journey as a programmer has taken many turns. I’ve learned how to be an eloquent scribe with a down-to-the-transistors understanding as well as a make-it-work and fix-it-later conjurer. But nothing has been as satisfying or better for my own personal mastery than the time I’ve spent as a teacher. So I say: to learn it all, teach your friends!