15.1. Hitting a Nail with the Right Hammer

We need to be flexible and diverse programmers. The programming landscape requires elegance, efficiency, and longevity. Gone are the days of picking one language and platform and executing like crazy to meet the requirements of our problem domain. Different nails sometimes require different hammers.

Given that there are hundreds of available languages on the .NET platform, what makes them different from each other? Truth be told, most are small evolutions of each other, and are not particularly useful in an enterprise environment. However, it is easy to class these languages into a range of programming paradigms.

There are various ways to classify programming languages, but I like to take a broad-strokes approach, putting languages into four broad categories: imperative, declarative, dynamic, and functional. Let's take a quick look at these categories and what languages fit within them.

15.1.1. Imperative

Your classic all-rounder — imperative languages describe how, rather than what. Imperative languages were designed from the get-go to raise the level of abstraction of machine code. It's said that when Grace Hopper invented the first-ever compiler, the A-0 system, her machine code programming colleagues complained that she would put them out of a job.

It includes languages where language statements primarily manipulate program state. Object-oriented languages are classic state manipulators through their focus on creating and changing objects. The C and C++ languages fit nicely in the imperative bucket, as do our favorites Visual Basic.NET and C#.

They're great at describing real-world scenarios through the world of the type system and objects. They are strict — meaning the compiler does a lot of safety checking for you. Safety checking (or type soundness) means you can't easily change a Cow type to a Sheep type — so, for example, if you declare that you need a Cow type in the signature of your method, the compiler will make sure that you don't hand that method a Sheep instead. They usually have fantastic reuse mechanisms too — code written with polymorphism in mind can easily be abstracted away so that other code paths, from within the same module through to entirely different projects, can leverage the code that was written. They also benefit from being the most popular. So they're clearly a good choice if you need a team of people working on a problem.

15.1.2. Declarative

Declarative languages describe what, rather than how (in contrast to imperative, which describes the how through program statements that manipulate state). Your classic well-known declarative language is HTML. It describes the layout of a page: what font, text, and decoration are required, and where images should be shown. Parts of another classic, SQL, are declarative — it describes what it wants from a relational database. A recent example of a declarative language is XAML (eXtensible Application Markup Language), which leads a long list of XML-based declarative languages.

Declarative languages are great for describing and transforming data. And as such, we've invoked them from our imperative languages to retrieve and manipulate data for years.

15.1.3. Dynamic

The dynamic category includes all languages that exhibit "dynamic" features like late-bound binding and invocation (you learn about these in a couple of paragraphs or so), REPL (Read Eval Print Loops), duck typing (non-strict typing, that is, if an object looks like a duck and walks like a duck it must be a duck), and more.

Dynamic languages typically delay as much compilation behavior as they possibly can to runtime. Whereas your typical C# method invocation "Console.WriteLine()" would be statically checked and linked to at compile time, a dynamic language would delay all this to runtime. Instead, it will look up the "WriteLine()" method on the "Console" type while the program is actually running, and if it finds it, will invoke it at runtime. If it does not find the method or the type, the language may expose features for the programmer to hook up a "failure method," so that the programmer can catch these failures and programmatically "try something else."

Other features include extending objects, classes, and interfaces at runtime (meaning modifying the type system on the fly); dynamic scoping (for example, a variable defined in the global scope can be accessed by private or nested methods); and more.

Compilation methods like this have interesting side effects. If your types don't need to be fully defined up front (because the type system is so flexible), you can write code that will consume strict interfaces (like COM, or other .NET assemblies, for example) and make that code highly resilient to failure and versioning of that interface. In the C# world, if an interface you're consuming from an external assembly changes, you typically need a recompile (and a fix-up of your internal code) to get it up and running again. From a dynamic language, you could hook the "method missing" mechanism of the language, and when a particular interface has changed simply do some "reflective" lookup on that interface and decide if you can invoke anything else. This means you can write fantastic glue code that glues together interfaces that may not be versioned dependently.

Dynamic languages are great at rapid prototyping. Not having to define your types up front (something you would do straightaway in C#) allows you concentrate on code to solve problems, rather than on the type constraints on the implementation. The REPL (Read Eval Print Loop) allows you to write prototypes line-by-line and immediately see the changes reflect in the program instead of wasting time doing a compile-run-debug cycle.

If you're interested in taking a look at dynamic languages on the .NET platform, you're in luck. Microsoft has released IronPython (www.codeplex.com/IronPython), which is a Python implementation for the .NET Framework. The Python language is a classic example of a dynamic language, and is wildly popular in the scientific computing, systems administration, and general programming space. If Python doesn't tickle your fancy, you can also download and try out IronRuby (www.ironruby.net/), which is an implementation of the Ruby language for the .NET Framework. Ruby is a dynamic language that's popular in the web space, and though it's still relatively young, it has a huge popular following.

15.1.4. Functional

The functional category focuses on languages that treat computation like mathematical functions. They try really hard to avoid state manipulation, instead concentrating on the result of functions as the building blocks for solving problems. If you've done any calculus before, the theory behind functional programming might look familiar.

Because functional programming typically doesn't manipulate state, the surface area of side effects generated in a program is much smaller. This means this is fantastic for implementing parallel and concurrent algorithms. The holy grail of highly concurrent systems is the avoidance of overlapping "unintended" state manipulation. Dead-locks, race conditions, and broken invariants are classic manifestations of not synchronizing your state manipulation code. Concurrent programming and synchronization through threads, shared memory, and locks is incredibly hard, so why not avoid it altogether? Because functional programming encourages the programmer to write stateless algorithms, the compiler can then reason about automatic parallelism of the code. And this means you can exploit the power of multi-core processors without the heavy lifting of managing threads, locks, and shared memory.

Functional programs are terse. There's usually less code required to arrive at a solution than with its imperative cousin. Less code typically means fewer bugs and less surface area to test.

15.1.5. What's It All Mean?

These categories are broad by design: languages may include features that are common to one or more of these categories. The categories should be used as a way to relate the language features that exist in them to the particular problems that they are good at solving.

Languages like C# and VB.NET are now leveraging features from their dynamic and functional counterparts. Linq (Language Integrated Query) is a great example of a borrowed paradigm. Consider the following C# 3.0 Linq query:

var query =   from c in customers
              where c.CompanyName == "Microsoft"
              select new { c.ID, c.CompanyName };

There are a few borrowed features here. The "var" keyword says "inference the type of the query specified," which looks a lot like something out of a dynamic language. The actual query itself "from c in ..." looks and acts like the declarative language SQL, and the "select new { c.ID ..." creates a new anonymous type, again something that looks fairly dynamic. The code-generated results of these statements are particularly interesting: they're actually not compiled into classic IL (intermediate language); they're instead compiled into what's called an expression tree and then interpreted at runtime — something that's taken right out of the dynamic language playbook.

The truth is, these categories don't particularly matter too much for deciding which tool to use to solve the right problem. Cross-pollination of feature sets from each category into languages is in fashion at the moment, which is good for a programmer, whose favorite language typically picks up the best features from each category.

And if you're a .NET programmer, you've got more to smile about. Language interoperation through the CLS (Common Language Specification) works seamlessly, meaning you can use your favorite imperative language for the majority of the problems you're trying to solve, then call into a functional language for your data manipulation, or maybe some hard-core math you need to solve a problem.

So now that we've learned a little bit about the various categories and paradigms of languages and their features, let's explore one of the newest members to the Microsoft Developer Division, a functional language called F#.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.253.223