Dis­claimer: I do not claim credit for the code exam­ples and much of the con­tents here, these are mostly extracts from the book by Chris Smith, Pro­gram­ming F#: A com­pre­hen­sive guide for writ­ing sim­ple code to solve com­plex prob­lems. In fact, if you’re think­ing of learn­ing F# and like what you read here, you should buy the book your­self, it’s easy to read and the author has gone go great lengths to keep things sim­ple and included a lot of code exam­ples for you to try out yourself.

Tuple

A tuple (pro­nounced “two-pull”) is an ordered col­lec­tion of data, and an easy way to group com­mon pieces of data together.

A tuple type is described by a list of the tuple’s ele­ments’ types, sep­a­rated by asterisks:

clip_image001

You can even have tuples that con­tain other tuples:

clip_image002

There’s a num­ber of ways to extract val­ues from a tuple, there’s fst (first) and snd (sec­ond) func­tions if you have a two-elements tuple:

clip_image003

And then there’s the let binding:

clip_image004

But remem­ber, you’ll get a com­pile error if you try to extract too many or too few val­ues from a tuple.

It is pos­si­ble to pass tuples as para­me­ters to functions:

clip_image005

Lists

Whereas tuples group val­ues into a sin­gle entity, lists allow you to link data together to form a chain. Doing so allows you to process list ele­ments in bulk using aggre­gate operators.

You can declare a list like this:

clip_image006

Notice in the snip­pet above the empty list had type ‘a list because it could be of any type, there­fore it’s generic.

Unlike other lan­guages, F# lists are quite restric­tive in how you access and manip­u­late them — there are only two oper­a­tions you can per­form with a list:

  1. The first is cons, rep­re­sented by the :: or cons oper­a­tor. This joins an ele­ment to the front or head of a list:

clip_image007

  1. The sec­ond is append, uses the @ oper­a­tor. Append joins two lists together:

clip_image008

List ranges

Declar­ing list ele­ments as a semicolon-delimited list quickly becomes tedious, espe­cially for large lists. To declare a list of ordered numeric val­ues, use the list range syntax:

clip_image009

If an optional step value is pro­vided, then the result is a list of val­ues in the range between two num­bers sep­a­rated by the step­ping value:

clip_image010

List com­pre­hen­sions

List com­pre­hen­sions is a rich syn­tax that allows you to gen­er­ate lists inline with F# code. The body of the list com­pre­hen­sion will be exe­cuted until it ter­mi­nates, and the list will be made up of ele­ments returned via the yield keyword:

clip_image011

Almost any F# code can exist inside of list com­pre­hen­sions, includ­ing things like func­tion dec­la­ra­tions and for loops:

clip_image012

When using loops within list com­pre­hen­sions, you can sim­ply the code by using -> instead of do yield:

clip_image013

Here’s a more com­plex exam­ple show­ing how you can use list com­pre­hen­sion to eas­ily find prime numbers:

clip_image014

List mod­ule functions

The F# library’s List mod­ule con­tains many meth­ods to help you process lists:

image

The fol­low­ing exam­ple demon­strates the List.partition func­tion, par­ti­tion­ing a list of num­bers from 1 to 15 into two new lists: one com­prised of mul­ti­ples of five and the other list made up of every­thing else:

clip_image015

The trick is that List.partition returns a tuple.

Aggre­gate Operators

Although lists offer a way to chain together pieces of data, there really isn’t any­thing spe­cial about them. The true power of lists lies in aggre­gate oper­a­tors, which are a set of power func­tions that are use­ful for any col­lec­tion of values..

List.map

List.map is a pro­jec­tion oper­a­tion that cre­ates a new list based on a pro­vided func­tion. Each ele­ment in the new list is the result of eval­u­at­ing the func­tion, it has type (‘a -> ‘b) -> ‘a list -> ‘b list

The fol­low­ing exam­ple shows the result of map­ping a square func­tion to a list of integers:

clip_image016

List.map is one of the most use­ful func­tions in the F# lan­guage, it pro­vides an ele­gant way for you to trans­form data.

List.fold

Folds rep­re­sent the most pow­er­ful type of aggre­gate oper­a­tor and not sur­pris­ingly the most com­pli­cated. When you have a list of val­ues and you want to dis­til it down to a sin­gle piece of data, you use a fold.

There are two main types of folds you can use on lists, first is List.reduce which has type (‘a -> ‘a -> ‘a) -> ‘a list -> ‘a

List.reduce iter­ates through each ele­ment of a list, build­ing up an accu­mu­la­tor value, which is the sum­mary of the pro­cess­ing done on the list so far. Once every list item has been processed, the final accu­mu­la­tor value is returned, the accumulator’s ini­tial value in List.reduce is the first ele­ment of the list.

This exam­ple demon­strates how to use List.reduce to comma-separate a list of strings:

clip_image001[7]

Whilst use­ful, reduce fold forces the type of the accu­mu­la­tor to have the same type as the list. If you want to use a cus­tom accu­mu­la­tor type (e.g. reduc­ing a list of items in a shop­ping cart to a cash value), you can use List.fold.

The fold func­tion takes three parameters:

  1. A func­tion that when pro­vided an accu­mu­la­tor and list ele­ment returns a new accumulator.
  2. An ini­tial accu­mu­la­tor value.
  3. The list to fold over.

The return value of the func­tion is the final state of the accu­mu­la­tor. The type of the fold func­tion is:

(‘acc -> ‘b -> ‘acc) -> ‘acc -> ‘b list -> ‘acc

Here’s an exam­ple of how you can use it to count the num­ber of vow­els in a string:

clip_image002[7]

Fold­ing right-to-left

List.reduce and List.fold process the list in a left-to-right order. There are alter­na­tive func­tions List.reduceBack and List.foldBack for pro­cess­ing lists in right-to-left order.

Depends on what you are try­ing to do, pro­cess­ing a list in reverse order can have a sub­stan­tial impact on per­for­mance.

List.iter

The final aggre­gate oper­a­tor, List.iter, iter­ates through each ele­ment of the list and calls a func­tion that you pass as a para­me­ter, it has type (‘a -> unit) -> ‘a list -> unit

Because List.iter returns unit, it is pre­dom­i­nately used for eval­u­at­ing the side effect of the given method, mean­ing that exe­cut­ing the func­tion has some side effect other than its return value (e.g. printfn has the side effect of print­ing to the con­sole in addi­tion to return­ing unit):

clip_image001[9]

Option

If you want to rep­re­sent a value that may or may not exist, the best way to do so is to use the option type. The option type has only two pos­si­ble val­ues: Some(‘a’) and None.

A typ­i­cal sit­u­a­tion you’ll use an option type is when you want to parse a string as an int and if the string is prop­erly for­mat­ted you’ll get an int, but if the string is not prop­erly for­mat­ted you’ll get None:

clip_image002[9]

A com­mon idiom in C# is to use null to mean the absence of a value. How­ever, null is also used to indi­cate an unini­tial­ized value, this dual­ity can lead to con­fu­sion and bugs. If you use the option type, there is no ques­tion what the value rep­re­sents, sim­i­lar to how System.Nullable works in C#.

To retrieve the value of an option, you can use Option.get.

clip_image003[7]

One thing to watch out though, is that if you call Option.get on None, an excep­tion will be thrown. To get around this, you can use Option.isSome or Option.isNone to check before the value of the option type before attempt­ing to access it, sim­i­lar to System.Nullable.HasValue in C#.

Printfn

printfn comes in three main flavours: printf, printfn, and sprintf.

printf takes the input and writes it to the screen, whereas printfn writes it to the screen and adds a line continuation.

pin­rtf has for­mat­ting and check­ing built-in (e.g. printfn “%s is %d%c high” moun­tain height units), it’s also strong typed and uses F#‘s type infer­ence sys­tem so the com­piler will give you an error if the data doesn’t match the given for­mat specifier.

Here’s a table of printf for­mat specifiers:

image

sprintf is used when you want the result of the print­ing as a string:

clip_image001[11]

Anatomy of an F# Program

Most other lan­guages, like C#, require an explicit pro­gram entry point, often called a main method. In F#, for single-file appli­ca­tions, the con­tents of the code file are exe­cute from top to bot­tom in order with­out the need for declar­ing a spe­cific main method.

For multi-file projects, how­ever, code needs to be divided into orga­ni­za­tion units called mod­ules or name­spaces.

Mod­ules

By default, F# puts all your code into an anony­mous mod­ule with the same name as the code file with the first let­ter cap­i­tal­ized. So if you have a value named value1, and your code is in file1.fs, you can refer to it by using the fully qual­i­fied path: File1.value1.

You can explic­itly name your code’s mod­ule by using the mod­ule key­word at the top of a code file:

clip_image001[13]

Files can con­tain nested mod­ules as well. To declare a nested mod­ule, use the mod­ule key­word fol­lowed by the name of your mod­ule and an equals sign =. Nested mod­ules must be indented to be dis­am­biguated from the “top-level” module:

clip_image002[11]

Name­spaces

The alter­na­tive to mod­ules is name­spaces. Name­spaces are a unit of orga­niz­ing code just like mod­ules with the only dif­fer­ence being that name­spaces can­not obtain value, only type dec­la­ra­tions.

Also, name­spaces can­not be nested in the same way that mod­ules can, instead, you can add mul­ti­ple name­spaces to the same file:

clip_image001[15]

It may seem strange to have both name­spaces and mod­ules in F#. Mod­ules are opti­mized for rapid pro­to­typ­ing and quickly explor­ing a solu­tion, as you have seen so far. Name­spaces, on the other hand, are geared toward larger-scale projects with an object-oriented solution.

Pro­gram Startup

For sin­gle file projects, the code will be exe­cuted from top to bot­tom, how­ever, when a you add a new file to the project, the newly added file will be run when the pro­gram starts up.

For more for­mal program-startup seman­tics, you can use the [<Entry­Point>] attribute to define a main method. To qual­ify, your method must:

  • Be the last func­tion defined in the last com­piled file in your project.
  • Take a sin­gle para­me­ter of type string array, which are the argu­ments to your program.
  • Return an inte­ger, which is your program’s exit code.
Share

Dis­claimer: I do not claim credit for the code exam­ples and much of the con­tents here, these are mostly extracts from the book by Chris Smith, Pro­gram­ming F#: A com­pre­hen­sive guide for writ­ing sim­ple code to solve com­plex prob­lems. In fact, if you’re think­ing of learn­ing F# and like what you read here, you should buy the book your­self, it’s easy to read and the author has gone go great lengths to keep things sim­ple and included a lot of code exam­ples for you to try out yourself.

Func­tions

You define func­tions the same way you define val­ues, except every­thing after the name of the func­tion servers as the function’s para­me­ters. The fol­low­ing defines a func­tion called square that takes an inte­ger, x, and returns its square:

clip_image001

Unlike C#, F# has no return key­word. The last expres­sion to be eval­u­ated in the func­tion deter­mines the return type.

Also, from the FSI out­put above, it shows the func­tion square has sig­na­ture int -> int, which reads as “a func­tion tak­ing an inte­ger and return­ing an integer”.

Type Infer­ence

Take this add func­tion for example:

clip_image002

Look­ing at this you might be won­der­ing why does the com­piler think that the add func­tion only takes inte­gers? The + oper­a­tor also works on floats too!

The rea­son is type infer­ence. Unlike C#, F# doesn’t require you to explic­itly state the types of all the para­me­ters to a func­tion, it fig­ures it out based on usage. Because the + oper­a­tor works for many dif­fer­ent types such as byte, int, and dec­i­mal, the com­piler sim­ply defaults to int if there is no addi­tional infor­ma­tion.

The fol­low­ing FSI snip­pet shows what type infer­ence in action if we not only define the add func­tion but also call it pass­ing in floats, then the function’s sig­na­ture will be inferred to be of type float -> float -> float instead:

clip_image003

How­ever, you can pro­vide a type anno­ta­tion, or hint, to the F# com­piler about what the types are. To do this, sim­ply replace a func­tion para­me­ter with the fol­low­ing form ident -> (ident: type) like this:

clip_image004

This works because the only over­load for + that takes a float as its first para­me­ter is float -> float -> float, so the F# com­piler infers y to be a float as well.

Type infer­ence can reduce code clut­ter by hav­ing the com­piler fig­ure out what types to use, but the occa­sional type anno­ta­tion is required and can some­times improve code readability.

Generic Func­tions

You can write func­tions that work for any type of a para­me­ter, such as an iden­tity func­tion below:

clip_image005

Because the type infer­ence sys­tem could not deter­mine a fixed type for value x in the ident func­tion, it was generic. If a para­me­ter is generic, then that para­me­ter can be of any type.

The type of a generic para­me­ter can have the name of any valid iden­ti­fier pre­fixed with an apos­tro­phe, but typ­i­cally let­ters of the alpha­bet start­ing with ‘a’ as you can see from the FSI snip­pet for the ident func­tion above.

Writ­ing generic code is impor­tant for max­i­miz­ing code reuse.

Scope

Every value declared in F# has a spe­cific scope, more for­mally referred to as a dec­la­ra­tion space.

The default scope is mod­ule scope, mean­ing vari­ables can be used any­where after their dec­la­ra­tion. How­ever, val­ues defined within a func­tion are scoped only to that function.

For exam­ple:

clip_image006

The scop­ing of a vari­able is impor­tant because F# sup­ports nested func­tions — i.e. you can declare new func­tion val­ues within the body of a func­tion. Nested func­tions have access to any value declared in a higher scope as well as any new val­ues declared within itself. The fol­low­ing exam­ples shows this in action:

clip_image007

In F#, hav­ing two val­ues with the same name doesn’t lead to a com­piler error; rather it sim­ply leads to shad­ow­ing. When this hap­pens, both val­ues exists in mem­ory, except there is no way to access the pre­vi­ously declared value. For example:

clip_image008

This tech­nique of inten­tion­ally shad­ow­ing val­ues is use­ful for giv­ing the illu­sion of updat­ing val­ues with­out rely­ing on muta­tion. Think strings in C#, which is an immutable type that allows reas­sign­ment using the same shad­ow­ing technique.

Con­trol Flow

You can branch con­trol flow using the if key­word which works exactly like an if state­ment in C#:

clip_image001[6]

F# sup­ports if-then-else struc­ture, but the thing the sets if state­ments in F# apart is that if expres­sions return a value:

clip_image002[7]

F# has some syn­tac­tic sugar to help you com­bat deeply nested if expres­sion with the elif keyword:

clip_image003[6]

Because the result of the if expres­sion is a value, every clause of an if expres­sion must return the same type.

But if you only have a sin­gle if and no cor­re­spond­ing else, then the clause must return unit, which is a spe­cial type in F# that means essen­tially “no value”.

Core Types

Besides the prim­i­tive types, the F# library includes sev­eral core types that will allow you to orga­nize, manip­u­late and process data:

image

Unit

The unit type is a value sig­ni­fy­ing noth­ing of con­se­quence. unit can be thought of as a con­crete rep­re­sen­ta­tion of void and is rep­re­sented in code via ():

clip_image001[8]

if expres­sions with­out a match­ing else must return unit because if they did return a value, what would hap­pen if else was hit?

Also, in F#, every func­tion must return a value, think method in C# and the void return type, so even if the func­tion doesn’t con­cep­tu­ally return any­thing then it should return a unit value.

The ignore func­tion can swal­low a function’s return value if you want to return unit:

clip_image002[9]

Share

Dis­claimer: I do not claim credit for the code exam­ples and much of the con­tents here, these are mostly extracts from the book by Chris Smith, Pro­gram­ming F#: A com­pre­hen­sive guide for writ­ing sim­ple code to solve com­plex prob­lems. In fact, if you’re think­ing of learn­ing F# and like what you read here, you should buy the book your­self, it’s easy to read and the author has gone go great lengths to keep things sim­ple and included a lot of code exam­ples for you to try out yourself.

Prim­i­tive Types

F# is sta­t­i­cally typed, mean­ing that type check­ing is done at com­pile time.

F# sup­ports the full set of prim­i­tive .Net types which are built into the F# lan­guage and sep­a­rate from user-defined types.

Here’s a table of all the numeric types (both inte­ger and floating-point) with their suffixes:

image

F# also allows you to spec­ify val­ues in hexa­dec­i­mal (base 16), octal (base 8 ) or binary (base 2) using pre­fix 0x, 0o, or 0b:

clip_image001

There are no implicit type con­ver­sion in F#, which elim­i­nates sub­tle bugs intro­duced by implicit type con­ver­sion as can be found in other languages.

Arith­metic Operators

You can use stan­dard arith­metic oper­a­tors on numeric prim­i­tives, like other CLR-based lan­guages, inte­ger divi­sion rounds down to the next low­est num­ber dis­card­ing the remain­der. Here’s a table of all sup­ported operators:

image

A very impor­tant to note here is that by default, these arith­metic oper­a­tors do not check for over­flow! If a num­ber becomes too big for its type it’ll over­flow to be neg­a­tive, and vice versa:

clip_image002

F# also fea­tures all the stan­dard math func­tions, here’s a table of the com­mon math functions:

image

Big­Int

If you are deal­ing with data larger than 2^64, F# has the Big­Int type for rep­re­sent­ing arbi­trar­ily large inte­gers. While the Big­Int type is sim­ply an alias for the System.Numerics.BigInteger type, it’s worth not­ing that nei­ther C# nor VB.Net has syn­tax to sup­port arbi­trar­ily large integers.

Big­Int uses the I suf­fix for lit­er­als, see exam­ple below:

clip_image003

You should remem­ber that although Big­Int is heav­ily opti­mized, it is still much slower than using the prim­i­tive inte­ger types.

Bit­wise Operations

Prim­i­tive inte­ger types sup­port bit­wise oper­a­tors for manip­u­lat­ing val­ues at a binary level:

image

Char­ac­ters

The .Net plat­form is based on Uni­code, so char­ac­ters are rep­re­sented using 2-byte UTF-16 char­ac­ters. To define a char­ac­ter value, you can put any Uni­code char­ac­ter in sin­gle quotes, for example:

clip_image004

Like C#, to rep­re­sent spe­cial con­trol char­ac­ters you need to use an escape sequence from the table below:

image

You can get the byte value of a char­ac­ter lit­eral by adding a B suffix:

clip_image005

Strings

String lit­er­als are defined by enclos­ing a series of char­ac­ters in dou­ble quotes which can span mul­ti­ple lines. To access a char­ac­ter from within a string, use the indexer syn­tax, .[ ], and pass in a zero-based char­ac­ter index. For example:

clip_image006

If you want to spec­ify a long string, you can break it up across mul­ti­ple lines using a sin­gle back­slash, \, for example:

clip_image007

Like in C#, you can define a ver­ba­tim string using the @ sym­bol, which ignores any escape sequence characters:

clip_image008

Boolean Val­ues

F# has the bool type (System.Boolean) as well as stan­dard Boolean oper­a­tors listed below:

image

F# uses short-circuit eval­u­a­tion when eval­u­at­ing Boolean expres­sions, mean­ing that if a result can be deter­mined after eval­u­at­ing the first of the two expres­sions, the sec­ond value won’t be eval­u­ated. For example:

true || f() - will eval­u­ate to true with­out exe­cut­ing func­tion f.

false && g() — will eval­u­ate to false with­out exe­cut­ing func­tion g.

Com­par­i­son and Equality

You can com­pare numeric val­ues using stan­dard oper­a­tors listed below:

image

All these oper­a­tors eval­u­ate to a Boolean value except the com­pare func­tion which returns –1, 0, or 1 depend­ing on whether the first para­me­ter is less than, equal to, or greater than the second.

You should have noticed that these oper­a­tors are sim­i­lar to those found in SQL Server and F# doesn’t dis­tin­guish assign­ment from equal­ity (like C#, where = is assign­ment and == is equal­ity comparison).

When it comes to equal­ity, as in other CLR-based lan­guages, it can mean dif­fer­ent things — value equal­ity or ref­er­en­tial equal­ity. For value types, equal­ity means the val­ues are iden­ti­cal. For ref­er­ence types, equal­ity is deter­mined by over­rid­ing the System.Object method Equals.

Share

I decided to take some time out on Sil­verlight and have a play around with Microsoft’s new lan­guage F#, I’ll be mak­ing notes as I go along and post them here so maybe they’d help sat­isfy some of your curios­ity too!

Dis­claimer: I do not claim credit for the code exam­ples and much of the con­tents here, these are mostly extracts from the book by Chris Smith, Pro­gram­ming F#: A com­pre­hen­sive guide for writ­ing sim­ple code to solve com­plex prob­lems. In fact, if you’re think­ing of learn­ing F# and like what you read here, you should buy the book your­self, it’s easy to read and the author has gone go great lengths to keep things sim­ple and included a lot of code exam­ples for you to try out yourself.

Before you start, you need to down­load F# from:

http://research.microsoft.com/en-us/um/cambridge/projects/fsharp/release.aspx

and install it for either VS2008 or VS2010 beta.

Hello, World

In VS2008, open a new project and choose F# Appli­ca­tion, in Program.fs type in:

printfn “Hello, World“

Hit Ctrl+F5, and voila:

You might notice that your pro­gram worked with­out an explicit Main method.

Here’s a slightly more com­plex Hello, World to show off the syn­tax of F#:

image

The let key­word binds a name to a value, unlike most other pro­gram­ming lan­guages, in F#, val­ues are immutable by default (mean­ing they can­not be changed once ini­tial­ized).

image

F# is also case-sensitive. The name of a vari­able can con­tain let­ters, num­bers, under­score, or apos­tro­phe (‘) and must begin with a let­ter or an under­score. How­ever, you can enclose the value’s name with a pair of tick­marks in which case the name can con­tain any char­ac­ter except for tabs and new­line:

let “this.Isn’t %A% good value Name$!#“ = DateTime.Now.ToString(“hh:mm tt”)

printfn “%s, %s at %s” greet­ing thing “this.Isn’t %A% good value Name$!#“

Other lan­guages like C# use semi­colons and curly braces to indi­cate when state­ments and blocks of code are com­plete, but it clut­ters the code.

In F#, white­space (spaces and new­lines) is sig­nif­i­cant. The F# com­piler allows you to use white­space to delimit code blocks. For exam­ple, any­thing indented more than the if key­word is con­sid­ered to be in the body of the if state­ment. Because tab char­ac­ters can indi­cate an unknown num­ber of space char­ac­ters, they are pro­hib­ited in F# code. You can con­fig­ure the Visual Stu­dio edi­tor to auto­mat­i­cally con­vert tab char­ac­ters into spaces in Tools -> Options -> Text Edi­tor -> F#.

The ear­lier code also demon­strated how F# can inter­op­er­ate with exist­ing .Net libraries:

let time­Of­Day = DateTime.Now.ToString(“hh:mm tt”)

F# can take advan­tage of any .Net library by call­ing directly into it, con­versely any code writ­ten in F# can be con­sumed by other .Net languages.

Com­ments

Like any lan­guage, F# allows you to com­ment your code. To declare a sin­gle line com­ment, use two slashes (//).

For larger com­ments that span mul­ti­ple lines, you can use the mul­ti­line com­ments using (* and *) characters.

For F# appli­ca­tions writ­ten in Visual Stu­dio, there is a third type of com­ments: an XML doc­u­men­ta­tion com­ment. If a com­ment start­ing with three slashes (///) is placed above an iden­ti­fier, Visual Stu­dio will dis­play the comment’s text when you hover over it:


F# Inter­ac­tive

Visual Stu­dio comes with a tool called F# Inter­ac­tive or FSI. F# Inter­ac­tive is a tool known as a REPL (read-evaluate-print loop), it accepts F# code, com­piles and exe­cutes it, then prints the results. This allows you to quickly and eas­ily exper­i­ment with F# code sim­i­lar to how snip­pet edi­tor allows you to do the same with C# code.

Once it’s open, it accepts F# code until you ter­mi­nate the input with ;; and a new­line, the code entered will be com­piled and exe­cuted. After each code snip­pet is sent to FSI, for every name intro­duced you will see val <name> : type value, for example:

Notice when you don’t give a vari­able a name, FSI will sim­ply call it ‘it’.

FSI allows you to write code in Visual Stu­dio edi­tor which offers syn­tax high­light­ing and Intel­liSense, but test your code in the FSI win­dow. You can copy the entire code body from the exam­ple ear­lier and test the main method in FSI by call­ing it:

Man­ag­ing F# Source Files

The F# lan­guage has some unique char­ac­ter­is­tics when it comes to man­ag­ing projects with mul­ti­ple source files. In F#, the order in which code files are com­piled is sig­nif­i­cant.

You can only call into func­tions and classes defined ear­lier in the code file or in a sep­a­rate code file com­piled before the file where the func­tion or class is used. If you rearrange the order of the source files, your pro­gram may no longer build!

The rea­son for this sig­nif­i­cance in com­pi­la­tion order is type infer­ence, a topic to be cov­ered later on.

F# source files are com­piled in the order they are dis­played in Visual Studio’s Solu­tion Explorer, from top to bot­tom. You can rearrange the files by right-clicking and select­ing Move Up or Move Down. The equiv­a­lent key­board short­cuts are Alt+Up and Alt+Down, though these don’t seem to be work­ing in VS2008 with Resharper, or maybe I just need to tweak my key mapping.

Share

Def­i­n­i­tion:

Aspect Oriented Program­ming (AOP) is a pro­gram­ming par­a­digm where each appli­ca­tion can focus on its pri­mary func­tions and core con­cerns by encour­ag­ing greater mod­u­lar­ity and increas­ing sep­a­ra­tion of cross-cutting con­cerns (such as log­ging and authentication).

Pur­pose:

In any real-world appli­ca­tions, when you’re writ­ing code to address the prob­lem domain (say, book­ing an order) you might need to address other con­cerns such as:

  • per­sis­tence — writ­ing to the data­base for example
  • trans­ac­tion han­dling – defin­ing trans­ac­tion scope and set­ting roll­back strat­egy, etc.
  • secu­rity — user authen­ti­ca­tion for example
  • log­ging — for audit­ing and debugging

So effec­tively you’re mix­ing mul­ti­ple domains with fine-grained inter­sec­tions and likely to end up with:

  • tan­gled code — mak­ing it more dif­fi­cult to work out what the code is doing to address the core concern
  • boil­er­plate code at every inter­sec­tion point – intro­duc­ing dupli­cated code and increas­ing the size of the code base and the blast radius of any change that are not related to the prob­lem domain, e.g. chang­ing the per­sis­tence media..

AOP aims to address these prob­lems by sep­a­rat­ing cross-cutting con­cerns into sin­gle units called aspects, each aspect encap­su­lates behav­iours that affect mul­ti­ple classes into reusable modules.

Part­ing thoughts..

As far as I can think of, the only draw­back of AOP is that you no longer see all the behav­iours of your class when you open it and it requires knowl­edge of the whole sys­tem to know what else are hap­pen­ing under the cover. Which inter­est­ingly, is the flip side of the same coin because you employ AOP when you don’t want to deal with cross-cutting con­cerns all the time!

One of the ways to mit­i­gate this prob­lem is to build up a cul­ture in your team and stan­dard­ise how AOP is imple­mented so that every­one is on the same page and there are few surprises.

Frame­works:

Post­Sharp pro­vides a light­weight AOP frame­work for the .Net plat­form and is estab­lish­ing itself as the de facto stan­dard much like the way AspectJ has done for Java.

Share