Thursday, September 13, 2012

LINQ Extension Methods Cheat Sheet

LINQ Extension Methods are great. Here's a cheat sheet of the common ones:


Filter

Takes a larger set down to a smaller set

First
  • customers.First(c => c.LastName == "Anderson")
    The first customer with a last name of Anderson
Last
  • customers.Last(c => c.LastName == "Anderson")
    The last customer with a last name of Anderson
Single
  • customers.Single(c => c.Id == 456)
    The only customer with an ID of 456
Where
  • customers.Where(c => c.Active == true)
    All customers that are Active
FirstOrDefault
  • customers.FirstOrDefault(c => c.LastName == "Anderson")
    The first customer with a last name of Anderson or null if there isn't one
LastOrDefault
  • customers.LastOrDefault(c => c.LastName == "Anderson")
    The last customer with a last name of Anderson or null if there isn't one
SingleOrDefault
  • customers.SingleOrDefault(c => c.Id = 999)
    The only customer with an ID of 999 or null if there isn't one

Sort

Returns a copy of a set but in a different order

OrderBy
  • customers.OrderBy(c => c.LastName)
    Returns the customers sorted alphabetically by last name
OrderByDescending
  • customers.OrderByDescending(c => c.LastOrderDate)
    Returns the customers sorted by the date they last placed an order (most recent first)
ThenBy (must be done after OrderBy or OrderByDescending)
  • customers.OrderBy(c => c.LastName).ThenBy(c => c.FirstName)
    Returns the customers sorted first by last name then by first name
ThenByDescending (must be done after OrderBy or OrderByDescending)
  • customers.Order(c => c.Category).ThenByDescending(c => c.LastOrderDate)
    Returns the customers sorted first by category then by the date they last placed an order (most recent first)

Conditional

Answers a yes/no question based on a set

All
  • customers.All(c => c.Active == true)
    Is every customer in the set active?
Any
  • customers.Any(c => c.LastOrderDate > DateTime.Now.AddDays(-7))
    Did any customer in the set make an order in the past 7 days?

Projection

Transforms a set of objects in one form to a set of objects in another form

Select
  • IEnumerable<string> names = customers.Select(c => c.FirstName)
    Select the first name of every customer (transform each Customer object to a string object)

Extension methods always return a COPY:

  • IEnumerable<Customer> sorted = customers.OrderBy(c => c.LastName)

Friday, August 3, 2012

.NET LINQ and Lambdas Step by Step

LINQ is powerful, really powerful, can make code more readable, and can help you write code faster. However, LINQ has a syntax hurdle, lambda expressions. Lambdas are one of those constructs that trips up developers new to .NET. Luckily, there's a large return on the investment of learning them. So, let's learn how they work step by step.

Consider it without any of the LINQ/lambda mumbo jumbo:
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    foreach (int x in numbers)
    {
        if (x < 0)
        {
            result = true;
            break;
        }
    }
    return result;
}
Now, let's factor out a method and call it IsNegative:
bool IsNegative(int x)
{
    return x < 0;
}
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    foreach (int x in numbers)
    {
        if (IsNegative(x))
        {
            result = true;
            break;
        }
    }
    return result;
}
The code above works great. However, there's a lot of it, thus more opportunity for bugs. Not only that, but it is a common algorithm to determine if any element in an array satisfies a certain condition (in this case, whether any element is negative). Surely there's a way to make the code simpler and more readable. There is. This is where LINQ shines! Let's use LINQ, but no Lambdas yet:
bool IsNegative(int x)
{
    return x < 0;
}
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    result = numbers.Any(IsNegative);
    return result
}
We are calling a LINQ method called Any. The Any method takes a single argument which is yet another method (in our case, the IsNegative method). That method must take a single int argument (because the array contains only integers) and return a bool. The functionality of Any is to return true if any element in the array matches the specified condition (in our case, if the number is negative).

Ok great, we simplified the code and reduced the chance for bugs to sneak in. However, the IsNegative method may not need to be used by anyone other than the IsAnythingNegative method. In this case, it is just overhead to have to define a separate IsNegative method, and it fragments the code. So, let's accomplish the same thing with an anonymous method defined in-line.
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    result = numbers.Any
    (
        (int x) =>        // anonymous method takes a single argument
        {
            return x < 0; // method body is a single statement
        }
    );
    return result
}
Don't freak out yet, this is just syntax. We are defining an anonymous method which takes a single int argument named x. The method body consists of a single statement: return x < 0;. And thus, the method returns bool. This anonymous method is just like IsNegative. Guess what, you just wrote a lambda expression!

Ok, x must be int since numbers only contains int, so let's remove that redundancy:
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    result = numbers.Any
    (
        (x) =>            // int can go away
        {
            return x < 0;
        }
    );
    return result
}
.NET provides a shortcut for lambdas which take a single argument and return a single result:
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    result = numbers.Any
    (
        x =>              // () can go away
                          // {} can go away
            x < 0         // return can go away and ; can go away
    );
    return result
}
Whitespaces removed:
bool IsAnythingNegative(int[] numbers)
{
    bool result = false;
    result = numbers.Any(x => x < 0);
    return result
}
And now, we finally arrived at the all-too-confusing lambda expression => < ( > % #(*^!^$%$%#@**($ syntax.

Here are some other fun methods to play with:
bool areAllEven = numbers.All(x => x % 2 == 0);
int[] justTheNegatives = numbers.Where(x => x < 0).ToArray();
Hopefully this helps ease you into the new syntax.

Monday, June 11, 2012

Choose to Want

How many times have you heard the phrase "I have to..." or "They made me..." or "I had no choice...". Did you really "have" to? Did they really "make" you? Did you truly have "no choice"? Anytime you have a choice (which is almost always), you don't have to choose a particular option, and no one can make you choose that option. The option you choose is the one you want.

For example, you work at a place you dislike. Some morning, you may be tempted to say "I have to go to work today." Well, that's not really true. You have other options. You could choose to not go to work that day. You could choose to never go to work there ever again. There are plenty of humans out there that choose that option. What makes you different than them? There would be ramifications for sure. You may want to explain the situation to your employer; you may want to find a new job; you may lose your house and/or your family. You could choose to live in a box and eat dog food. The point is that you choose to go to work because you want that more than you want all the alternatives .. when you consider all the factors.

Humans rarely make other humans do anything. A man points a gun at your head and says "Give me your wallet." You give him your wallet because you want to more than you want a bullet hole in your skull. He is not making you give him your wallet unless he pins you down and forcefully takes it from you. Your boss (or spouse) makes you do something? Not likely, unless he/she is physically forcing your body to do it. And at that point, he/she is the one doing it, not you

There are certain situations in which you must do something. But these are situations in which there is truly no choice. Your body must die. You must obey the laws of physics. You can't choose an alternative in these situations (unless of course you are a superhero).

If you want to choose a happy life, think of the situations you encounter as opportunities to evaluate your choices (even the not-so-obvious ones) and go with what you want. If you think you can make someone do what you want, guess again. All you can do is provide more information to that person and hope that it motivates them to want what you want. Embrace life and be happy that you have so many choices.

Monday, May 21, 2012

Project Leadership

We've all heard the term project management. But how about project leadership?
Project management is often solely that, management. It's concerned with tracking, measuring, and reporting on progress. It answers questions like "how much work has been completed", "how much work is left according to original project scope", and "how fast is work getting done". Put another way, examining the past. Hopefully these activities are performed with the goal to better predict the future.
This kind of past-oriented project management may work great when the work you did in the past is very similar to the work you will do in the future. But when is the last time you built the same software solution twice? Hopefully never. That's one of the benefits of software. Once it's built it can be reused and installed over and over.
So, in software, a past-oriented project management approach produces a team of victims. The team believes it has no control over its destiny, the release date, the project scope, or its velocity. They will meander along and will be done when they're done or will be forced to cut scope or quality when it comes to crunch time.
Sure there's value in past experiences, but only when you learn from and improve upon it. I'm not talking about things like estimates vs actuals at the agonizing detail of each individual's hours. Perhaps there are folks out there that have experienced those metrics being worth the effort to track, but I haven't. I'm talking more about the team dynamics. Did the team enjoy working on the project? Was the customer thrilled with what was delivered? Exploring those kind of subjective questions is what will improve a team's health and future project successes.
Now about the future. Stop being victims of the past. Look to the future, share a vision and a plan of the project. Ask yourself and others how the project should go. Have a plan for if (and likely when) the unexpected happens. Be proactive in providing options and recommendations. Do you add resources? How long will it take for those additional resources to ramp up? Do you carve out scope? Is there a way to work faster? Do you push the date? Don't fall into the blame game or run away from issues. Be honest. Practice project leadership.

Tuesday, April 10, 2012

It's all for humans

Ask yourself, who or what is going to use the code I'm about to write.

  1. You're building a UI:
    "A human" you answer. Certainly, that's the whole point of a UI.
  2. You're building a service or API:
    "Other applications / systems" you answer. Directly, yes. But who's using that application / system? "Yet another application" you answer. OK, but who's using that one? "A developer" you answer, or "The sales group", or "A website visitor". What do all these "users" have in common? All humans.
  3. You are fixing a bug deep inside some nasty code:
    "This stinks, I hate fixing bugs" you answer. Well hopefully you're making the code better to help out the next human (programmer) that visits that code, not to mention the human asking for the code to be fixed. 
Software is cool, but what makes it cool is its usefulness to human beings. Without being useful to humans, it is software for software's sake which is vanity.

Saturday, April 7, 2012

Post 1

Well, here it is, blog post number one. I never thought I'd have one, but I keep finding myself subjecting those I work with to tangent after tangent of barely-related thoughts that come flooding out of my brain. I also couldn't resist once I saw clayanderson.blogspot.com was available.

My name is Clay Anderson, I am a software guy who is working to become a people guy. I find software to be an incredible field. There's seldom a definitive "right" or "wrong" solution to any given problem. That is what makes software development an art more than science. However, figuring out people is an even larger problem and one that has even less "rights" and "wrongs". Every individual has different motivations and strengths. It is those differences that I find intriguing and challenging.

My goal is that the content that makes its way out of my brain and into cyberspace is useful and relevant.