Tag Archive for 'Learning'

Fast Learners

Slow learners need weeks of training and years of practice to become skilled in their area of expertise. Fast learners «get it» within days, and become fully operational within weeks. Intelligence is certainly a factor, but it does not matter as much as one would expect.

How fast is a given person going to relate new concepts to her experience? Is she going to sift through all the feedback she gets, positive or negative, for lessons or ideas? Faced with new responsibilities, is she going to try something, anything at all, or freeze in fear because of the possible consequences? Does she think about the issue at all between 6pm and 9am? Is she going to repeat the same mistakes twice? Does she think everything is fine when everything is not fine?

But being a fast learner is a skill that is hard to demonstrate. You can demonstrate great skill with a programming language by single-handedly writing an open source program, you can demonstrate great leadership or management skills by successfully leading several teams and managing several projects, and you can demonstrate great artistic skills with a well-stocked portfolio, because these skills work on the basis of «if you did it ten times, you can do it eleven times»

By definition, you cannot learn the same thing ten times in a row, and saying that you will learn how to manage a team in two weeks because you learned how to code in PHP in two weeks is a bit of a stretch. It’s very hard to determine in a single job interview how fast someone can learn about new subjects. Once you hire someone and get the chance to work with them for a short while, though, you should be able determine this.

Otherwise, there’s no telling where that person will be a few months from now. And that would be bad management.

Information Flow

The real world is a complex place. When writing software that has to interact with the real world, there are literally thousands of concepts you have to master and tens of thousands of details you have to be aware of, or you will paint yourself into a corner where your software clashes with reality. And reality always wins.

Understanding concepts and details is a fundamental part of a project’s time budget, whether they come from the project requirements, real-world constraints, third party code or teammates. Every time information goes around in a project, it uses up valuable time, and to keep the time budget tight it becomes necessary to decide what information should be allowed to go around, and where.

Working on concurrent systems is an enlightening experience, because of the many similarities between an array of computers and a team of information workers. Computers arrays have latency issues when one thread depends on another thread to be done…

“When do you think your settings import module will be done? I’m stuck on the payment API until I can load those settings!„

…they have bandwidth issues and manipulating some data yourself is usually faster than sending the data to another part of the cluster for treatment…

“The User object? Well, it’s a bit of a weird design, but it’s rather clever. I’ll draw you a quick UML sketch on the blackboard so you can see what the five helper classes do.„

…they have to avoid data loss if a computer or network is down…

“I have no idea how this stored procedure works, you should ask Tim, he’s the one who wrote it. He’s in southern France right now but I think he’ll be back next month.„

… and they have to handle a directory of parts and a garbage collector for data…

“Wait, nobody’s written the comment moderation back-office! Who was in charge of doing it? Who wrote the comments front-end anyway?„

There are algorithms, strategies and techniques for handling and optimizing those things. Many of these can be adapted to humans, with the added benefit that, humans being smart, they can understand the point of those algorithms and compensate for minor flaws if the plan isn’t perfect.

HADOPI

The HADOPI law was recently adopted by the French parliament. I have an issue with this law: it deals with technical things that few people are knowledgeable in (including most members of parliament) such as the Internet Protocol and the use of IP addresses.

So, I have made a small effort on this website to explain the basic technical principles underlying the HADOPI law [fr].

Inline Help

Your average user does not know what a trackback is. Yet, WordPress must let experienced users ping trackbacks. How to include trackback information without scaring away the inexperienced users (and possibly even educating them along the way)?

The solution chosen by WordPress is to use slightly more verbosity to describe what trackbacks are:

wordpress-back

By contrast, Magento involves a lot more knowledge than just publishing a blog. While it’s possible to assume that Magento users earn their wages by knowing how to use it, most of the time they only manipulate the system as a side-effect of handling sales in their brick-and-mortar company, or they are new to sales altogether. So, the result is a complex product with outright terse field descriptions that have very complex effects:

magento-backWho, among normal Magento users, knows what a meta keyword or meta description is? Or whether meta keywords are as useful now as they were in the good old days? But that’s not very important, since you could just ignore those fields.

What’s an URL key? Now, even an experienced web developer might have trouble with this one (it’s the equivalent of a WordPress slug, except WordPress displays that “URL key” field as a more easily understood “Permalink: http://www.nicollet.net/2009/05/inline-help/” with the last URL segment editable).

What about the Page Title? What’s the difference between the category name and the page title? Which is displayed where?

Things get even more complex with other areas of Magento. For instance, in a lot of places a given field is disabled and a “Use Config Defaults” checkbox next to it is checked. The problem is that there is no indication about where those configuration defaults can be changed.

Last but not least, there are several classic questions to be asked, such as “Why does this product appear as out-of-stock?” or “Why doesn’t this product appear in this category?” or “How do I set a table rate?” which require careful analysis of the dozen options that might affect the actual state of the item (enabled? present in website? present in category? stock greater that zero? set as in-stock? children items enabled, present in website and set as in-stock? …)

Inline help items

Modern Javascript libraries allow altering an existing page in a non-intrusive manner by decorating the page elements once they are loaded (or when the user asks for help). This means it’s possible to add novice-specific inline help as:

  • Short text snippets under complex or technical items to explain what they are, possibly with a link to the complete explanation.
  • Explanatory tooltips on hovering.
  • See-also links (where do I change this configuration default? where do I set table rates?) placed exactly where the user might be wondering something.
  • Move-along tutorials that detect whether data was entered in certain fields and guide the user to create items, add them to categories, and so on…
  • Troubleshooting checklists (with links) to determine why a product does not appear, or why it appears out of stock.

In fact, it would even be possible for IT companies to provide their customers with customized help messages that match their specific internal processes.

JITBrain

Some of you may have wondered, what is this secret project he is working on?

The project is called JITBrain. In itself, it’s nothing quite groundbreaking, merely an issue tracking platform that services two categories of users:

  • Individuals that have a lot to do but never seem to manage it. These are helped by features such as extremely simple todo-list manipulation, a search engine for looking at previous tasks and retrieving important information, and helpful statistics.
  • Teams that must collaborate on projects. These are helped by features such as issue tracking, simple workflows, attached links and files, planning poker, reporting charts, and motivational gizmos.

The unusual thing about the project is the development method: it builds upon my earlier ramblings on snippet-oriented development (developing quality software by actively thinking of the people who will read and reuse the code) to actually become an advanced tutorial in itself. This brings yet another benefit, since the code is not only designed in short bursts of concisely explained functionality, but a complete documentation and log is being written along with it.

As such, it has the additional purpose of serving as a simple reference for “classic mistakes” both in technical and functional areas in the development of a website.

The tutorial advances along with the development of the system, which means you can see the tutorial or look at the website.

The C++ hits you! You feel confused.

If you’re reading this post, you’re probably either a beginner intending to learn C++, a veteran keen on flaming my teaching philosophy, or someone searching for the origin of the “The foobar hits you! You feel confused.” Nethack quote. Either way, welcome.

I intended this article as a short introductory meta-note about learning C++. It should give you some elements that can be helpful in understanding C++ books and tutorials. If you’re really keen on doing this, I suggest Thinking in C++ and the C++ FAQ Lite, both of which are freely available online and are quality resources.

And stay away from any tutorials that #include <iostream.h> !

Continue reading ‘The C++ hits you! You feel confused.’

Published Articles

I have recently contributed two articles to two game development books.

These are:

Both are in the gamedev.net collection.

Beginning OCaml, Part 1

Perhaps you’ve never programmed. Or perhaps you know of other languages, and wish to learn others—this post will discuss only pure functional programming, so I suggest you forget everything you know and start anew. Either way, this series of articles provides a quick introduction to the functional side of Objective Caml.

Expressions

The vast majority of code you will write in Objective Caml will be expressions. An expression is usually a mathematical formula or something close to one. The simplest expression is a constant, such as:

1

This is not a very useful expression. A slightly more useful example would be using Objective Caml as a pocket calculator, with expressions like:

(2 + 4) * 3

Objective Caml runs expressions by computing their value: this is known as evaluation. The above expression would result in the integer value 18. As we discover more elements of the language, the rules for evaluation will become more complex, but the fundamental principle remains almost intact: an Objective Caml program is an expression or series of expressions, running the program means evaluating those expressions.

Variables

The first step in raising Objective Caml above the lowly pocket calculator level is the ability to give names to objects.  The language construct for doing so is borrowed from mathematics, where mathematicians would say “let x be the smallest integer such that …” and refer to that integer as “x” from then on. The syntax for doing so is:

let (variable) = (expression) ;;

Use the semicolons for now—we will see later on that they are optional in some circumstances. Example of such a definition:

let x = (2 + 4) * 3 ;;
x - 2

This will evaluate the expression (which yields the value 18) then bind that value to the name x. Every expression below the definition of x will know that x equals 18, so the second expression would evaluate to 16. Here, x is called a variable—a confusing name, since it does not actually vary: once it’s defined, it stays forever. Any name can be used for a variable, as long as it starts with a lowercase letter and contains only letters, numbers and underscores.

It is of course possible to define more than one variable in a program:

let x = 3 + 4 ;;
let y = 2 * 5 ;;
x + y

This example evaluates to 17. A normal Objective Caml program defines hundreds and even thousands of variables in order to work.

Having a thousand variables creates a risk for collision. The good news is that collisions are handled smoothly: at any point in the program only the last definition found so far counts. So, if we were to consider an example:

let x = 3 ;;
let x = x + 1 ;;
x + x

Line 1 defines x as 3, line 2 defines x again, this time as 3 + 1 = 4, and line three evaluates to 4 + 4 = 8.

This doesn’t solve the problem entirely, though: what if I accidentally overwrite a previously defined value, and I need that value later on?

Local Definitions

Objective Caml solves this by providing local definitions: instead of making a variable available to all lines that appear below it, the variable is only available within an expression. The syntax is:

let (variable) = (expression) in (expression)

The variable exists only within the second expression, and uses the value of the first expression. For instance:

let x = 1 ;;
let y =
  let x = 2 in
  x + x ;;
x + y

This example defines x as 1. Then, within the definition of y, it defines x again as 2, which makes the value of y equal to 2 + 2 = 4. However, the second definition of x is only available within the “x + x” expression, so the “x + y” expression uses the original value, and the result is “1 + 4 = 5″.

Local definitions are expressions. This means that they can be used as part of other expressions, such as on either side of a mathematical operator, or within other definitions. It’s perfectly legal to write code like:

1 + (let x = 1 + 2 in x * 2)

This evaluates to 1 + (3 * 2) = 7.

In practice, most variables are defined locally, and only the most important variables are defined globally.

Functions

While useful, the above features still don’t get very far beyond basic calculation needs. The one feature that turns Objective Caml into a highly expressive tool is functions. A function follows the mathematical tradition of being a mapping: it associates every element of a set with an element from another set. The element from the first set is the argument, and the element from the other set is the return value.

To call a function, you provide it with an argument and it is automatically turned into its return value for that argument. For example, the function “string_of_int” returns a bit of text representing an integer, so you could use it like so:

string_of_int 10

This would evaluate to the text “10″.

How do we define functions? Well, we simply write an expression which uses the argument and evaluates to the return value. Of course, the function doesn’t know the value of its argument until it’s called. So, when we write the function’s code code, we use a placeholder name to represent the argument: this variable is called the parameter, and it is replaced with the argument itself when the function is called. The syntax is:

fun (parameter) -> (expression)

For instance, a function that adds two to a number can be defined as:

fun x -> x + 2

It is not very useful as such, so let’s give it a name and call it:

let add = fun x -> x + 2 ;;
add 3 * add 4

This evaluates to 5 * 6 = 30, and illustrates the main point of functions: they allow you to describe an operation once, and use it in many places simply by using the function’s name.

The Objective Caml language provides two shortcuts for defining functions. The first was designed to write functions that returns functions. Suppose that I write:

fun x -> (fun y -> x + y)

This can be elegantly shortened to:

fun x y -> x + y

The second shortcut was designed to make the definition of named functions easier. Suppose that I write:

let add = fun x -> x + 2

This can be elegantly shortened to:

let add x = x + 2

The two shortcuts can be combined, so that:

let add x y = x + y

Means the same as:

let add = fun x -> (fun y -> x+y)

You can see all the above (along with the general structure of the tutorial) on this page.

Heaps of Knowledge

A question I like to ask for evaluating programming skill is, “Implement Heap Sort” (in whatever language I need programming in).

Heap sort looks something like this (the example is in C++, but the implementation is fairly similar in just about any imperative language):

void swap(int &a, int &b) {
  int c = a;
  a = b;
  b = c;
}

void sift(int *data, int i, int size) {
  int l = i * 2 + 1, r = l + 1;
  int argmax = i;
  if (l < size && data[argmax] < data[l]) argmax = l;
  if (r < size && data[argmax] < data[r]) argmax = r;
  if (argmax != i) {
    swap(data[i], data[argmax]);
    sift(data, argmax, size);
  }
}

void heapsort(int *data, int size) {
  for (int i = (size-1)/2; i >= 0; --i) sift(data,i,size);
  for (int i = size; i >= 2; --i) {
    swap(data[i-1],data[0]);
    sift(data,0,i-1);
  }
}

This short version requires some experience to get right, as well as knowledge of the algorithm. I suspect that a large number of programmers have never heard of heap sort, and of those who have heard of it, few will know how to implement it on their own. Of course, if you ask someone who knows how to write, you will usually get a pleasant surprise. But most of the time, you’ll be facing someone who just doesn’t know the answer. That’s the entire point: what people know is important, but it’s far more important to know how people will react when they don’t know (and especially, how quickly they can learn).

If the programmer doesn’t know what heap sort is, you can nudge him in the right direction by explaining how heap sort works. Basically, heap sort is an improvement over the naive selection sort: instead of simply extracting the maximum element from the unsorted area in the array, heap sort turns the unsorted area into a heap—a binary tree where the root is the maximum element of the tree and each sub-tree is also a heap—thereby making extraction of a maximum a Θ(log n) task instead of the usual Θ(n). The trick behind heap sort is that the unsorted area of the array can be seen as a heap, by deciding that every index in the array is a node in the tree, with the left child being at index (2n+1) and the right child being at index (2n+2).

From there, it’s fairly elementary to deduce that the algorithm should first turn the entire array into a heap, then remove the first element, restore the heap, and repeat the process until the heap is empty. The sift function itself should be guessed fairly easily by anyone with any experience in recursive functions (it is, after all, merely a question of constructing a large heap from two smaller heaps).

The benefits I see to the question are:

  • See how the interviewee or student handles a situation where he has no idea about how to answer a question. Do they stare without saying a word? Do they get angry at an impossible question? Or do they admit they don’t know, and try to gather more information?
  • Determine how much general Computer Science knowledge the candidate has. As you explain Heap Sort, do they already know what heaps and selection sort are? Do they have to ask what a binary tree is? Do they have to ask what an array or a sort is, or how to swap two values?
  • Detect positive laziness and knowledge of standard libraries. Does the candidate mention they’d use the standard library sort in production code? In C++, do they already know of std::make_heap or std::swap?
  • Test basic knowledge of recursion and iteration. Does the interviewee ‘get’ the principle of sifting on the first try? Are the bounds for the two for-loops correct? Can the interviewee evaluate the complexity of the function?
  • Test basic knowledge of the language idioms. Are the functions declared correctly? Are the control structures used correctly? Is the choice of a storage type appropriate for the array?

An Object Philosophy : The Tools

There comes a time in every programmer’s career when the question of Object-Oriented Programming crops up. Various sources attempt to explain Object-Oriented Programming, though subtle nuances exist that often make such definitions incompatible with each other. Even worse, every programmer usually builds over the years his own version of what OOP really is about, and severe clashes can happen as a consequence.

Wikipedia’s approach is a quite pragmatical one: it accepts the existence of multiple definitions, and merely attempts to explain those concepts that are shared by most. Some define the core of OOP as the ISP, LSP, OCP, DIP and SRP acronyms principles. Others take a build-your-own approach from a set of basic premises. It only seems fair that I could get my own stab at it as well.

Object-Oriented Programming is usually used to refer to two distinct yet related concepts:

  • A set of tools that can be used for design and for programming: classes, objects, messages, inheritance, code metrics, design patterns…
  • The ways in which that set of tools may be used to construct software that guarantees certain benefits, such as low-cost maintenance or reuse of existing code.

It is impossible, and foolish, to separate the two. Using classes, objects and the other tools without proper discipline or skill does not bring any of the benefits that are associated with OOP—even worse, programmers who come expecting proper OOP use of these tools will be surprised and will often have a lot to do to correct the situation. No single Object-Oriented concept is a magic bullet capable of working wonders on its own.

Today, I’ll discuss the tools. The next article in the series will deal with the mindset.

Object-Oriented tools are language-independent and implementation-independent. Most languages have their own ways of providing support for these tools, and they can sometimes even be used in those languages that don’t provide any kind of helpful support. Considering Object-Oriented Programming as “What happens in Language X” often leads to trying to replicate language X features in language Y, even though language Y also provides support for OOP in a different way. Besides, since programming languages seldom provide the entire OOP toolset out of the box, restricting oneself to a single language also reduces the horizon of potential tools.

Objects

One thing everyone manages to agree on is that Object-Oriented Programming is about objects—what objects are, or how they should be used, is already a matter of disagreement in certain places. My own take on objects is that you don’t need to know what they are, you merely need to know how to manipulate them. This means that an OOP object can be implemented as a Java object, an Objective Caml abstract type or a C structure, as long as it behaves like OOP objects should.

First, where do objects come from? Before you can manipulate them, you must create them. The easiest way of getting a brand new object in your program is to create it yourself from scratch. Writing the string “Hello” in your source code will automatically create a string object representing “Hello” when the program is run. Most programming languages provide means of creating certain categories of objects directly in the code: strings, integers, floating-point numbers, booleans, functions and classes are typical examples. Yes, functions and classes are, from an Object-Oriented Programming perspective, objects. Some programming languages also allow the creation of arbitrarily complex objects on-the-fly as a literal (the Objective part of Objective Caml allows this, for instance), but most languages only allow the creation of complex objects from classes. I’ll get back to this class business later.

Messages

The sole purpose of objects is to receive messages.A message is a one-shot two-way communication channel between a piece of code and an object. The code sends a request to the object, and the object sends a response to the code. What the response looks like is up to the object, two distinct objects may respond differently to the same request and even a single object may respond differently to the same request at two distinct points in time. Both the request and the response carry some data—this data is usually a set of objects. A request also has an identifier that helps determine what the request is about: a “getAccountBalance” identifier means that the request is about getting the balance of an account, while a “setDuration” means that the request is about changing the duration of something.

Not all objects can process all messages. For instance, one cannot expect a rubber duck to respond to a “getAccountBalance” message. So, not being able to process a message is a possibility to be considered—one of the main advantages of having language support for OOP is that statically typed languages can check at compile-time whether all messages are going to be processed successfully. But, again, more on that later.

At this point, most OOP manuals summon forth a class definition of some form and happily declare “this class describes sets of objects, its methods define messages that the object can receive”. I find that approach quite annoying, because it forevers equates in the minds of the readers object with instance of a class and message with class method—the consequence being that readers then find themselves at a loss when they encounter languages with class-less objects (such as Objective Caml) or class-independent implementations of Object-Oriented Programming (such as Service-Oriented Architectures).

Everything is an object

So, my example is going to be one simple piece of C pseudocode instead:

int squared(int x)
{
  return x * x;
}

printf("%dn", squared(10));

In C terms, this pseudocode defines a function that returns its squared argument, then outputs the square of 10 on the standard output.

In Object-Oriented terms, this creates a new object and gives it the name squared. It does so by using a “function literal” which creates a brand new object by specifying what the object does when it receives a “function call” message: in this situation, the behavior would be to extract an integer object from the request, send that integer a “multiply by yourself” message, then respond with the result. Our example then sends the “function call” message associated with the integer literal 10 to the squared object, then binds the response to another “function call” message sent to the printf object.

In other words, a plain old piece of C code without a single occurrence of the class keyword can be interpreted as an object-oriented program. This extends even further: any piece of imperative code can be interpreted as sending messages to objects. Going even further, even pure functional code without even a hint of imperative design can also be expressed as sending messages to objects: every function is an object that can process the “function call” message.

So, in languages without classes, you can usually find:

  • Primitive objects : integers, booleans, floating-point numbers and similar kinds of values are objects which are created from literals. They accept a wide range of messages which correspond to their operators (add, multiply, subtract, boolean-and, boolean-or, and so on).
  • Aggregate objects : C structures, OCaml record types, Javascript objects (ignoring the this keyword) that are a collection of sub-objects that can be accessed by name. They support “set value X” and “get value X” messages for every member X. They are created as literals by assigning the appropriate names with the appropriate initial values. They may or may not require preliminary definition of their type (for checking purposes in strongly typed languages) and extension of their contents by sending a “set value Y” message for an yet-undefined member Y.
  • Functions : these objects accept only one message (“call function”). They are created as a literal which describes how the data is extracted from the request, what operations are performed on it, and what data is sent back as part of the response.

Semantic shifting

If Object-Oriented Programming was all about looking at previously written programs and noticing how they are Object-Oriented, there wouldn’t really be much of a point to doing it. The good news is that OOP is not only about observing objects within existing code: it can also be used to introduce brand new behaviors into existing objects. This happens by performing a semantic shift of what a message and an object is: you decide that a certain construct you just invented is an object, and that another construct is a message.

Let’s look at our C pseudocode example again:

int squared(int x)
{
  return x * x;
}

This can be interpreted as creating a new object, “squared“, which can handle the “function call” message. But it could also be interpreted as defining a new message, “squared“, which can be sent to integers. After all, since this is all a matter of interpretation, both interpretations can be correct at the same time: as long as squared(10) is a one-shot two-way communication channel between some code and the integer 10, it’s a message.

This semantic shift can be applied in almost all situations: a function with at least one argument can be seen as both an object that accepts a “call function” message, and as a message that can be sent to one of its arguments (with the other arguments as its associated data). So, now, you can go around and extend any of the objects that the programming language provides you with by creating the appropriate functions.

Polymorphism

Back to our “squared” message. That message can certainly be applied to integers, but it’s equally valid to apply it to floating-point numbers. Besides, if we (by some miracle, or perhaps some feature of the language) managed to create a new kind of object which also supported multiplication by itself (such as a complex number) then the “squared” message could also be sent to that object. This is because that message merely requires that the object it’s applied to supports multiplication by itself and so it can be applied to any such object. This is called polymorphism: when a message can be sent to any object, regardless of its nature, as long as it supports a certain set of operations. This provides the benefit of avoiding code repetition: you only define your “squared” message once, and then you can apply it everywhere. In a theoretical, ideal object-oriented programming language (the part is played here by Smalltalk, a very nice OOP language), you would just write this line once:

squared := [:x | x * x ]

Interfaces

The problem is that languages don’t play nice with the concept of polymorphism. To determine whether a program behaves correctly at runtime, the language uses a type system. This type system allows expressing certain constraints over the values, and some rules to determine which constraints imply that the program works.

The C type system is a fairly crude one. Every value has a type, with types being mutually distinct. So, you have the type of all integers, and the type of all floating point numbers. And a function argument has only one type. So, our polymorphism example, applied to two types, becomes:

int squared(int x)
{
  return x * x;
}

float squared(float x)
{
  return x * x;
}

The problem, of course, is that there is no way in the C type system to express the constraint “supports multiplication by itself”. So, although the semantics of “multiply the argument by itself” are clear, the C compiler cannot understand that it’s safe to define one such function. For that matter, the Java, C++ and Objective Caml type systems won’t let us define such a function either. This is one of the reasons I chuckle when I hear Java advocates tout Java as a “pure object-oriented programming language”: despite all the effort poured into creating a clean object model, a lot of elementary Java operations (including multiplication) are not messages, and several elementary Java types (including integers) are not objects. If you’re looking for a pure OOP language (you don’t need one to do proper OOP, of course), I strongly suggest Smalltalk.

Back to the point: languages that support OOP actively, yet have a static type system, provide the notion of interface to help with type-checking. An interface is a set of constraints and requirements, stating what messages can be received by the object, what data has to be sent as part of the request, and what data will be returned as part of the response. So, one can express an interface with a “multiply by” message, and the define the “squared” function to work on all objects with that interface: the language will then see that the interface provides the “squared” function with all it needs (namely, the “multiply by” message) and consider the types to be correct.

In Java, the interface and function would look like this:

interface Multipliable
{
  // Accepts "multiplyBy" message
  Multipliable multiplyBy(Multipliable);
}

Multipliable squared(Multipliable x)
{
  // Send "multiplyBy" message
  return x.multiplyBy(x);
}

Of course, we had to use explicit message names here, because the multiplication operator in Java is not a message supported by the type system. On the other hand, Objective Caml is a tad smarter, because it can guess the interface based on the messages being sent:

let squared x =
  x # multiplyBy x

(* squared : (< multiplyBy : 'a -> 'b ; .. > as 'a) -> 'b *)

Another consequence of Objective Caml’s more expressive type system is that it allows retrieving the correct type. For instance, if you pass an integer into Java’s “squared” function, you would get back a Multipliable object, but you wouldn’t know if it was an integer or something else. This can be annoying, because you, as a programmer, know that it’s an integer, but the language won’t let you use it as such until you remind the compiler that it should trust you (and it will still check it at runtime). By contrast, Objective Caml types are parametric. An integer would probably have a “multiplyBy : integer -> integer” function, so the squared function would correctly return an integer.

But all of that is idle bickering about type systems that deviates from the purpose of the article.

Classes

A very important element of object-oriented programming is the notion of class. Earlier on, I said that objects could only be constructed at runtime by literals. That is, you create a new object and set its various properties right away. This, of course, makes it difficult to define categories of similar objects, because you have to define them one at a time and also make sure they share similar properties.

Another way of creating objects has been proposed in several programming languages, to the point of becoming (mistakenly) a synonym for OOP. A class is an object—even though some impure programming languages do not treat it as such—which defines a single message called a constructor. Upon receiving a constructor message, the class creates (by some arcane magic implemented by the compiler) a brand new object with a predetermined set of properties that are a combination of the data sent with the constructor message and the data provided when the class itself was created.

The exact syntax for sending the constructor message varies from language to language, but usually involves something along the lines of “new Classname(arguments)“.

In practice, a class defines two things:

  • The data to be carried by the object. This data is either created from scratch by the constructor, gathered from the global scope, or extracted from the constructor message itself.
  • The list of messages that the object can process, along with the code to perform said processing.

Again, the exact syntax for defining a class varies. In Objective Caml, the constructor message is described as part of the class name and used to initialize the values in the object, while the messages to be processed are called “methods”:

class vector2d (x,y) =
object
  val x = x
  val y = y
  method length = sqrt(x *. x +. y *. y)
end

let v = new vector2d (1.0,2.0) in
  v # length

[Edit : corrected small typo] In Java (as well as C++ and C#) the constructor is described as if it were a method, which can sometimes be confusing. Also, the language does not automatically guess which interfaces are implemented by a certain object, so they have to be specified as part of the class definition.

class Vector2d
{
  private float x;
  private float y;
  public Complex(float x, float t)
  {
    this.x = x;
    this.y = y;
  }
  public float Length()
  {
    return Math.sqrt(x * x + y * y);
  }
}

Vector2d v = new Vector2d(1.0,2.0);
v.Length();

In Javascript, classes are constructors, with methods being defined as part of that constructor’s prototype:

function vector2d(x,y)
{
  this.x = x;
  this.y = y;
}

vector2d.prototype.length = function()
{
  return Math.sqrt(this.x * this.x + this.y * this.y);
}

var v = new vector2d(1.0,2.0);
v.length();

Class extensions

In fact, classes support another message besides constructors: inheritance, or extension. When extending a class or inheriting from a class (two ways of expressing the same concept), one create creates a new class which imports all the contents of another class, then adds its own set of contents. Most type systems apply a subtype relationship to inheritance, meaning that a function which can operate on an instance of the original class can also operate on an instance of the inheriting class.

Inheritance is a strange beast: on the one hand, it behaves a little like interfaces (and is in fact the only way of replacing interfaces in languages that don’t have them, such as C++) to provide polymorphism but on the other hand it is a non-polymorphic way of extending the functionality of a class. It happens quite often that entire programs avoid using inheritance at all, because interfaces solve all their polymorphism needs and they do not need the extension features of inheritance.

A summary

Object-oriented programming introduces the following set of concepts:

  • An object is a value manipulated by the program. Integers, booleans, strings, functions and classes are examples of objects. Objects are usually created using literals provided by the programming language.
  • A program works by sending messages to objects. A message transmits a request (with arguments) to an object and the object responds with some data. Calling a function on an argument can be seen as sending a message, and calling a member function or method can also be interpreted as sending a message.
  • An interface, in a statically typed programming language, represents a set of messages that an object must be able to process. This is used to ensure that a function argument can be used without causing a runtime error.
  • A class is a special object which can receive constructor messages. Every constructor message constructs a brand new object that is returned as part of the response. Usually, an object created from a class is said to be an instance of that class.
  • Classes can inherit from one another, which can be useful in some cases to extend its functionality in a non-polymorphic manner.

The next article in the series is here (starting on January 9, 2009).



1170 feed subscribers
(readers who polled a feed this week)