Sunday, January 8, 2017

Explaining To My Dad: What "Programming" Actually Involves

What makes a good computer scientist? Is it the ability to program? Is it the ability to apply mathematics? Is it the mythic ability to pull esoteric one-liners out of thin air? Here I will attempt to answer these questions from the perspective of a layperson by analyzing the type of work computer science is, and the skills that go into it.

Objectively, a good programmer will make software that makes some system that operates well, gets done on time, and appeals to its user-base. Accomplishing those three things well requires you to be able to understand the tools and platform you're using enough to trick the computer into doing exactly what's in your head.

Software Systems and the Work that Goes into Them


Computer scientists work within a computer system, thus, their work involves every layer of its operations whether they know it or not. Knowledge of their work's effect within a computer system is one indicator of a good and effective computer scientist.

Good understanding?

At the highest level, a program tells things to the operating system which sends messages to the hardware to get those things done. The program describes its commands in vague, nearly human terms, then the operating system translates them into extremely specific commands for your hardware. This is how your computer works.



As the user, you're only really aware of the "program" you're running and the OS, so it's sort of natural to assume that there's a set of programmers that just make the applications you use and another smaller set that make the OS. While being a good assumption, it's not specific enough to reveal actual work.

A more programmer-centric model would look like this




Each component could have its own team and specialization, and they all have a similar set of jobs. For each system, you can generally split it into a front-end that presents a set of tools and back-end that uses a set of tools closer to the machine's instructions, and closer to the bottom of this chart. For an easy-to-learn language like python or matlab, the front-end is the simple syntax itself and the back-end is a more complicated language. For a operating system, a front-end would be its system functions, and its back-end would be the kernel that interfaces with hardware. You often have teams managing each of these sub-components separately. Thus the job description of a programmer is a person that translates some vague idea like a graphical application that lets your friends hit "like" on your face into instructions that will interface at the lowest level of the machine. Let's peek at what each level looks like and the tasks that consist of most of the work.



User Program:

User Program: Where you only focus on the user experience

-Deisgn and create graphical interface using rendering tools
-Define what each menu button does
-Create some central logic behind the program itself
-Think of a good way to structure all of that



Developer Program:

Systems Programming: Where you create specialized tools

-Decide on a set of tools that User Programmers can rely on
-Figure out what part of the operating system you need to use to implement these tools
-Make your tools extremely fast, as well as robust



Operating System:



Operating System: Where you think of the devices

-Create adapters for different hardware platforms
-Create programs to start and stop tasks
-Create ways to manage different tasks
-Create ways to efficiently manage memory between tasks
-Create tools to make tasks on operating system

Hardware: Where this chart is a simplification

Hardware:
-Design various components in block-diagram to get something resembling the task(hard)
-Define each block(hard)
-Figure out necessary timing for each component and how to sync


Theoretical Math:
-Derive elegant, efficient abstractions for engineers to use for their tasks
-Define fundamental problems that most other problems will stem from
-Become a tenured professor then do whatever you want(hard)

This is Nice, but How Do They Use These Things?

The best way to illustrate how these levels of knowledge come into play is by providing examples of normal work-flows getting affected by them.

Scenario 1:
So, say you have to make application X by due date Y. You are extremely good at the language Serpent with the "abacus" framework. After porting your app, all of a sudden your users are experiencing a bug on a core feature. The code itself is fine, and it only occurs on the new platform. This means that the error is happening on a lower level. In order to fix this, you need to look at the implementation of Serpent and how that part of the code is written.

LESSON:
If you only know the surface tools well, then everything below that isn't guaranteed. If your users move platforms, you may encounter errors you don't know how to fix!

Scenario 2:
You need to make a feature that searches your database. You're an ace so you immediately implement that feature perfectly and elegantly in your favorite language. The problem is, that the customers all of a sudden yell at you for using your own language instead of the one they wanted it in. They never said anything about this, but it would be too inconvenient to them to adopt your weird esoteric language!* You knew everything perfectly, but the inability to properly communicate an agreed-upon product wasted your effort!
*The language is LISP

LESSON:
You can be a perfect programmer, but if you don't communicate effectively about what needs to get done, then effort is ultimately wasted.

Scenario 3:
You need to fix a bug by the end of the day, but in order to do so you have to use a new tool you're unfamiliar with. However, since you've used different debuggers before, and you know how they're implemented, it takes you only two hours to learn enough of the tool to hook it into your program and then recreate the issues your user was having.

LESSON:
If you understand a similar tool or the way something is implemented, you'll learn the tools faster. The more reference points you have, the faster you learn.

An Important Reminder:

While knowing all of these makes you the ideal programmer, programming itself only requires the ability to write in some language, and you can often find people that know nothing else but are very effective within their domain. At the same time, the knowledge of these separate levels comes into play for any computer platform and language. They give deeper insight and let you do everything more effectively than the guy that's only good at the specific. That's why these components are the basis of a good computer science curriculum, and that's why "good programmers" aren't just good at a specific language, but know their theory quite well.


No comments :

Post a Comment