The best thing you can do is read & write a lot of programs, and pick them based on what is new and unfamiliar to you. Try writing programs from different domains (compilers, parsers, network protocols, distributed systems, data structure libraries, desktop GUIs, web GUIs, mobile GUIs, graphical visualizations, machine-learning, data storage engines, geo data, command-line scripts, testing, automation). Try writing programs in different languages (Haskell, C, Javascript, Erlang, Prolog, Go, Common Lisp, Python, etc.). Try writing programs of different scales (weekend hobby projects vs. Google Search), and try entering them at different points in their lifecycle (starting with a blank editor window vs. parachuting in when the company already has a million lines written and the original authors have long since left).<p>I'll second what mindcrime said about never really feeling like you know everything. The rate at which new CS knowledge is being created is far faster than the rate at which I can learn, so I've long since given up being able to learn it all. But what I can do is see patterns. I can see that the new single-page Javascript MVC frameworks are reinventing patterns that were common in desktop GUIs a decade ago, or that what Chrome's rendering engine is doing when it schedules JS execution isn't all that different from the Win32 message pump, or that Guice/Dagger are basically introducing data-flow programming to Java, or that Go's channels & goroutines are basically the same as Erlang messages and processes. Then I can apply what I already know about those other programming paradigms to the new technology, and only focus on learning the differences. That's a lot easier than picking up a new concept from scratch.