Tuesday, July 3, 2012

Will Program For Twenty Cents

The subject of this post is actually programming, and another word after it which makes the post title a geeky pun. Bonus points for those who can figure it out! (Hint: You won't find the word anywhere in this post. I took extra effort not to use it).

From the first time I looked at computer code, I was fascinated by it. Ironically, during elementary school, I didn't think I'd ever be smart enough to program computers. This may have been because I wasn't smart enough at that point - the only intellectual limit of childhood seems to be one's inability to think farther than a week ahead. Better understanding your own potential for growth is part of maturing into an adult, I have found.

When personal computers first became available, their use was not widespread. Rather, the internet was simply a network of the major computers that existed at that time, and primarily between research facilities. Programming at that time would have been a headache compared to what it is today. Since binary (or more generally, anything digital) is nearly the opposite of how the human brain works (everything is analog), computer instructions then were written in hexadecimal, a number system on the other end of the scale from binary. Binary uses two digits; hexadecimal uses sixteen. In comparison, the number system we write with uses ten digits, and is simply called decimal.

Even in hexadecimal, computer code is all just numbers, but in a form more easily usable by humans. This is because, due to having eight times more digits than binary, a very long number in binary becomes a very short number in hexadecimal, meaning a lot more code can be shown with very few digits. This was the first form of software programming; hardware programming previously used switches that had to be set by hand.

Next came spaghetti code. The mental picture is fairly accurate - instructions just thrown in wherever they were deemed necessary. There was no real structure or organization at all. Each instruction was directly mapped to an address; the address was actually part of the programming code. The addresses had to be in order, but you could skip ones you didn't need, or decided not to use. You can see how it got its name with this kind of ad-hoc arrangement! However, the one improvement was that actual words could be used instead of codes. This introduced the need for another program, called a compiler, to come along after you write the code and turn the words into the hexadecimal and/or binary instructions that the computer can execute.

The first real structure came with the invention of - you guessed it - 'structured' code. The new idea here was to cut up the spaghetti into logical segments. Each segment, also known as a 'routine' or 'subroutine' was given a name, usually one that described what that portion of the instructions did. For instance, you might have a routine to display text on the screen, and another one to ask the user for input. In this way, instructions were organized by function, rather than being all thrown together in one big monolithic mess. In addition, this introduced the idea of parameters. In the case of a routine that displayed text on the screen, a parameter could be the text to be displayed. Whenever you invoke or call the routine (so that it performs the instructions contained therein) these parameters are given. This way, you need not reinvent the wheel and write the same code over and over each time you want to display text on the screen. You just call the routine that does it for you, and pass the text you want displayed as a parameter. This is also known as functional or procedural programming, because it is organized by function (routines are also known as functions or procedures).

This phase lasted quite a while until the next revolution: object-oriented programming. This provided not only further structure, but also several important, new concepts that would change the way programming was thought of, and what it was capable of doing. These powerful new tools created quite a stir and made computer code far more elegant and interesting. The three primary concepts are: encapsulation, inheritance, and polymorphism. All three fall under the umbrella term "abstraction" since they all give us new ways to represent abstract ideas (or objects) such as bank accounts, transactions, and other such things managed by computers, using computer code. This means the code is structured in a way that more accurately represents these objects, and therefore, more accurately handles and manages them.

Encapsulation is the idea of the black box. Think of a car engine, for instance. Many people haven't the foggiest notion of how a combustion engine works (perhaps a better example is how an airplane stays up in the air, since even fewer seem to understand that secret). However, that isn't a very big problem, unless of course, your car breaks down (or the airplane crashes). As you drive the car, it doesn't (and shouldn't) concern you what happens when you press the gas pedal, or the brakes. When you turn the steering wheel, you don't care how the engine responds and decides which way to turn the car. It doesn't matter to you, because it's a black box system. As long as it does its job, the black box can remain a mystery, and there is absolutely no problem with that.

We can do precisely this same thing with computer software. We can now write a portion of code that can interact in a well-defined way (known as an API) with other code. We can bundle up the code we wrote, sell it to someone else, and then they can write code on top of it that turns the steering wheel and pushes the pedals, so to speak. They don't care how our code works; it just works. When they turn the steering wheel, the car turns, and when they push the gas pedal, the car moves forward.

Encapsulation is accomplished in the software world by defining the scope of program elements. The scope tells us where in the program (and outside) we can see those elements. Functions, as mentioned earlier, are one such element. Stored data is the other primary element. We can define something as public (viewable by everyone, everywhere) or private (viewable only within the black box). This allows us to share the information we want, and protect the information that shouldn't be shared within the black box.

Inheritance is a lot simpler; you are already familiar with one form of it - genetics. In programming, inheritance works exactly the same way. We can write generic code that acts like an Animal - it has behaviors (defined by functions) such as speak, play, sleep, and so on. Then, we can write more specific code that acts like a Dog, but inherits the more generic aspects that it shares with all Animals. All animals can speak, but when a Dog speaks, the behavior can be defined specifically as "Bark." We could then write a Cat which inherits this same behavior (speaking) but again, when we invoke the Cat's 'speak' function, instead we receive a "Meow" in response.

Finally, polymorphism is the most complex of the three. It's quite a difficult concept to wrap your mind around, even if you're a programmer. However, the simplest way to explain it was already done in the last paragraph. It is closely related to inheritance. When a Cat speaks and we hear a "Meow" then a Dog speaks and we hear a "Bark," this is an example of polymorphism. In either case, we are simply invoking the inherited "speak" function - but the behavior is different depending on the subclass (Cat or Dog). This is polymorphism - the ability to define a specific response to a generic behavior.

In essence, these abstractions give us two dimensions in which to program. With structured design, a function always does the same thing every time you call it. With object-oriented design, polymorphism gives us a different response based on both the function/behavior and the object/idea. Invoking the same function on a different object normally produces different results.

Now, prepare your mind for some extreme warping - we are now in the age of subject-oriented programming, where we can wield three such dimensions. The result or response we get from a function can now be defined by the name of the function, the object on which it is invoked, and the subject related to the invocation. For instance, my Dog might have a different bark depending on whether he was happy to see me, or whether he was trying to fend off an intruder. This constitutes the subject, or aspect, in which the behavior is invoked.

Aspect-oriented programming is very similar to subject-oriented, but to spare your mind further warpage, I won't go into any detail on the differences between the two. Instead, I will just say that programming has come a long way from using hexadecimal codes and command line interfaces. We now have the power to determine the software's behavior based on the desired function, the object performing the action, and the context in which the interaction occurs. This gives incredible potential even just for artificial intelligence. Computer code that can update and edit itself is now just around the corner.

And yet, DNA has been doing exactly that for thousands of years. Is that something that occurred by random chance? I think it's about as likely as computers assembling and programming themselves out of thin air. It takes a mind more intelligent than a computer to design and build a computer. By the same token, it takes a mind more intelligent than a human mind to create such an incomprehensibly vast universe, and to populate it with beings whose bodies themselves contain technology far more advanced than computers; least of all, the human mind itself.

No comments:

Post a Comment