Book Review: Code Complete

I suppose for any serious software engineer one must read Code Complete. Last week I finished it and have been trying to think of how to write a review of it. I’ve decided to do so briefly.

Let me start off by saying I’m excited that I finished it. There is a lot of good information and there is no doubt that it is the standard for sound software developement principles. That being said, remember when you try to tackle this bood that it is a text book. Sure there are some interesting anecdotes about this and that. I suppose I should have been more thrilled about reading it but couldn’t drag myself to pour through it like I have some of my other software books. It took me a year to read Code Complete. During that time I re-read The Belgariad series, The Malloreon series, most of the Song of Ice and Fire series, and read for the first time Pro WPF in C# 2008, Effective C# and I’m almost done with More Effective C#.

So what am I saying? I know there are those of you out there that love Code Complete and read it voraciously like a good fiction novel. I couldn’t even read it like a good code book. Pro WPF in C# 2008 I read like a good fiction novel. I drank it in and loved it. Code Complete I just couldn’t do that with. As I said, it’s sound, solid developement principles I try to apply every day on the job. I learned a lot and will continue to try and apply the princibles of Code Complete. Simply because of that it is a reason to read the book.

If you’re like me and are struggling to get through Code Complete, spread it out, read a chapter and then take a break and read something else. There are 35 chapters in Code Complete. Read a chapter every two weeks, in between other books and it will take you just a bit over a year to read it.

What else can I say? 99% of the book makes perfect sense. Some of the code formatting seemed a bit off but I just let visual studio format my code for me. Ctrl-K + Ctrl-D, Baby!

Read it, grok it, follow it and your code will be better, cleaner and easier to maintain.
That’s all there it to it.

Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

Often Unused Operators: Curly Braces {}

Okay, I know you think I’ve seriously hit the crack pipe here. Curly Braces, as I’m sure we all know, are fundamental to programming in most languages. This is true no more so then here in C#. We use them for if, for, using, do, while, namespace scope, class scope, method scope and getters and setters for parameters.

So how could I dare to say the {} is an often unused operator? Well, I’m specifically talking about a use of the operators in this case, not the operators themselves.

Did you know you can use curly braces by themselves? Take a look at this:

public Window1()
{
    InitializeComponent();

    {
        int [] intList = { 1, 2, 3, 4, 5, 6 };
        var evens = intList.Where(x => x % 2 == 0);
    }

    {
        int[] intList = { 1, 2, 3, 4, 5, 6 };
        var odds = intList.Where(x => x % 2 == 1);
    }
}

Yes! That there are curly braces by themselves!

Why the hell would anyone want to do this? I find myself using them all the time when writing up samples where at http://www.formatexception.com. The reason is that I test all the sample code I post up here that I write. This has been a big help especially since it seems like a lot of the linq code here derives from msdn samples and, believe it or not, not all of them work.

What this means is that if I want to do a write-up on linq where I’m using the where method on IEnumerables (like above) I write the code surrounded by curly braces. Because each is it’s own scope, call it internal method scope if you will, there won’t be any name collisions. It’s like doing an if(true){} without the if(true), or like using the using keyword as in:

using(Stream ImageStream = new MemoryStream(File.ReadAllBytes(ImagePath)))
{
    BitmapImage bi = new BitmapImage();
    bi.BeginInit();
    bi.StreamSource = ImageStream;
    bi.EndInit();

    Image imageFromFile = new Image() { Source = bi };
    //dump image into wrap panel in form
    imagePanel.Children.Add(imageFromFile);
}

except you don’t have to have a class the implements IDisposable.

So, where would you use this? If you’re real paticular (i.e. anal) about the your variable names. For instace the following code is not valid:

{
    int [] intList = { 1, 2, 3, 4, 5, 6 };
    var evens = intList.Where(x => x % 2 == 0);
}

int[] intList = { 7, 8, 9, 10, 11, 12 };
var odds = intList.Where(x => x % 2 == 1);

The reason is that the set of curly braces define a child scope but the second intlist exists in the parent scope. Sibling scopes can have variables of the same name but not parent/child scopes. If I really wanted my intList to be named “intList” and assuming it would only be needed within the child scope I could put a second set of curly braces around the other code and be free to name my intList to, um, “intList”.

I have never really found a use for this in production code to be honest. I use it a lot when writing up samples for my posts, but not in production code. I suppose if I was adamant about my variable names I would use it more and I think a few of you out there are. I, however, have no problem simply naming my second int list to intListForOdds.

So that is the curly braces and their often unused purpose.

Later,
Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

LINQ Any and All Quantifiers with group by

Now that we’ve touched on “group by” lets throw in a couple of where clauses on the group by with any and all.

If you are really interested in all the data I have the code at the end of this post showing how I add all the products. Since this is just sample data I threw it in a list but chances are you’re going to be getting your list from some sort of DAL.

Let’s start with some lead up to “Any”.

Given:

string[] words = { "cow", "believe", "bread", "river", "receipt", "field" };
var wordsList =
    from w in words
    where w.Contains("ei")
    select w;

we can see this gives a list of words that have “ei” in them. But what if we don’t care for the list? What if we just want to know if any of the words have “ei”? We can simplify life by using the Any on a list from linq and get a boolean.

bool iAfterE = words.Any(w => w.Contains("ei"));

is true.

“No kidding”

“Oh great, folks, if you don’t know already this is Ivan.”

“So next you’re going to tell me I can use the All method on lists to tell me if all of the words contain “ei”? Come on and give your audience some credit. If you’re head wasn’t stuck so far…”

“Ivan, I get the point, I’ll make this easy for all of us and give them the code.”

“And don’t you think this whole talking to yourself think is getting old? I mean come on!”

“You think you can do better?”

“Listen to yourself. You’re talking to me who just happens to me you. What does me doing any better have to do with anything? I am you. Wow, pull yourself together and get this overwith. We have a database rewrite to review today, implement tomorrow and then a week to recode the app for the new database, time to move on.”

“Fine, here” (Note: I couldn’t do it, it looked like crap when I just put up all the code. I have to break it up a little bit so I’m ignoring Ivan because it was just a bad suggestion.)

string[] words = { "cow", "believe", "bread", "river", "receipt", "field" };
var wordsList =
    from w in words
    where w.Contains("ei")
    select w;

bool iAfterE = words.All(w => w.Contains("ei"));

As I’m sure you know, iAfterE is false as not all the words have “ei” in them.

List<Product> products = GetProductList();

var productGroups =
    from p in products
    group p by p.Category into g
    where g.Any(p => p.UnitsInStock == 0)
    select new { Category = g.Key, Products = g };

Console.WriteLine("\nFor Any:");
foreach (var group in productGroups)
{
    Console.WriteLine("\nFor Category {0}:", group.Category);
    foreach (var p in group.Products)
    {
        Console.Write("{0} with {1} units, ", p.ProductName, p.UnitsInStock);
    }
}

In this first product group you can see that the where on the group by is only creating groups by category where any of the products in the category have 0 units in stock. This is key to the where with group by, only if the where is satisfied will the group be created. You will end up with:

For Any:
For Category Condiments:
Aniseed Syrup with 13 units, Chef Anton’s Cajun Seasoning with 53 units, Chef Anton’s Gumbo Mix with 0 units, Grandma’s Boysenberry Spread with 120 units, Northwoods Cranberry Sauce with 6 units, Genen Shouyu with 39 units,
For Category MeatPoultry:
Mishi Kobe Niku with 29 units, Alice Mutton with 0 units, Thüringer Rostbratwurst with 0 units, Perth Pasties with 0 units, Tourtière with 21 units,
For Category DairyProducts:
Queso Cabrales with 22 units, Queso Manchego La Pastora with 86 units, Gorgonzola Telino with 0 units, Mascarpone Fabioli with 9 units,

List<Product> products = GetProductList();
var productGroups =
    from p in products
    group p by p.Category into g
    where g.All(p=> p.UnitsInStock > 0)
    select new { Category = g.Key, Products = g };

Console.WriteLine("\nFor All:");
foreach (var group in productGroups)
{
    Console.WriteLine("\nFor Category {0}:", group.Category);
    foreach (var p in group.Products)
    {
        Console.Write("{0} with {1} units, ", p.ProductName, p.UnitsInStock);
    }
}

For the second product group it is looking to make sure that all products in the group of a UnitsInStock of greater then 0 thus giving you:

For All:
For Category Seafood:
Ikura with 31 units, Konbu with 24 units, Carnarvon Tigers with 42 units, Nord-Ost Matjeshering with 10 units, Inlagd Sill with 112 units, Gravad lax with 11 units,
For Category Produce:
Uncle Bob’s Organic Dried Pears with 15 units, Tofu with 35 units, Rössle Sauerkraut with 26 units,
For Category Beverages:
Chai with 39 units, Chang with 17 units, Guaraná Fantástica with 20 units, Sasquatch Ale with 111 units, Steeleye Stout with 20 units,

Well, that’s a quick write up on any and all with group by. Time to start reviewing ERDs.

Brian

And here is GetProductList:

private List<Product> GetProductList()
{
    List<Product> products = new List<Product>();
    products.Add(new Product { ProductId = 10, ProductName = "Ikura", Category = "Seafood", UnitPrice = 31.0000, UnitsInStock = 31 });
    products.Add(new Product { ProductId = 13, ProductName = "Konbu", Category = "Seafood", UnitPrice = 6.0000, UnitsInStock = 24 });
    products.Add(new Product { ProductId = 18, ProductName = "Carnarvon Tigers", Category = "Seafood", UnitPrice = 62.5000, UnitsInStock = 42 });
    products.Add(new Product { ProductId = 30, ProductName = "Nord-Ost Matjeshering", Category = "Seafood", UnitPrice = 25.8900, UnitsInStock = 10 });
    products.Add(new Product { ProductId = 36, ProductName = "Inlagd Sill", Category = "Seafood", UnitPrice = 19.0000, UnitsInStock = 112 });
    products.Add(new Product { ProductId = 37, ProductName = "Gravad lax", Category = "Seafood", UnitPrice = 26.0000, UnitsInStock = 11 });
    products.Add(new Product { ProductId = 7, ProductName = "Uncle Bob's Organic Dried Pears", Category = "Produce", UnitPrice = 30.0000, UnitsInStock = 15 });
    products.Add(new Product { ProductId = 14, ProductName = "Tofu", Category = "Produce", UnitPrice = 23.2500, UnitsInStock = 35 });
    products.Add(new Product { ProductId = 28, ProductName = "Rössle Sauerkraut", Category = "Produce", UnitPrice = 45.6000, UnitsInStock = 26 });
    products.Add(new Product { ProductId = 3, ProductName = "Aniseed Syrup", Category = "Condiments", UnitPrice = 10.0000, UnitsInStock = 13 });
    products.Add(new Product { ProductId = 4, ProductName = "Chef Anton's Cajun Seasoning", Category = "Condiments", UnitPrice = 22.0000, UnitsInStock = 53 });
    products.Add(new Product { ProductId = 5, ProductName = "Chef Anton's Gumbo Mix", Category = "Condiments", UnitPrice = 21.3500, UnitsInStock = 0 });
    products.Add(new Product { ProductId = 6, ProductName = "Grandma's Boysenberry Spread", Category = "Condiments", UnitPrice = 25.0000, UnitsInStock = 120 });
    products.Add(new Product { ProductId = 8, ProductName = "Northwoods Cranberry Sauce", Category = "Condiments", UnitPrice = 40.0000, UnitsInStock = 6 });
    products.Add(new Product { ProductId = 15, ProductName = "Genen Shouyu", Category = "Condiments", UnitPrice = 15.5000, UnitsInStock = 39 });
    products.Add(new Product { ProductId = 9, ProductName = "Mishi Kobe Niku", Category = "MeatPoultry", UnitPrice = 97.0000, UnitsInStock = 29 });
    products.Add(new Product { ProductId = 17, ProductName = "Alice Mutton", Category = "MeatPoultry", UnitPrice = 39.0000, UnitsInStock = 0 });
    products.Add(new Product { ProductId = 29, ProductName = "Thüringer Rostbratwurst", Category = "MeatPoultry", UnitPrice = 123.7900, UnitsInStock = 0 });
    products.Add(new Product { ProductId = 53, ProductName = "Perth Pasties", Category = "MeatPoultry", UnitPrice = 32.8000, UnitsInStock = 0 });
    products.Add(new Product { ProductId = 54, ProductName = "Tourtière", Category = "MeatPoultry", UnitPrice = 7.4500, UnitsInStock = 21 });
    products.Add(new Product { ProductId = 11, ProductName = "Queso Cabrales", Category = "DairyProducts", UnitPrice = 21.0000, UnitsInStock = 22 });
    products.Add(new Product { ProductId = 12, ProductName = "Queso Manchego La Pastora", Category = "DairyProducts", UnitPrice = 38.0000, UnitsInStock = 86 });
    products.Add(new Product { ProductId = 31, ProductName = "Gorgonzola Telino", Category = "DairyProducts", UnitPrice = 12.5000, UnitsInStock = 0 });
    products.Add(new Product { ProductId = 32, ProductName = "Mascarpone Fabioli", Category = "DairyProducts", UnitPrice = 32.0000, UnitsInStock = 9 });
    products.Add(new Product { ProductId = 1, ProductName = "Chai", Category = "Beverages", UnitPrice = 18.0000, UnitsInStock = 39 });
    products.Add(new Product { ProductId = 2, ProductName = "Chang", Category = "Beverages", UnitPrice = 19.0000, UnitsInStock = 17 });
    products.Add(new Product { ProductId = 24, ProductName = "Guaraná Fantástica", Category = "Beverages", UnitPrice = 4.5000, UnitsInStock = 20 });
    products.Add(new Product { ProductId = 34, ProductName = "Sasquatch Ale", Category = "Beverages", UnitPrice = 14.0000, UnitsInStock = 111 });
    products.Add(new Product { ProductId = 35, ProductName = "Steeleye Stout", Category = "Beverages", UnitPrice = 18.0000, UnitsInStock = 20 });
    return products;
}
Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

LINQ group by and GroupBy

I initially starting using LINQ as it was easy to order the objects in a list without having to write a Comparer. Just write your lambda expression and BOOM!, list sorted.

I want to take this thought a step further, and as implied by the post title, do a group by.

Starting, here is an order by % 2 giving us a list of even and then odd numbers:

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

var orderedNumbers = from n in numbers
                     orderby n % 2 == 0 descending
                     select n;

foreach (var g in orderedNumbers)
{
    Console.Write("{0},", g);
}

This is all pretty straight forward, order by numbers that when modded by 2 are 0 and we have the numbers 4,8,6,2,0,5,1,3,9,7.

But what if I want to simply have two lists, one with evens and one with odds? That’s where group by comes in.

int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

var numberGroups = from n in numbers
                   group n by n % 2 into g
                   select new { Remainder = g.Key, Numbers = g };

foreach (var g in numberGroups)
{
    if(g.Remainder.Equals(0))
        Console.WriteLine("Even Numbers:", g.Remainder);
    else
        Console.WriteLine("Odd Numbers:", g.Remainder);
    foreach (var n in g.Numbers)
    {
        Console.WriteLine(n);
    }
}

with the output:

Odd Numbers:
5
1
3
9
7
Even Numbers:
4
8
6
2
0

What’s happening here is that LINQ is using anonymous types to create new dictionary (actually a System.Linq.Enumerable.WhereSelectEnumerableIterator<System.Linq.IGrouping<int, int>>).

It is important to note here that the key here that everything is keyed on is the first value after the “by”.

Taking this one simple step forward let’s group a bunch of words. The following doesn’t work quite right:

string[] words = { "blueberry", "Chimpanzee", "abacus", "Banana", "apple", "cheese" };

var wordGroups = from w in words
                 group w by w[0] into g
                 select new { FirstLetter = g.Key.ToString().ToLower(), Words = g };

foreach (var g in wordGroups)
{
    Console.WriteLine("Words that start with the letter '{0}':", g.FirstLetter);
    foreach (var w in g.Words)
    {
        Console.WriteLine(w);
    }
}

giving us the output:

Words that start with the letter 'b':
blueberry
Words that start with the letter 'c':
Chimpanzee
Words that start with the letter 'a':
abacus
apple
Words that start with the letter 'b':
Banana
Words that start with the letter 'c':
cheese

That’s because there is a bit of a red herring here. Remember that the first value after the by is what is used to group by. In our case w[0] for Chimpanzee is “C”, not c. If we change it to:

string[] words = { "blueberry", "Chimpanzee", "abacus", "Banana", "apple", "cheese" };

var wordGroups = from w in words
                 group w by w[0].ToString().ToLower() into g
                 select new { FirstLetter = g.Key.ToString().ToLower(), Words = g };

foreach (var g in wordGroups)
{
    Console.WriteLine("Words that start with the letter '{0}':", g.FirstLetter);
    foreach (var w in g.Words)
    {
        Console.WriteLine(w);
    }
}

then we get the results we expect with:

Words that start with the letter 'b':
blueberry
Banana
Words that start with the letter 'c':
Chimpanzee
cheese
Words that start with the letter 'a':
abacus
apple

Taking this even one step further we can throw an orderby above the group and order things alphabetically:

var wordGroups = from w in words
orderby w[0].ToString().ToLower()
group w by w[0].ToString().ToLower() into g
select new { FirstLetter = g.Key.ToString().ToLower(), Words = g };

So let’s now make this a bit over the top complex. Given the classes:

public class Customer
{
    public List<Order> Orders { get; set; }
}

public class Order
{
    public DateTime Date { get; set; }
    public int Total { get; set; }
}

lets group a customer list by customer, then by year, then by month:

List<Customer> customers = GetCustomerList();

var customerOrderGroups = from c in customers
                          select
                              new {c.CompanyName,
                                   YearGroups = from o in c.Orders
                                                group o by o.OrderDate.Year into yg
                                                select
                                                    new {Year = yg.Key,
                                                         MonthGroups = from o in yg
                                                         group o by o.OrderDate.Month into mg
                                                         select new { Month = mg.Key, Orders = mg }
                                                    }
                                  };

Whew! that took a lot to copy and paste from MSDN’s sample library! ;)
As mentioned previously the important part here is that the keys for these are the first value after the “by”. This just creates a bunch of dictionarys keyed embeded together keyed on the values after the “by”.

The GroupBy method that is a part of Linq can also take an IEqualityComparer. Given the comparer:

public class AnagramEqualityComparer : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return getCanonicalString(x) == getCanonicalString(y);
    }

    public int GetHashCode(string obj)
    {
        return getCanonicalString(obj).GetHashCode();
    }

    private string getCanonicalString(string word)
    {
        char[] wordChars = word.ToCharArray();
        Array.Sort<char>(wordChars);
        return new string(wordChars);
    }
}

we can find all the matching anagrams. This is possible because the IEqualityComparer compares words based on a sorted array of characters. If you take “meat” and “team” they both become “aemt” when sorted by their characters.

string[] anagrams = { "from", "salt", "earn", "last", "near", "form" };

var orderGroups = anagrams.GroupBy(
                      w => w.Trim(),
                      a => a.ToUpper(),
                      new AnagramEqualityComparer()
                  );

foreach (var group in orderGroups)
{
    Console.WriteLine("For the word \"{0}\" we found matches to:", group.Key);
    foreach (var word in group)
    {
        Console.WriteLine(word);
    }
}

Like the inline Linq, here the first value is the key and the second value is what to put into the list. The last value is the IEqualityComparer I mentioned earler. We don’t get double entries since “last” will match “salt” and there is no reason, therefore, to add a new key.

That’s all for now.

Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

Often Unused Operators: checked and unchecked

From MSDN:
The checked keyword is used to explicitly enable overflow-checking for integral-type arithmetic operations and conversions.
By default, an expression that contains only constant values causes a compiler error if the expression produces a value that is outside the range of the destination type. If the expression contains one or more non-constant values, the compiler does not detect the overflow.

The unchecked keyword is used to suppress overflow-checking for integral-type arithmetic operations and conversions.
In an unchecked context, if an expression produces a value that is outside the range of the destination type, the overflow is not flagged.

Okay, so what the hell does this mean?
The C# compiler checks at compile time for overflow exceptions.
If you do:

int tooBig = 2147483647 + 10;

you get the error “The operation overflows at compile time in checked mode.” The problem arises when you use variables. Since a variable could be anything the compiler doesn’t check for overflows. If you do:

int ten = 10;
int tooBig = 2147483647 + ten;

your code will compile but the value of tooBig will be -2147483639. This is because default behavior of the runtime environment is to skip checking for overflows and your values just wrap.

So, what do you care?

Most likely you don’t. I’ll be honest. Chances are you’re not writing algoritms so important that if you overflow the world is going to come crashing down about you. Every once in awhile you do, however, come across some peace of critical software that may need to handle overflow exceptions. That is where the checked and unchecked operations come into play.

The problem is that checking every math operation for an overflow is slow. Okay, maybe slow is a bit much. It is, however, a couple of microseconds that you could be using on other things and it’s really slow if an overflow exception is thrown and you have to handle it. In math heavy operations and algorithms these few microseconds could add up to a lot of time so be sure that your code is critical enough that an overflow must be handled.

So, how do we fix this? We use the checked operation (in either the block or expression form).

//block
checked{
    int twenty = 10 + 10;
}
//expression
int thirty = checked(10 + 20);

This tells the compiler to check the numbers and if there is an overflow throw an overflow exception.

The opposite of the checked operator is unchecked:

//block
unchecked{
    int twenty = 10 + 10;
}
//expression
int thirty = unchecked(10 + 20);

This works just like the default behavior of not checking for overflows with variables. Since this is done automatically you probably won’t use this too often unless you start using the checked operator. The nice thing is that you can combine both checked and unchecked for the appropriate values.

unchecked
{
    int ten = 10;
    int tooBig = checked(2147483647 + ten);
    Console.WriteLine(i3);
}

yields an overflow exception being thrown since 2147483647 + ten overflows. Conversely,

checked
{
    int ten = 10;
    int tooBig = unchecked(2147483647 + ten);
    Console.WriteLine(i3);
}

results in a value of -2147483639 since the unchecked means the runtime environment to not check for overflow.

That’s all for now,
Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

Too many good movies this summer

<off_topic>

This is going to be a busy summer :)

Watchmen (sorry, couldn’t find an embedded player of this one)

</off_topic>

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

WPF XAML Data Binding Cheat Sheet

I hate posts about posts and try to avoid them. Sometimes, however, neat stuff pops up that you may have not run across before.

If you head over to Nbd-Tech and read the post on WPF XAML Data Binding Cheat Sheet you’ll find a great resource for databinding in the form of a pdf.

For some reason, though I seem to grok most of WPF, data binding often eludes me and I have to refer to sources like the cheat sheet to figure out what I’m doing.

Later,
Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

Often Unused Operators: |= (or equals)

I’ve debated before the usefulness of the | and & operators. The use of the | operator depends on the context in which it is used.

In the case of bools a boolean operation is performed. In the case of ints a bitwise OR is performed.

For boolean operations when the | operator is used both sides of the operator are evaluated. In the example below both VerifyStatus and SetDefaults are called regardless of the boolean returned by each of them.

public void TestTransaction(PaymentTransaction Transaction)
{
    if (Transaction != null &&
        (VerifyStatus(Transaction.State) | SetDefaults(Transaction)))
    {
        //do something with the code
    }
}
private bool VerifyStatus(ItemState State)
{
    if (State == null)
        return false;
    if (State.Status == Status.NotVerified)
        ValidateStatus(State);
    if (State.Status == Status.Valid)
        return true;
    //Status.Invalid
    return false;
}
private void ValidateStatus(ItemState State)
{
    //validate the status
}
private bool SetDefaults(PaymentTransaction Transaction)
{
    if (Transaction == null)
        return false;
    //no need to set the defaults if the state is already valid
    if (Transaction.State.Status == Status.Valid)
        return true;
    //set all the default values for the transaction
    return true;
}

Ok, I know it’s not a pillar of phenomenal code. But you get the point, both of the sides of the | are run. Now, what if you’ve all ready evaluated the status earlier in code? No need to do it again. But you may need to still set the defaults. Well, that is where the |= comes into play.

bool transStatus = VerifyStatus(Transaction.State);
//do something with the code
transStatus |= SetDefaults(Transaction);
if(transStatus)
{
    //do something with the code
}

In the case of an int a bitwise operation is performed.

int a = 0x0c;
a = a | 0x06;
//a results in 0x0000000e
//1100
//0110 results in
//1110 which is e

Like the logical operation example above the | and assignment can be collapsed down to:

int a = 0x0c;
a |= 0x06;

I think it’s very important to understand the difference between | and || as well as & and &&. Recently I came across a bunch of code where the original developer used | and || interchangeably. They are not the same. Using | in place of || overrides the fail fast nature of boolean operations most modern languages support. They are not interchangeable. If Transaction was null the following code would not work

if(Transaction == null | Transaction.State == null)

simply because both sides of the operation are evaluated so Transaction.State would throw a null pointer exception. Not only that but your code will run slower.

Next in this series will be checked and unchecked.

Later,
Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

Linear Operations

<rant>

We all know O(n) = O(2n), right?  I mean, we’re talking about how algorithms scale here.  Linear is linear.  I add 100 more elements to my dataset and the time to finish what ever I was doing scales linearly.

Now that’s all fine and good but think a bit when working with code. Just because O(n) = O(2n) doesn’t mean that you should just throw loops around willy-nilly when with a bit of smarter design you can do O(n) instead of O(2n).

In the real world when iterating over datasets (especially potientially large datasets in my case) there is a big difference between O(n) and O(2n).

For example:

foreach(MyObjectType myObject in myList)
{
    //do something
}
foreach(MyObjectType myObject in myList)
{
    //do something
}

I know this may be a bit of an oversimplification but lately I’ve been looking at a lot of code that basically works out to the above. It’s really more like:

MyList stuffToProcessNext = new MyList();
foreach(MyObjectType myObject in myList)
{
    //do a lot of stuff here with a bunch more loops
    //rather then write some recursion to another method to handle children
    //and siblings just add to stuffToProcessNext
    stuffToProcessNext(myObject);
}
//now that MyObjects are processed and I don't have to worry about the
//siblings I can finish processing each of the children to MyObjects
foreach(MyObjectType myObject in myList)
{
    //do a lot of stuff here with a bunch more loops
    foreach(MyObjectType childObject in myObject.Children)
    {
        //do something relating to the siblings of myObject
    }
}

But don’t just look at your own code, understand how the underlying framework code works.
For example:

//assume myList is a List
//and myObject is MyObjectType
if(myList.Contains(myObject))
    myList.Remove(myObject);

No need to call Contains and force the framework to iterate over the list twice. Just remove it. No worries if it isn’t there.

</rant>

Please return to your regulary scheduled program.

Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews

Top 25 Most Dangerous Programming Errors

Follow the below link, read it, consume it, grok it.

2009 CWE/SANS Top 25 Most Dangerous Programming Errors (If it doesn’t come up be patient. It looks like the server is getting hit pretty hard with bloggers like myself linking to it.)

Or read a summary of it and then go to the link over at Coding Horror.

On a side note, now that the holidays have calmed down I’ve been working on a series of “Often Unused Operators” like ~ and |=. Credit goes to Jeff Clark for turning me onto this. Hopefully I’ll have the first one up on Friday.

Brian

Share and Enjoy:
  • Digg
  • Facebook
  • DotNetKicks
  • Google Bookmarks
  • Live
  • HackerNews