Assuming you mean <i>software</i> engineer ...<p>Hardware: understand CPUs, including caching, pipelining, RISC/CISC/ucode/uops, multi-core, on-chip networks, etc; GPUs; FPGAs; memory, and memory bandwidth; storage; PCIe bus; Ethernet. In all of this, your goal is to understand how it works in enough detail to reason about the performance of what you write, and to make decisions about platforms.<p>Learn a variety of languages to a basic fluency. Maybe 5 or 6: at least one assembly (Macro-11, Z80, x86, 68k, MIPS, ARM, doesn't matter -- pick one); C, some of Java/C#, LISP, Forth, Haskell, Python, Go, Rust, Erlang. There are two goals here: to train your brain to think at a level above any specific language to analyse the problem and come up with different ways to solve it; and to expose yourself to different language styles so that you can make a good choice based on the trade-offs between capabilities and popularity (~= ability to hire devs and maintain the product).<p>Real computer science. Learn enough about data structures, algorithms, parsing, complexity analysis, and formal methods, that you can apply this knowledge on those occasions that you need it. 95% or more of your professional life you won't be thinking about this stuff (largely because you'll be using libraries and languages where others have done it for you). But sometimes it's crucial to a design, to solving a problem, or to making the right implementation choices. No need to go overboard here, but enough knowledge is really helpful.<p>Software engineering: team work, design, development methodologies, estimation, and project management. Whether you end up working solo, in small groups, or in a big team, you need to understand how the daily practise of software engineering works.<p>Debugging computer systems is a craft. It can be learnt and it can be taught. It's not dissimilar to the process of analysis used during implementation, but during debugging you need to be able to work backwards from a symptom to its cause. It's mostly a way of thinking that you need to learn, but a good grounding in the tools (debugger, profiler, static analysis, tracing, packet capture, etc) is necessary too.<p>One area that I think is under-appreciated, but makes for a truly excellent engineer, is the ability to take the customer's point of view. Understand their problem, not from a programmer's point of view, but as an issue for their business. Being able to genuinely understand the requirements makes the design process vastly simpler, and much more likely to deliver a good solution. This means understanding how their business works, revenues, costs, competitive aspects, cultural aspects, etc, etc.<p>And finally, tools. Learn your toolset, and continue to evolve it. Go beyond just the IDE -- learn how to monitor the low-level performance (dtrace, perf, dstat, VTune, etc), understand shared libraries (ldd, nm, otool), compilers and static analysis; valgrind, Purify; git, hg, svn; diff and patch; tcpdump, netstat, nc; the better you can analyse and understand the OS, the hardware, the network, the better your systems can be.<p>None of this needs college. The formal computer science bit might be worth doing a few online courses. The rest is just as well done by yourself or in a small group, learning as you work or tinker.