Does implementation technology limit the problems you can solve?

12 Sep 2014

In the past week or so, I've heard two quotes that seem to say opposing things about the relationship between the implementation technologies we (and others like us) use to build software and the types of problems we can solve. I feel that they are both 100% correct and here's why.

Quote number 1 is

At the end of the day, it's all just code.

This statement is absolutely correct. Computer science has its roots in a set of mathematical models that describe the types of problems computers can solve. I've often said that computers really only add numbers together, and this (while simple) is absolutely true. Even the most complex graphics or games that run on your computer are the result of your computer adding the right sets of numbers together in just the right way, in such a small amount of time that we can barely comprehend it (think of your processor speed as the number of additions per second that your computer is performing).

This being the case, even the programming languages that look the most like natural language are subject to these mathematical models that mean they can solve the same types of problems as any other programming language. In fact, this means that somehow, any code that is written for the computer must go through some process to be converted into a (nauseatingly long) series of additions that the computer's hardware can execute.

However, some problems appear easier to solve in some languages than others, which brings us to our second quote:

A programmer's choice of programming language will dictate how he solves a given problem.

(NOTE: I think this may have actually been in the context of choosing a first programming language, with the argument that if a first-time programmer learns a very strict language, all subsequent attempts to solve problems will be accompanied by an unrealistic expectation that the problems will be well-behaved; for this reason languages like Javascript and Ruby are advocated.)

This statement is also absolutely correct, but not for the reason that is immediately obvious. As stated above, no language is any more powerful than any other in terms of the range of problems it is capable of solving. However, languages vary in terms of expressiveness (the types of functionality you can call on with as little code as possible), syntax (the series of keywords, data, and punctuation that comprises a logical part of a program), execution environment (does it run directly on the hardware or does it require additional programs), and many other characteristics.

The biggest differences that are often perceived as limiting the types of problems a language can solve are (a) the amount of external code that can be leveraged to tie in with other pre-existing systems and (b) the types of applications that a programming language tends to be used for.

To illustrate the first point, the success of languages like Java and C# can be attributed to the large framework of pre-existing code they ship with, in the Java Runtime Environment/JDK and the .NET Framework, respectively. Newer languages like Ruby and Python (and now even Javascript through the node.js environment and the Node Package Manager, npm) have found similar success through their use of open-source community-contributed modules. With any of these languages, virtually any problem can be solved with relative ease and without solving too many of the same problems as have already been solved.

However, even with comprehensive frameworks or vibrant code communities, languages often get pigeon-holed into viable solutions for only certain types of problems. C#, being sponsored primarily by Microsoft, has a stigma of being "only for Windows", when in fact it is viable for virtually every platform, including mobile. Ruby is often overshadowed by Rails, the massively popular web framework written using the language. On the flip side, languages like C, which is often described as being lower-level than many other "modern" languages, are stereotyped as being "systems-level" languages, both because they contain syntax that is intimately tied with raw resource management and because they lack significant and cohesive shared-code support beyond the system level (for instance, you don't usually see a C library for the latest social web API, while you do for Python, Ruby, and Javascript).

This doesn't mean that all programming languages are equal. Depending on a particular problem, a language or evironment may have the right tools already built to get the job done. Organizational, political, and financial strains might dictate that a particular Platform as a Service provider will be used, requiring certain implementation technologies. However, all solvable problems can be solved in all programming languages (mathematically provable!), so while it may be fun to build a solution in the newest untested technology, it's best to let the actual limitations on implementation technology prevail and focus on using all the tools available.