Any time a claim starts with the clause "It's a new era...", you should automatically be wary. Modern times have brought a slew of incredible advancements in technology, but if we're honest, the proverb still holds true: the more things change, the more they stay the same.
Few arenas are haunted by zeitgeist quite as much as the programming field. We tend to select technologies by nothing more than popularity and follow design patterns blindly to our own detriment. We have absurd conversations about whether "X language is dying," and constantly debate the relevance of anything we deem "old-fashioned".
So it should come as little surprise that popular programming trends call for the dismissal of half our historic toolbox, and I think that's harming us more than we know.
A Word of Warning
Now, before we go further, I ask that you not hold this up as evidence that real programmers use Emacs, Vim, Nano, or butterflies...
Integrated Development Environments, or IDEs to us acronym-obsessed nerds, are absolutely incredible tools. I'd go as far as to call them essential, indispensable tools in nearly any modern programmer's toolbox. If you haven't found one yet, you really need to, especially as there are hundreds to choose from: Visual Studio Code, Atom, Brackets, Eclipse, Emacs, anything from Jetbrains...
Going one step further, I'd actually say there is absolutely no excuse not to learn and use at least one IDE on a regular basis, especially in writing production code. Even the clunkiest terminal-only dinosaur is capable of running Emacs. If I hear tell of anyone shipping new production code written solely in Notepad, in lieu of an available IDE, I will personally smack them upside the head with their source.
Now, with that out of the way...
The Dark Side of the Power Tools
If you've ever done any woodworking, you know how much of a timesaver an electric drill and power saw can be. It would be rather ridiculous for a professional contractor crew to have access to these tools, and not use them.
However, that same contractor crew is almost certainly capable of doing the same work without power tools. In fact, I'd guarantee that they have hand saws, clamps, screwdrivers, hammers, sandpaper, measuring tapes, and levels in their toolboxes. One might wonder what the point is. If we can do it quicker using the automatic tools, why bother carrying these manual tools?
There are two very good reasons that I know of:
Power tools fail! You might not have access to the necessary power, or be in a situation where it isn't safe to use the tool (such as in the rain). There are a handful of rare, but very real, situations that hand tools are needed.
Hand tools are actually easier in some cases! Precision work is difficult with some power tools. The very thing that makes a power tool useful - power - can actually make the job harder at times. Hand tools offer more fine-grained control.
Besides these issues, however, is a deeper issue: the same skills are needed to use both manual and automatic tools effectively. Sure, someone who has no knowledge whatsoever of how to use a screwdriver can appear proficient with a drill, but chances are, their technique will ultimately result in a lot more stripped screws. Someone who cannot use a handsaw might easily use a power saw table, but their inexperience with cutting accurately will make for more mistakes. Power tools allow you to make bigger mistakes quicker.
Every carpenter must be able to measure, sight, select tools, and control those tools, in the same manner. The slower, more manual process of using the hand tools trains those instincts. Once proficient, that individual can make the most of the power tools, where the combination of the tool's conveniences and the worker's instincts results in quick, efficient, accurate work. Power tools can contribute speed and accuracy, but they cannot compensate for a workman's incompetency.
The Programmer's Power Tools
Many people are shocked to learn that I summarily ignored Intellisense and autocomplete for nearly a decade. I learned to debug as quickly and effectively with a few well-placed print statements as with a debugger. I actually wrote and compiled practice code in the command line!
All that might sound like wasted effort on my part. After all, Intellisense, debuggers, and featureful editors are essential tools! Why wouldn't I avail myself of them?
The fact is, I knew I could learn how to use those tools in mere minutes. They were available to me, and the day would come when I would choose to employ them constantly. These are the power tools we have in our toolkits, and they're all wrapped up nicely in the IDE, alongside dozens of other useful features. Indeed, that day has come for me: I virtually never write C++, Python, HTML, or CSS without my IDE of choice.
However, I've reaped rare fruits of my early decision to abstain from the power tools. I can write a decently complex chunk of code in a text editor, and have it work on the first or second try, with few (if any) logic errors. Adding the convenience of an IDE to my already honed skills means that I frequently write entire classes that work on the first shot.
In training young programmers, I've discovered that their early reliance on IDEs have robbed them of many of these skills, resulting in code that is seldom stable, clean, or efficient on the first half dozen attempts. If they continue in this manner, their growth is stunted.
There are essential skills we can only gain and refine by writing code without an IDE! This doesn't mean we don't use IDEs on a daily basis, but it does mean that deliberately honing this skill allows us to use IDEs at full efficiency.
Text Editor Coding
I wish every programmer, at some point in their career, would undertake writing an entire programming challenge solution in Notepad, with the added requirement that it compile and work on the first try. No syntax highlighters, no Intellisense, just the editor and the language documentation.
There are several skills this trains:
Grok the Syntax
You have to actually memorize major syntactical rules of your language; this, in turn, requires you to understand the why of those rules. Knowing "why" invariably produces better code, in any language.
You can certainly look up the boilerplate and syntax every time, but sooner or later, the sheer inconvenience leads to you understand what in the hey int main(int argc, char* argv) { //... }
even means! Once you know that, you can actually start using it to your advantage. Patterns and solutions reveal themselves to you. Language behaviors become part of your instinct.
Spot the Errors
You train your eyes to spot typos, including those that syntax highlighting and your linter normally point out for you. Later, those tools merely take a majority of the workload off your editorial eye, freeing you up to spot the peskier errors that the IDE misses!
When I was working in ActionScript 3.0 several years back - a language I had never learned to write without an IDE - I forgot a semicolon in a loop, and created an infinite loop in a particularly pesky part of my codebase. It took me two weeks to find it! By contrast, after years of practicing writing C++ without Intellisense and linters, I can find the same sorts of loop errors in mere minutes.
Type In Style
Messy code is unmaintainable code, but the IDE's code formatter often allows us to get complacent about our spacing and brackets. Laziness is quite virulent, and habitual failure to properly indent can quickly turn to failure to properly spell function names right. (This isn't even remotely theoretical - I've observed the exclusive pairing of these lazy habits in nearly a decade of mentoring programmers.)
By stripping away the code formatter, we are forced to reap the immediate consequences of our own sloppiness. We have to suffer through eye-tiring rereads of our code, until we are forced to refactor the style just to make it readable. We learn to take pride in a clean, well-styled source.
When the IDE is reintroduced, it merely saves us the extra keystrokes of proper indentation and bracketing. The code formatter becomes a mere janitor, cleaning up after the occasional typo. Meanwhile, our style habits have now spilled over into the areas the IDE cannot help us with: naming conventions and standards compliance. We're in the habit of doing things right!
Old School Debugging
Debuggers are an utter lifesaver for which I am daily grateful! However, you'll never hear me say "I don't know what I would do without gdb and valgrind". I do know what I'd do, because I've trained myself in the forgotten art of debugging without a debugger!
Now, I absolutely don't recommend that these habits be used in place of your language's debugger tools. That would be, frankly, moronic. Debuggers exist for a reason, and there's no excuse not to know how to use yours! At the same time, debuggers are still a power tool. Being able to debug without them means we can debug far faster and more efficiently with them!
Which would you rather do: spend an hour stepping through your source with a debugger, or spend ten minutes stepping through your source with a debugger?
Desk Checking
My good friend and fellow coder, Chris "Fox" Frasier, spent a good part of his younger years working in FORTRAN, COBOL, Assembly, and punchcards. In his era, debuggers were barely a dream. If you wanted to debug your code, there was only one way: desk checking.
Desk checking involves reviewing a printed copy of your source, and actually being the computer. You step through it in the same manner as the machine, noting the value of all your registers and variables as they change. A steady practice of desk checking leads to us suspending our own mental shortcuts for the pure logic of the computer.
This is truly a lost art, but it's one we need to reintroduce! I've done desk checking nearly as long as I've done coding. As a result, I am able to manually allocate, manage, and deallocate raw memory in C and C++ with very few errors, and debug nearly all of the errors I do get in a matter of minutes. I've learned to think like the computer. Memory management, caching, conditional branching, order of operations, data casting...all of this is just instinct to me!
Of course, I use a debugger regularly, but my desk checking abilities have merged seamlessly with it! As I step over and into code, I'm running the logic in my own mind, and can often find the problem in minutes. Sometimes I don't even need to run the debugger at all - one careful read of the function reveals the problem.
Flowcharting
It's unfortunate that flowcharts have fallen out of favor with so many coders. Perhaps it's because they've been treated as an end, instead of a means, but I wish more coders would learn to use them to their advantage.
A good flowchart can help with both preventing and debugging errors. It takes the non-linear computer logic out of the limiting, linear structure of the source code, and puts it into a form we can process more easily. Even if one doesn't follow the "official" symbology, a quick flowchart on a whiteboard or notebook can untangle some of the most pesky logic errors.
Print Statement Debugging
I don't think this technique gets enough credit, honestly. While many young coders (unwisely) use print-statement debugging in lieu of a proper debugger, it doesn't nullify the potential usefulness of the technique.
In essence, print-statement debugging is really just a form of I/O Debugging, the earliest form of testing. In the era before debuggers, this was the other tool a programmer had, besides desk checking. Fox has described sessions just watching the lights blinking, and inferring the logic error from that data alone!
There are some bugs I've chosen to chase down using a few well-placed print statements, instead of firing up gdb
. This wasn't laziness or ignorance, but a deliberate desire to approach the situation in a different way than what I was used to.
Mind you, I wasn't just dumping every piece of available data onto the command line. I'd do a quick mental desk-check, figure out where the logic was probably breaking down, and then writing a print statement to show me the relevant variable values and function call order. I was forcing myself to select a subset of information with which I'd solve the problem. This is in contrast to a debugger, which just hands you everything. Then, given the output, I'd have to run the logic in my mind and infer the issue.
Was it harder? Absolutely! But the effort has paid off. Now when I use a debugger, I can zero right in on the information I need, and figure out what's wrong in far less time.
This has also trained my test-writing habits. Having done plenty of this sort of debugging, I have a better sense of what is important to test, and what is best left to the background. After all, testing absolutely everything is a tremendous waste of time and effort.
Command Line Compiling
The last skill I've gained from working with an IDE is the necessity of compiling or running the code myself. This applies to any language, whether you're building a C++ binary, or executing a Python module. By running the code manually in the command line, you learn how the build/run process inherently works.
Knowing the steps involved has saved me considerable time in writing portable build systems, as well as in making decisions about languages, libraries, tools, and build options. I can say from experience, there is nothing worse than completing a project, only to discover that it's impossible to package the binary on a targeted platform because of one of your dependencies!
Actually, this is one thing I wish I'd learned sooner. I had often compiled or run single-file programs in the command line, but it wasn't until recently that I actually tried building anything larger that way. Let me tell you, it's an entirely different process!
Even if you ultimately use your IDE and automatic build system for your production builds, you should challenge yourself to compile an entire large project on the command line at least once. Now that I have that experience, I can diagnose nearly any build problem in mere moments.
Reintroducing the IDE
I hope you're now convinced that writing code without an IDE develops many valuable skills and habits. However, I must once again stress that I am in no way advocating for eschewing IDEs! These power tools are incredibly useful, especially when paired with the skills we gain by working without them!
There are a couple of situations where our lack of IDE-reliance comes in handy:
You may not always have your IDE handy when you are called upon to fix an urgent issue. Imagine your build has fundamentally broken, and the chain of responsibility means that you need to do something about it right now. You don't have the luxury of installing IntelliJ IDEA on your Uncle Steve's desktop; you need to bring up a private browsing tab (so your creds don't get stored), log into GitHub, and fix the fundamentally broken function that somehow got pushed to live prod. (Yes, this is a rare situation, but I've had this happen to me two or three times in my career). If you're IDE-reliant, you're entirely useless in this case. But if you know how to write the code without the IDE, you are capable of editing straight in GitHub, fixing the problem in less than ten minutes in one shot, and mitigating major disaster or inconvenience.
In some cases, the IDE just gets in the way. Sometimes, I actually prefer printing off my source code, settling into my armchair with a cup of hot tea and a red pen, and just desk-checking it. Not only does it give my eyes a break from the screen, but the change of environment and tools help me see the problem in a different light. I might even solve it faster than if I had used the debugger!
Most of the time, you'll still use your IDE, but I guarantee that those additional skills will allow you to write cleaner code in less time. With the added features and safety nets - syntax highlighting, linters, Intellisense, autocomplete, debuggers, and the like - your already good code has the potential to be truly great code.
Top comments (27)
I started programming professionally in the 1980's, primarily C and MASM, using ASCII text editors. I had to write my own tools and extensions to editors to do things that are integrated into the IDE today. I don't get the attraction to doing things retro that seems to be a trend now. I see no advantage to ditching the efficiency of modern IDE's to use command lines and such on a real paid project.
It might be fun, I guess, to see how things were done in the "old days", kind of like driving a Model T car on a Sunday afternoon country drive. But that Model T's appeal would wear thin quickly if you drove it as a daily commute with no AC, no Bluetooth, no radio and so forth.
Well, I never said it was "fun" or "trendy," nor am I advocating for ditching IDEs and doing everything "old school" as a rule, so I suspect you may have missed something in the article. In fact, I explicitly said...
I'm not referring to doing this manually as an end or habitual practice, but rather as a means for honing certain skills...skills which, when paired with the modern convenience of an IDE, allow one to write better code faster.
My first language was C at university in 2005 but the first language I had professional experience with was FoxPro for DOS in 2008. By then I was already introduced to OO with Java and C# also at university.
The IDE didn't have any kind of intellisense or highlighting. I had to fully understand the language instead of waiting for the IDE to teach me only when I made a mistake.
This made my code better and my coding reflexes more natural. I believe that those 4 years working with a terribly outdated language made me a better programmer in Java, C# or Kotlin (which are my main daily languages today).
That being said, it is great when a well thought out IDE like IntelliJ tells you stuff that you didn't realise but are obvious like testing strings like "text".equals(variable) to avoid nullpointers in Java or when it alerts you to whole 30 lines blocks of code that are completely duplicate and you can refactor, etc.
IDEs are great and should always be used in a professional setting, but doing challenges on notepad are a good thing to do from time to time.
Thanks for sharing your experience!
I guess the point is: make good use of IDEs, but don't depend on them.
Yes, exactly.
Even though modern editors have made software development a bit easier and manageable, it's not the only way to go about doing it.
I know a few very experienced software developers who still use ed, which is a line text editor (not even a full screen text editor) and has no support for virtually anything that modern software developers rely on (e.g. auto-completion, syntax highlighting). Instead, they rely on the entire ecosystem of tooling (e.g. command-line tools) to accomplish the task.
Honestly, there might be an exception if someone has honed their craft to that point. Still, the tools (in some fashion, at least) should be involved somehow, at least as a safety net. If you're going to write your program in the command line, it had better run through a linter, proper tests, and the like.
Autocomplete and syntax highlighting do have their place: they prevent some of those pesky minor errors we all miss. It's not impossible to work without them, but they are useful.
However, for the record, that statement was primarily for the younger coders who don't have 30 years experience in making and fixing mistakes while coding without the safety net.
Certainly.
I was not suggesting that engineers should develop without safety nets.
On the contrary, when I said...
I meant exactly what you have said; they run their code through stringent pipelines locally and remotely to guarantee quality of software.
I guess the point I was trying to make is that for modern software development, I would have placed the emphasis on practices that guarantee quality of software, rather than on tools.
In other words, you can use whatever tool you feel comfortable with as long as you adopt the practices to guarantee a high quality of code.
Edit: Analogy:
Say, I use a ball-peen hammer to drive a nail and you use a you use a regular hammer to drive a nail. If you make a mistake, you're tool has built-in facilities to correct the mistake and remove the nail. If I make a mistake, I have to reach for a different tool to correct the mistake. But as long as we both can deliver same quality product, does it matter that I used a ball-peen hammer?
I think I agree. I just didn't want to leave that much room for the group of inexperienced coders that uses text editors out of sheer laziness for learning how to properly use anything else. ;)
It's kinda like building a dining room table with only hand tools, to be honest. For most people, it's going to take a lot more time than necessary, unless you're this guy...
So, until you're that guy, probably shouldn't be trying to ship critical code with only those tools.
Agreed! I try to editor hop at least sort of regularly, and while I have settled into an IntelliJ groove of all things of late -- my preference when using any IDE is to disable as many of the tools it carries as I can.
I usually:
Probably because we're in different sectors. Application development, everyone and their mother relies on IDEs. It's just the expected default behavior. By contrast, web development hasn't really had any decent IDEs until the last few years (save for WYSIWYG editors, which don't count in this regard).
I'm glad we started that conversation, because this is a very nice read :).
Those skills you mention (e.g. print statement debugging) are indeed valuable skills, but I consider them quite separare skills, that may or may not be useful depending on the context (like knowing the ins and outs of a specific language). As such you're only a better developer for having them when the context requires them.
As to being able to change code quickly without an IDE, the only context I can think of that warrants that kind of haste, is when something is wrong in production, and there: with or without an IDE, it's dangerous and should generally not be done. Most cases I've come across where this was needed were in fact because someone had made a (non-critical) change for which they had bypassed the proper CI and/or acceptance flow.
Yeah, it's a rare case, although it sometimes can't be avoided. Still, I don't advocate bypassing the CI!
I have used all these techniques while using an IDE. Not sure they are mutually exclusive. Did they help me write better code? For me I can't really say yes to that. What helped me is learning why readable code is so important and learning TDD. I would rather teach someone TDD first before teaching them using a debugger. It becomes a big time waste when you write a bunch of code then try to figure out what went wrong in ther debugger or even trying to step through the code in your head. I think knowing this has value but again not sure it helps anyone write better code.
This article reminded me of my old me:
Back in the days when I was pretty young and very obsessed with programming, I once write a full "game"'s code on paper - the "F1 on math paper" game. Pascal, 640x480 graphics mode :) (I was spending my summer vacation at my grandparents and had no access to a PC there.)
When I got back home and typed the code in, it was working flawlessly -- at least this is the way I remember it :). It felt good. It still feels good.
IDEs might alert you to bad habits that may slow down your code even if functional. They could alert you of duplicate code that could be refactored into a single method.
Thing is that an IDE might show you a second opinion on your code, which is always a good thing. It makes you think over that masterpiece of a code you just chiseled and find a little extra nipple for you to remove
Shoot, I actually added some functionality into the print wrapper I wrote for my company's utility library, which allows certain messages to be flagged as "debug only". That way, when the "verbosity" is set to high, they'll print, but when its normal or below, the debug messages won't even be parsed!
But, yeah, leaving those in is definitely a valid problem. Still, a decent code review process should catch them.