In this post I will talk about the lists in F#, one of the fundamental concepts of the language. What should be said from the very beginning is that list are imutable single linked list. That means whenever you change a list, a new list is created.

You can declare a list in the following ways:

let list1 = [1;2;3;4]
let list2 = 5::6::7::8::[]

To print the content of the list you can do this:

printfn “list1: %a” output_any list1
printfn “list2: %a” output_any list2

list1: [1; 2; 3; 4]
list2: [5; 6; 7; 8]

You can concatenate two lists with operator @:

let list3 = list1 @ list2
printfn "list3: %a" output_any list3

list3: [1; 2; 3; 4; 5; 6; 7; 8]

and you can append elements to the beginning of the list with operator ::

let list4 = -1::0::list3
printfn "list4: %a" output_any list4

list4: [-1; 0; 1; 2; 3; 4; 5; 6; 7; 8]

You can also use the List (defined in Microsoft.FSharp.Code) functionality to print a list by iterating over its elements:

list3: [1; 2; 3; 4; 5; 6; 7; 8]

1 2 3 4

The same can be achieved using the pipe operator:

list1 |> List.iter (fun x -> printf "%d " x)

You can also iterate and get the index of the list elements, with List.iteri:

list1 |> List.iteri (fun i x -> printfn "list1[%d] : %d " i x)

list1[0] : 1
list1[1] : 2
list1[2] : 3
list1[3] : 4

List have a special representation, a head followed by a tail, that is in turn another list (including empty list []). Let's consider the list [1;2;3]. It has the head 1, and the tail [2;3]. The tail, in turn, has the head 2 and the tail [3]. This tail has the head 3 and the tail [], which is the empty list.
You can see the head and tail of a list with List.hd and List.td:

printfn "head list1: %a" output_any (List.hd list1)
printfn "tail list1: %a" output_any (List.tl list1)

The ouput for list1 [1;2;3] is:

head list1: 1
tail list1: [2;3]

Enough with basic things. Let's try working with lists.

1. Minimum and maximum from a list

We can compute the maximum (or minimum) of a list using the following algorithm:

  • if the list is empty, indicate error
  • if the list has only one element, that is the maximum (or minimum)
  • if the list has at least to elements, compute the maximum between that element and the maximum from the rest of the list

That sounds like a recursive operation, which can be simply put in F# like this:

let rec greatest_element l =
    match l with
    | [] -> failwith "empty list"
    | [x] -> x
    | x::rest -> max x (greatest_element rest)

let rec smallest_element l =
    match l with
    | [] -> failwith "empty list"
    | [x] -> x
    | x::rest -> min x (smallest_element rest)

We can use that like this:

let list1 = [1;2;3;4;-4;-3;-2;-1]
let list2 = []   

try
   printfn "maximum from list1: %d" (greatest_element list1)
   printfn "minimum from list1: %d" (smallest_element list1)

   printfn "maximum from list2: %d" (greatest_element list2)
   printfn "minimum from list2: %d" (smallest_element list2)
with
   Failure msg ->
      printfn "Error: %s" msg

and the output would be:

maximum from list1: 4
minimum from list1: -4
Error: empty list

2. Reversing a list

How would we reverse a list? We should take the last element and append to it the one before the last. To the new list we append the one before the one before the end, etc. That again sounds recursive.

let rec revert_list l =
   match l with
   | [] -> []
   | x::rest -> (revert_list rest) @ [x]

let list1 = [1;2;3;4;-4;-3;-2;-1]

printfn "list1: %a" output_any list1
printfn "list2: %a" output_any (revert_list list1)

And here is the output:

list1: [1; 2; 3; 4; -4; -3; -2; -1]
list2: [-1; -2; -3; -4; 4; 3; 2; 1]

3. Inserting in a list

So how could we insert an element in a list, before or after a specified element? We can use the following algorithm:

  • if the list is empty, the new list has one element (the one to insert)
  • else, if the head is the element we are looking for, create a list, with the new element either before the head, or between the head and the tail
  • else, if the head is not the element we are looking for, append the head to a list created by inserting the new element in the tail.

You got that right, recursion again.

let rec insert_after elem newelem l =
    match l with
    | [] -> [newelem]
    | x::rest -> if x = elem then
                    (x::newelem::rest)
                 else
                     x::(insert_after elem newelem rest)

let rec insert_before elem newelem l =
    match l with
    | [] -> [newelem]
    | x::rest -> if x = elem then
                    (newelem::x::rest)
                 else
                    x::(insert_before elem newelem rest)        

let list1 = [1;2;3;4;-4;-3;-2;-1]
let list2 = insert_after 4 6 list1
let list3 = insert_before 6 5 list2

printfn "list1: %a" output_any list1
printfn "list2: %a" output_any list2
printfn "list3: %a" output_any list3

And the output is:

list1: [1; 2; 3; 4; -4; -3; -2; -1]
list2: [1; 2; 3; 4; 6; -4; -3; -2; -1]
list3: [1; 2; 3; 4; 5; 6; -4; -3; -2; -1]

4. Removing elements from a list

As a last exercise, let's consider the removing of elements from a list. The following steps can be used to remove elements:

  • if the list is empty, return an empty list
  • if the list is not empty and the head meets the removing criteria, return a list obtained by reiterating the algorithm on the tail of the list
  • if the list is not empty and the head does not meet the removing criteria, return a list obtained by appending the head to a list optained by reiterating the algorithm on the tail of the list

let rec remove_if l predicate =
    match l with
    | [] -> []
    | x::rest -> if predicate(x) then
                    (remove_if rest predicate)
                 else
                     x::(remove_if rest predicate)

The great thing about this implementation is that we can pass a lambda expression as a predicate, and use it to specify the criteria for removing elements. We can remove like that, for instance, the odd elements, or the even elements, or the negative elements. Here is some sample code:

let list1 = [1;2;3;4;-4;-3;-2;-1]

let list2 = remove_if list1 (fun x -> (abs x &&&1) = 1)
let list3 = remove_if list1 (fun x -> (abs x &&&1) = 0)
let list4 = remove_if list1 (fun x -> x < 0)

printfn "%a" output_any list1
printfn "%a" output_any list2
printfn "%a" output_any list3
printfn "%a" output_any list4

The output for this sample is:

[1; 2; 3; 4; -4; -3; -2; -1]
[2; 4; -4; -2]
[1; 3; -3; -1]
[1; 2; 3; 4]

I hope this will help you to get a grip on how you can work on lists in F#.

Hits for this post: 17385 .

I was writing today about the movie Pirates of the Caribbeans, naming the post “Pirates at their Worst“. In the meanwhile I found this article on the APC Magazine’s web site, called Romania: a global hotspot for eBay fraud. It reported that the Australian office of eBay has organized a news conference to talk about the frauds commited by Romanians. According to a report from 2006 of the IC3.GOV Internet Crime Complaint Center, Romanian ring crime scammed eBay users for $5,000,000. Out of the sudden, pirats are no longer romantic heroes, looking for adventure, driven by honor and best rolemodels our kids can have.

Mat Henley, of the eBay global fraud investigation team said that:

We discovered that Romania had a huge technology gap between generations. It was enormous: 25-30 year old criminals were some of the brightest people we’ve dealt with, but when you mix in the prosecutors, law enforcement and magistrates, some of them had never been on a computer – period.

To tackle the perpetrators, eBay had to buy computers and digital cameras for the Romanian police and involve US agents working in Romania. The result were “hundreds” of arrests being made, though he refused to give any figures about the actual impact on the internet fraud.

Now, what I have to say about that: yes, Romanians were involved in many frauds, but I doubt that eBay bought computers for the Romanian Police and they made hundreds of arrests in Romania. The news conference was rather a way to make publicity for the company and calm down the unrest among Australian users about frauds on eBay. If you read the report I mentioned above, you’ll see that Romania takes only the 5th place, accounting for only 1.6% of fraud.

Top Ten Countries – Perpetrator
1. United States – 60.9%
2. United Kingdom – 15.9%
3. Nigeria – 5.9%
4. Canada – 5.6%
5. Romania – 1.6%
6. Italy – 1.2%
7. Netherlands – 1.2%
8. Russia– 1.1%
9. Germany – 0.7%
10. South Africa – 0.6%

Most of Romanians operated from countries such as US or UK. I don’t think they had to buy computers to the Police in these countries. So, without a real report from eBay or Romanian Police about the frauds made from Romania, I call the eBay announcements a scam.

And as an interesting thing, I read in the report that:

Pruette is a Romanian national and is currently being held by the Immigration and Naturalization Service. He is believed to be part of a multi-state cell which sends funds to Romania and other countries to support terrorist efforts.

So, according to people that investigate internet crime, Romania might be a terorrist heaven. Let’s only hope that after the Middle East, they won’t focus on us to counter terrorism and bring democracy to the area.

Hits for this post: 8315 .

I have decided to make a comparison for file IO operations on Win32, CRT, STL and MFC.

For all four libraries/APIs I have done the profiling in the following way:

  • open the file
  • allocate the buffer used for reading
  • start the timer
  • read/write from/to the file
  • stop the timer
  • close the file
  • release the memory

This way, the profiling only applies on the read or write operations, not on other task such as opening and closing files, allocating or releasing memory.

What I’ve used:

  • Win32: functions CreateFile, ReadFile, WriteFile and CloseHandle
  • CRT: functions FILE, fopen, fread, fwrite and fclose
  • STL: for reading class std::ifstream, and methods, open(), read() and close() and for writing class std::ofstream and methods open(), write() and close()
  • MFC: class CFile, and methods Open(), Read(), Write and Close()

I have performed the reading with different buffer sizes: 32, 64, 128, 256, 512 bytes and 1KB, 2KB, 4KB, 8KB, 16KB, 32KB, as well as with a buffer accomodating the entire file. Same buffer sizes were used for writing. For testing the write operation I also wrote the file at once. In all cases, I generated a 16MB file.

To decide which one is better overall, I have associated a score with each result. The faster (for each buffer size) got 4 points, the next 3, 2, and 1. The bigger the sum, the more performant overall.

I have run the program on two files for reading on a Intel(R) Pentium(R) 4 CPU at 3.20GHz, 1 GB RAM, running Windows XP, SP2. The results, representing an average of 15 runs, are shown bellow:

File 1: size 2,131,287 bytes

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 0.01917630 0.063093700 0.02123180 0.064283700 4 2 3 1
64 0.01474360 0.031909200 0.01460960 0.032482700 3 2 4 1
128 0.01118370 0.016183700 0.01164060 0.016426700 4 2 3 1
256 0.00929148 0.008573490 0.01063090 0.008840810 2 4 1 3
512 0.01071420 0.004684040 0.00985086 0.004745970 1 4 2 3
1024 0.00883909 0.002584480 0.00907385 0.002486950 2 3 1 4
2048 0.00847502 0.001531440 0.00894887 0.001477660 2 3 1 4
4096 0.00776395 0.000981391 0.00891128 0.001009350 2 4 1 3
8192 0.00740465 0.000744340 0.00913489 0.000749145 2 4 1 3
16384 0.00740928 0.000604900 0.00936410 0.000673978 2 4 1 3
32768 0.00736531 0.000657141 0.00837419 0.000610040 2 3 1 4
file size 0.00955846 0.002496180 0.00981464 0.002428280 2 3 1 4
          28 38 20 34

File 2: size 110,999,662 bytes

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 1.011360 3.3216500 2.47695 3.2822700 4 1 3 2
64 0.742683 1.6815600 0.804563 1.6836300 4 2 3 1
128 0.600344 0.8697840 0.639113 0.8750610 4 2 3 1
256 0.521233 0.4661430 0.586376 0.4751340 2 4 1 3
512 0.501420 0.2734540 0.532212 0.2653010 2 3 1 4
1024 0.474670 0.1532950 0.510266 0.1587330 2 4 1 3
2048 0.458538 0.1012430 0.479981 0.1067980 2 4 1 3
4096 0.432552 0.0715536 0.488251 0.0774886 2 4 1 3
8192 0.417481 0.0607284 0.467426 0.0674372 2 4 1 3
16384 0.400320 0.0510897 0.458111 0.0602826 2 4 1 3
32768 0.406497 0.0503835 0.461796 0.0572124 2 4 1 3
file size 0.523950 0.1867240 0.583327 0.1828440 2 3 1 4
          30 39 18 33

The first conclusion is that overall Win32 is the fastest, followed by MFC, then by CRT, the slowest being the STL.

The second conclusion is that CRT is the fastest with buffer sizes smaller than 256 bytes, and then Win32 and MFC are the faster.

The results for writing were a quite similar. Of course, running several times, can produce slight variation in the results (both for read and write).

File 3 : size 16,809,984

Buffer Size CRT Win32 STL MFC CRT Win32 STL MFC
32 0.273796 0.890973 0.335245 0.877301 4 1 3 2
64 0.219715 0.465254 0.259597 0.450076 4 1 3 2
128 0.181927 0.24715 0.201949 0.245169 4 1 3 2
256 0.178976 0.141146 0.189154 0.143666 2 4 1 3
512 0.153816 0.0872411 0.172239 0.0851424 2 3 1 4
1024 0.148846 0.0608282 0.159186 0.0601419 2 3 1 4
2048 0.139997 0.0493811 0.150503 0.0496117 2 4 1 3
4096 0.125797 0.0705146 0.15275 0.0508061 2 3 1 4
8192 0.126708 0.15708 0.1459 0.0655567 3 1 2 4
16384 0.121919 0.0282886 0.14662 0.158024 3 4 2 1
32768 0.124429 0.0247259 0.145496 0.0267301 2 4 1 3
16809984 0.148424 0.47066 0.146321 0.513205 3 2 4 1
          33 31 23 33

You can download the project I used for the benchmark from here.

Hits for this post: 18800 .

Suppose you have a class foo like this:

class foo
{
public:
	int X;
	int Y;
	int Z;

	foo(int x = 0, int y = 0, int z = 0): X(x), Y(y), Z(z) {}
};


And you have a variable f(1, 2, 3) what you watch in your Watch window. The window looks like this:

Default expansion for foo

The field Value shows a default expansion of the object, {X=1 Y=2 Z=3}. However, this can be changed by modifying a file called autpexp.dat, located in the Visual Studio installation folder, under Common7\Packages\Debugger. This file allows the control of several things in the debugger, such as the string displayed in the Value column, the functions the debugger skips when stepping, etc. One important limitation however, is that it does not support complex expression, for which it simply displays “???”. This file is loaded each time you start the debugger.

The Autoexp.dat file consists in a set of rules, called AutoExpand rules, specified on a single line and having the format:

type=...



where

type      Name of the type (may be followed by <*> for template
          types such as the ATL types listed below).
text      Any text.Usually the name of the member to display,
          or a shorthand name for the member.
member    Name of a member to display.
format    Watch format specifier. One of the following:

Letter  Description                 Sample         Display
------  --------------------------  ------------   -------------
d,i     Signed decimal integer      0xF000F065,d   -268373915
u       Unsigned decimal integer    0x0065,u       101
o       Unsigned octal integer      0xF065,o       0170145
x,X     Hexadecimal integer         61541,X        0X0000F065
l,h     long or short prefix for    00406042,hx    0x0c22
          d, i, u, o, x, X
f       Signed floating-point       3./2.,f        1.500000
e       Signed scientific-notation  3./2.,e        1.500000e+000
g       Shorter of e and f          3./2.,g        1.5
c       Single character            0x0065,c       'e'
s       Zero-terminated string      pVar,s         "Hello world"
su      Unicode string              pVar,su        "Hello world"


The AutoExpand rules must be located under the [AutoExpand] section, because the file also contains rules for visualizing types when the object is expanded. These visualization rules are located under [Visualizer] and are a feature new in VS2005.

Going back to our foo class, suppose you use this class heavily and you don’t like the default string shown in the Value column, and you would like it to be like this: {X=0×00000001, Y=0×00000002, Z=0×00000008}. That means using comma to separate the fields and display the values as hexadecimal numbers. What you would have to do is adding a AutoExpand rule like this:

foo =X=< X, X >, Y=< Y, X >, Z=< Z, X >


It says something like this: display X followed by = and the value of member X of foo in hexadicimal, followed by comma, space, Y and = followed by the value of member Y of foo in hexadecimal, and so on. Debugging now, will show a different string:

Custom auto expand string for foo

But now let’s imagine that our foo class was actually a template class, like this:

template < typename T >
class foo
{
public:
	T X;
	T Y;
	T Z;

	foo(T x, T y, T z): X(x), Y(y), Z(z) {}
};


The rule above would not help for an object foo f(1, 2, 3) and the default format would be used. That is so because template types have a different form: we need to use <*>.

foo< * > =X=< X, X >, Y=< Y, X >, Z=< Z, X >


With this rule the string is the same as in the above image (the type though changes to foo).

What is this good for? Well, I have shown you a simple example here, but suppose you have complex types, with a lot of members, and the default string shown by the debugger doesn’t help you. To see the info you actually need in the watch window or when you put the mouse over the variable you would have to expand the object and scroll down, perhaps expand aggregated objects, etc. to reach what you actually need on a regular basis. Creating a custom rule for the auto displayed value allows you to show exactly the information you need, in the form you want. For instance you may always want to see the numeric values of X,Y and Z from foo as hexadecimal, but you switched for decimal view in the debugger (from the context menu of the Watch window). That won’t affect the way you view your type, because of the custom rule.

A second part of autoexp.dat file is dedicated to visualization rules. These are mappings from types to display form, shown when you expand the object. Unlike the simple AutoExpand rules, these are more complex and have a dedicated scripting language, which unfortunatelly is not documented.

The basic form of a rule is:

typename[|typename...] {
    preview (
        preview-string-expression
    )
    stringview (
        text-visualizer-expression
    )
    children (
        expanded-contents-expression
    )
}


The three sections have the following purpose:

  • preview: an expression (string literal or expression) to be shown in the Watch, QuickWatch or Command window; if the preview section is present and you also have a AutoExpand rulu for it, the AutoExpand rule is ignored;
  • children: offer the possibility to construct hierarchies;
  • stringview: used to compose the string that is shown in the Text, XML or HTML visualizer; for instance when you have a string, it shows a magnifying glass on the right; clicking it opens a modal dialog that displays the full content of the variable

Considering the template version of foo, the visualizer template bellow sets the text to be shown in the preview. It’s the same result as with the AutoExpand rule.

foo< * > {
	preview
	(
	  #(
		"X=",
		[$c.X, X],
		", Y=",
		[$c.Y, X],
		", Z=",
		[$c.Z, X]
	  )
	)
}


If you are interested to see the sum of the values, in decimal, you could add a children element like this:

children
(
  #(
	sum: [$c.X + $c.Y + $c.Z, d]
  )
)



The Watch window now looks like this:

Visualizer with childrens

But now the X, Y and Z members are gone. You can shown them modifying the children:

children
(
  #(
	X: [$c.X, X],
	Y: [$c.Y, X],
	Z: [$c.Z, X],
	[sum]: [$c.X + $c.Y + $c.Z, d]
  )
)


Visualizer with childrens

To show original members with the auto evaluation, you can use [$c, !]. However, the parser seems to be unstable, and many times it yields errors that may confuse it, or it could work in a way you don’t understand. At least that’s my case.

The visualizers are more complicated. They allow displaying of array, lists, trees, and could contain conditional statements. You actually have to use variable $c to dereference the current variable. A good attempt to document it can be found at http://www.virtualdub.org/blog/pivot/entry.php?id=120. I recommend reading this article for more information avout visualizers.

Hits for this post: 27971 .

One of the most important qualities of code is, or at least should be, readability. The simple fact that it works is not enough. If it’s not readable, it definitelly ain’t maintainable. Thus, our mission, as programmers, is to right code, that above being correct, is also readable and understandable. When a new programmer joins a team it takes time to familiarize with the application domain, language or code or all. To reduce that time, companies use code convension, that in theory should make the code readable, but unfortunatelly in reality, in many cases, does the oposite. 

A long time ago, in a galaxy far, far away there were no rich IDEs and no Intellisense. Programmers had to knew by memory all the types, functions, and variable names. Moreover they had to new the type of variables, parameters or returned values. Thus, naming conventions helped in taming the beast. Probably one of the most famous (and infamous at the same time) convention, at least for C and C++, is the so called Hungarian notation, invented almost 3 decades ago by Charles Simonyi, a chief architect at Microsoft. It was named so because it made code looked like written in a foreign language, and Simonyi was of Hungarian origins. Nowadays there are a lot of variations of the Hungarian notations, but in the beginning was one called Apps Hungarian, named after the group Simonyi was working in, called Applications, that was in charged with developing Word and Excel. Later, the group that developed the Windows barrowed the convention without understanding it, and developed a second version called System Hungarian. That was evangelized by Charles Petzold in his bestseller “Programming Windows”, probably the bible of windows programmers.

Though Simonyi had some good intentions and ideas, they were misinterpreted, and that led to a bad convention style. All because he used the term “type” when he actually meant “kind”. In a paper, written in an academic style, he wrote:

“The basic idea is to name all quantities by their type.”

Though he used to quote the word type, and tries to explain that a type is defined by a set of operators that apply to a quantity, people did not correctly undestand what he was saying. He used rgX to indicate an array of X or “range X”, cX, to count the instances of X, or dX for the difference between two instances of type X. Apps Hungarian was used for Excel and Word, where rowWidth could be an integer variable specifying the width of a row, and dX also an integer variable but specifying the number of selected colums. In his Apps Notation it didn’t make any sense for instance to add dX to rowWidth, though these were both integers, which has an operator + defined. They have the same type, but they are not of same kind. The original paper of Charles Simonyi was published in 1999 in MSDN: http://msdn2.microsoft.com/en-us/library/aa260976(VS.60).aspx

The Apps Hungarian focused on the semantic of quantities (variables, functions). In Systems Hungarian, however, the focus was moved on type. With p indicating pointer, ch characters, dw double words, ar arrays, sz, null-terminated strings, or lp far pointers, you could see variables named like lpszName (long pointer to null-terminted string specifing a name), dwI (double word index), arx (array of X), but also things like lpararszID (long pointer to an array of arrays of null terminated strings). Now imagine hundred of thousand on lines of code written line that. It simply makes my head ache. Such notations cannot make the code more readable. Only the oposite.

If you look up on the web, you’ll see a lot of notation conventions for the same language. Even for the Hungarian notations, there are plenty of variants. Here are just two that I picked-up randomly with a google search:
http://web.umr.edu/~cpp/common/hungarian.html
http://www.gregleg.com/oldHome/hungarian.html

I say enough with bad style programming! The days of such notations are long gone. Today Intellisense help you writing the code. When you use an object and type . or -> it automatically shows you the list of functions, variables, properties, etc. it has. When you write a function name it shows you the prototype, with all the overloads, parameters type and name, and even comments. And many other features that replace the need to prefix your variables with a long string of letters that you can barely read. Joel Spolsky wrote a very good article called Making Wrong Code Look Wrong, where among others he explains why the Hungarian notation fell into disgrace and was replaced at Microsoft with a new one with the release of the .NET framework.

I’m not going to delve into proposing good convention styles, there are plenty available. I just want to make some points: often, what you think it’s good for you, it proves the oposite in reality. Using bad naming convension is like deeling with a lot of birocrary: too many paper work, no real benefit. Thus I will restrain myself to just a few points:

  • variables (whether local, global, parameters, etc.) should be named in such a way that the focus is on the kind (the meaning of the variable) not the type. dwCnt doesn’t tell me anything, except that its a double word value, but countOfItems indicates that this variable is used to count items, regardless it’s a single or double word. That’s much more valuable for someone reading and trying to understand your code. When you have two variables dwCnt and dwNr, perhaps in a given context you may wonder why they are not summed together, but if they were called countOfItems and numberOfBuyers, you could immediatelly understand why.
  • context should not be added aritificially. Tim Ottinger makes a very good point on this matter in his article called Ottiger’s Rules for Variables and Class Naming. The company I work for uses a very bad naming convention that adds unnecessary context to variables. They use to prefix the names of types, functions, even variables with the name of the module. For instance if a module is called “Cluster Display Framework” (a name invented by me), they prefix everything with CDF: variable names, function, parameters, types, everything starts with the module name. Such context is totally unnecessary. Prefixing all your entities in a module with the module name does not add any kind of value to the code of that module, because you simply ignore that context. When you write in languages such C++, C#, Java, etc. you have the mechanism of namespaces available. You can put functions, classes, etc. that belong together inside a namespace, instead of prefixing everything.
  • unnecessary comments should be avoided. Don’t write comments just for the sake of writing. That doesn’t help. Polluting the code with redundant comments is unnecessary. If you have a variable of type string called nameOfUser, don’t add a comment to it, saying it specifies the user name. That is already known from the name of the variable. And that leads back to the first point I made above. Comments should be used to explain algorithms, or decision makings (why something is called in a particular context). As for the rest, the code should be self-commenting. That is a very good point made by Rober Fowler in his book “Refactoring”.

With all that being said, I just want to add that perhaps the best naming convension I know is the one use in the .NET framework (you can read about it here http://www.akadia.com/services/naming_conventions.html). I tend to use it lately even in C++, though C++ is not a language targeting the framework. It’s simple and meaningful. 

To conclude, make sure that when you write code, you do it in such a way that it doesn’t take a lot of time and head aches to understand it. Keep it simple. Keep it readable.

Hits for this post: 6172 .