Saturday, January 9, 2016

Depth of understanding of Tech Stacks

So before I start on this post, it's worth noting that this is about the rate I'll be posting on this blog probably. After the burst of posts to seed the blog initially, I'll probably post every 2-3 weeks about the most interesting project I've been working on. Since I started this blog, I've mostly been on winter break from school, and I'm taking time off instead of getting another internship (because after graduation, I'll be working full-time and I wanted to enjoy some time off). So my apologies for the lack of a constant stream of posts, but this is how it's going to go from here on out!

So today's topic is actually taking a break from coding for a little bit to talk about a post that I read from one of Steve Yegge's blogs. The post discusses the deepness of understanding of a technology stack (like, the WHOLE stack) that the average programmer needs to know. Is it okay to only know how to program in an application language, or does the average programmer also need to know how to program in a lower-level assembly language? Do we need to know how to implement circuit logic in hardware? What do we need to know about semiconductors? I've been thinking about this specific question for a couple months now, and I honestly don't think there is a good single answer.

What I do think, however, is that there is usually some situational variance. For instance, lets take any algorithm that uses multiplication. In the hardware you intend to run your program on, does their system implement constant time multiplication (number of CPU cycles, not the number of assembler instructions)? If not, any time you intend to multiply something it could take some extra non-constant time. Does the hardware that you are using have a specific hardware implementation that will make a specific algorithm run really quickly? For instance, an ASIC chip that will be used for bitcoin mining? The issue is not so easy to answer with sweeping generalizations, and that is why I think that the situation matters most when deciding how deep down a technology stack to learn.

Something that I have noticed about me and my fellow students (I'm a computer science major, not a computer engineering engineer), is that we tend to focus at too high of a level. I also think I'm less guilty of this because my concentration is in operating and distributed systems and I write a lot of C for school and MSIL for work, however us students tend to think of technology and programming strictly in the text that we write. There is some cognitive disconnect for a lot of students that says there is a magical layer called the JVM or .NET or Mono or whatever that does some hand-waving and all of a sudden the results are displayed on our screen. Nobody in school is taking the time to learn the internals of a language, never mind what that language is built on! They talk about the MEAN or [L|M|W]AMP stacks like the stack starts and ends within those four letters, which is absolutely not true! It's just abstracted away so that most of the time it doesn't matter to the application programmer. We are taught in school not to worry about the internals of a system; instead we should worry about writing fast application code (which is also very, very important) without worrying about how we can leverage the system we are using.

And in a way, it doesn't even matter that we don't have a thorough understanding of system internals! You could write a million lines of Python or Ruby and never need to worry about why your algorithm is slow. Many modern languages are exceptionally fast, and for the most part for simple web applications, the basics tools are good enough. What if you're writing something a little more interesting though that requires exceptionally quick results? What I think is happening nowadays is when we write in very high level languages, we are at risk of becoming complacent with the speed of the code we write. If you look at Python code for some algorithm, there are few ways to creatively speed up that code. There is a completely different attitude in C or C++ programmers, however. There always seems as if there is something you can do to give your code a little more punch. Take template meta-programming for instance in C++. You can define a template to be used to do some non-constant time calculations at runtime in constant time, so for instance you can calculate a factorial in constant time at run-time. This could potentially be very powerful, and it is completely lost on Python programmers (and programmers of many other high level languages)!

To be fair, the lack of support for features that enable much faster code allows a programmer to write much more simple and easy to read code which could save a lot of money and headaches. It really depends on what the need of the project is. I had talked to an engineer on the Bing team who said he wrote in mostly C++ because his code was extremely performance-intensive, however, one could certainly write a fast enough website in Python (Reddit, for example, is written using a lot of Python). Which brings me back to the original point of this blog post: everything is situational in software. There is no one-and-done solution for all of one class of problem. Which means that the depth of a technology stack that we need to know is highly varying. And it's always difficult to know when a system will make a specific function faster because you don't know what you don't know. I guess you could look at your application code and find potential bottlenecks and try Googling ways to fix them, but that's not a very good answer.

I guess we have to live with Yegge's comments: that there are a few major CS tenants that we all need to know, and rely on situational knowledge for the rest of the time. That's kind of okay because it will work in most cases, except when it's not and some critical performance slips through the cracks. I guess the answer is really just pay careful attention to every line of code you write, and do everything for a reason. Eventually, after months and hundreds of thousands or millions of lines of code, you can start to get a good feel for the environment you are working in. In other words, it just takes time to learn it all because writing code is hard! It's tough to learn, and even tougher to learn how to do well! I would say that the only language I've written upwards of a hundred thousand lines in is C#, and I still have a good amount to learn about .NET. The more we write, the better we get, and the better we will learn to leverage the systems we use.

Anyway, sorry for the amount of words in this post! Next time I'll break out some code and make it easier on the eyes. On the docket for this week is prep for the semester and a trip for a job interview after graduation in California (I live near Boston). This is my first time heading West, and I'm very excited! Anyways, I hope this post has been interesting for you! Leave a comment below if you have any thoughts!

No comments:

Post a Comment