LINQ, Lambda and the Learning Curve

3. January 2010

Been away for a while working on a 107,000 hour project. It isn?t done, but I am making time to blog and do my technical mentorship, because I have come to realize that there will always be high priority projects. You have to take the time to train and mentor during those projects because of that. Now on to the show.

I know that LINQ has received a massive welcome from the community and I have to say that it is a deserved on. On the whole it is a great addition to the language. I however don?t like one part of it. Verbose LINQ. I realize that it is more SQL like and that it is perceived to  shorten the learning curve, but I disagree. Lambdas are where the true power of LINQ sit and using verbose to me seems to focus you to learn LINQ one way so that you can re-learn it another.

I am going to focus on the Lambda side of LINQ simply out of preference. Keep an eye out here for the verbose VS. lambda death match, but that is a post for another time.

Lambda statements are actually fairly simple once you break them up.

SomeList.Where(c=>c.Id == someInt);

The above is the lambda conversion of this code block

foreach (Item item in SomeList)
{
    If(item.Id == soemInt)
        SomeOtherList.Add(item);
}

Lets break down the lambda so that this is a bit more clear.

c =>

This statement is declaring that the item in the list we are looking at is going to be held in the local variable named ?c?. This is no different than naming the variable in a for each loop ?c?. You can name your lambda variables more intuitively and I would encourage you to do so. Something like this.

SomeList.Where(menuItem => MenuItem.Id == someInt);

Once the object is declared you have the ability to use all of the members of that object. That is how we are able to use the ?Id? property to check something for a Boolean property. Selecting based on some Boolean expression is the most common use for Lambdas but not the only one.

List<SubMenu> submenus = SomeList.Select(menuItem => new SubMenu() 
                                                   {
                                                         ParentMenuId = menuItem.Id 
                                                   });

In this example we have created a submenu item from all the menu items in the list. We did this through the power of LINQ to let use change the output type of the selection at will. This is very usefull when you are creating items from other items. The code block that would represent is:

List<SubMenu> SubMenus = new List<SubMenu>();

foreach(MenuItem item in SomeList)
{
    SubMenu subMenu = new SubMenu();
    subMenu.ParentMenuId = item.Id;
    SomeOtherList.Add(subMenu);
}

To me this power is amazing. I have the ability to replace entire loops with a single line. The hit to readability is a concern but lambdas lend themselves to so many applications, and are key to LINQ so it should be part of the core toolset of a developer. If you use some sense and name your lambda variables intuitively you should get a lot of great millage out of LINQ without losing your readability.

C#, C# Helpful Functions, .NET

Comments versus Well written code

16. September 2009

So the conversation started today about a guy leaving our team and needing to knowledge transfer his part of the code base to the other team members. The lead programmer on the project told him to stop working on new development and start commenting his code so that the people coming in after him would understand what he had been doing.

Personally the first thing I do when opening a code base that I am not familiar with is to press CTRL-M, CTRL-O and start looking around. ( CTRL-M, CTRL-O is the default visual studio short cut for minimize all outlining. You get to see method declarations, and that is about it.) This will collapse blocks of comments so that they are not intrusive. I never re-expand them. The idea that you need comments for understanding code to me is a big red flag for bad code. I feel well named variables are much more intuitive to learning a new code base than using comments.

I have never sat down to learn an entire code base at one sitting. I am normally working on a small part or a bug fix and need to find something that is very specific. To that end a well named class/method/property is much more helpful with you use the ?Edit->Find? code parser than having to sort through and search all the comments for the set of information that you need.

Also, I am sure that almost everyone has opened a piece of code that had a form1, or class1 class right? Those names that MS graces us with are not supposed to stay named that. Here is the way you avoid this.

Step 1: Go to add class

Step 2: DON?T CLICK OK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Step 3: Look down at the bottom of the dialog and type in something intuitive.

image

Step 4: Go drink something with an umbrella and retire to the happy place of understandable class name land.

To prove my point.

   1:  //This is a class that handles 
   2:  //calculating tax for sales in 
   3:  //several states
   4:  public class class1
   5:  {
   6:          //Calc sales total for a couple states
   7:          //AR - tax 9.5%
   8:          //NM - tax 5.5%
   9:          //TX - tax 8.5%    
  10:          public decimal calc(decimal a, string n)
  11:         {
  12:               //The quick red fox jumped over the lazy brown dog.
  13:               //The quick red fox jumped over the lazy brown dog.
  14:               //The quick red fox jumped over the lazy brown dog.
  15:               //The quick red fox jumped over the lazy brown dog.
  16:               switch(n)
  17:               {
  18:                     case "AR":
  19:                            {
  20:                                  return  a * 1.095;
  21:                             }
  22:                             break;
  23:                      case "TX":
  24:                              {
  25:                                  return a * 1.0875;
  26:                              }
  27:                              break;
  28:                      case "NM":
  29:                             {
  30:                                  return a * 1.055;
  31:                              }
  32:                              break;
  33:                }    
  34:         }
  35:  }

versus my way

   1:  public class MultiStateSalesTaxCalculator
   2:  {
   3:          public decimal ARKANSAS_STATE_SALES_TAX = 0.095;
   4:          public decimal TEXAS_STATE_SALES_TAX = 0.095;
   5:          public decimal NEW_MEXICO_STATE_SALES_TAX = 0.095;
   6:   
   7:          public decimal CalculateSalesTotalWithTaxByState(decimal SubTotal, string stateAbreveation)
   8:         {
   9:               switch(stateAbreveation)
  10:               {
  11:                     case "AR":
  12:                            {
  13:                                  return  SubTotal + ( SubTotal * ARKANSAS_STATE_SALES_TAX)  ;
  14:                             }
  15:                             break;
  16:                      case "TX":
  17:                             {
  18:                                  return SubTotal + ( SubTotal * TEXAS_STATE_SALES_TAX);
  19:                              }
  20:                              break;
  21:                      case "NM":
  22:                             {
  23:                                  return SubTotal + ( SubTotal * NEW_MEXICO_STATE_SALES_TAX);
  24:                              }
  25:                              break;
  26:                }    
  27:         }
  28:  }

C# Functions that might help pt. 1

14. September 2009

When talking to a friend of mine we had the idea to do a blog series over C# functions that might help people if they don?t know about them. This will be categorized so you can keep up on it, and it will be once a week on Mondays. First I was going to start with ?continue?. Nest ifs inside a loop cause major performance issues in most applications but there are a few ways to avoid this. The MSDN definition of continue is ?The continue statement passes control to the next iteration of the enclosing iteration statement in which it appears.? . Here is the code snippet that we are going to clean up. ?Caution the following code is not suitable for young viewers or those that are faint of heart.?

IEnumerable<ReflectionParameter> test = new List<ReflectionParameter>();

            foreach (var parameter in test)
            {
                if (parameter != null)
                {
                    parameter.MethodName = "Something";
                    if (parameter.children != null)
                    {
                        foreach (var child in parameter.children)
                        {
                            if (child.MethodName == null)
                            {
                                child.MethodName = "Something";
                            }
                        }
                    }
                }
            }

I know right? We can clean this up by inverting the first if to a continue statement.

IEnumerable<ReflectionParameter> test = new List<ReflectionParameter>();

            foreach (var parameter in test)
            {
                if (parameter == null) continue;
                parameter.MethodName = "Something";
                    if (parameter.children != null)
                    {
                        foreach (var child in parameter.children)
                        {
                            if (child.MethodName == null)
                            {
                                child.MethodName = "Something";
                            }
                        }
                     }
            }
We can still clean this up by inverting the children check to a continue statement.
IEnumerable<ReflectionParameter> test = new List<ReflectionParameter>();

            foreach (var parameter in test)
            {
                if (parameter == null) continue;
                parameter.MethodName = "Something";
                if (parameter.children == null) continue;
                foreach (var child in parameter.children)
                {
                    if (child.MethodName == null)
                    {
                        child.MethodName = "Something";
                    }
                }
            }

We can also do this to the if inside the second for each loop.

IEnumerable<ReflectionParameter> test = new List<ReflectionParameter>();

            foreach (var parameter in test)
            {
                if (parameter == null) continue;
                parameter.MethodName = "Something";
                if (parameter.children == null) continue;
                foreach (var child in parameter.children)
                {
                    if (child.MethodName != null) continue;
                    child.MethodName = "Something";
                }
            }

This is a much cleaner section of code but is not great. It still has a nested for each loop. which makes my insides scream, but we will attack that sort of nesting next week.

.NET, Productivity, C# Helpful Functions

Generics ? What you should know?

11. September 2009

I have had some interesting conversations over the last week or so about generics. It was brought up out of a MCTS study group and then in the internal DNUG that I lead. so let me break it down.

Without Generics -

I have to setup collections of objects manual and for each type that I want to use. To add, sort, filter, or aggregate this collection takes a lot of code and time. Some things like ArrayList return objects which means all that casting or reflection over head to get into the objects I need.

With Generics -

I have to setup a collection and give it the input types. It handles sorting, filtering, adding, and aggregates through the use of generic Action<T>, Func<T>, or Predicate<T>. I can write sorts and filters and make them generic so that I don?t have to copy/paste change type.

Generics are not the end all and be all but they help a great deal when you are trying not to repeat yourself. I have found that when using generics that the compiler actually spits out the methods with the implemented types in them, which means that generics while great are syntactic sugar, and I have a sweet tooth.

With Linq being based on the use of IEnumerable<T> and the new parallel extensions to .NET 4.0 being able to spread the workload of Action<T> and Task<T> across multiple processors I would tell everyone. Start learning generics. It is easy to use once you wrap your head around it. Like if I wanted to add two numbers of different types I could write this:

public float Add(int one, decimal two)
{
       float item = new float();
       item = float.Parse(one.ToString()) + float.Parse(two.ToString());
       return item;
}

public float Add(decimal one, decimal two)
{
       float item = new float();
       item = float.Parse(one.ToString()) + float.Parse(two.ToString());
       return item;
}

public float Add(int one, int two)
{
       float item = new float();
       item = float.Parse(one.ToString()) + float.Parse(two.ToString());
       return item;
}

public float Add(double one, double two)
{
       float item = new float();
       item = float.Parse(one.ToString()) + float.Parse(two.ToString());
       return item;
}

public float Add(int one, double two)
{
       float item = new float();
       item = float.Parse(one.ToString()) + float.Parse(two.ToString());
       return item;
}

public float Add(double one, decimal two)
{
       float item = new float();
       item = float.Parse(one.ToString()) + float.Parse(two.ToString());
       return item;
}

or I could write this:

public float Add<T, T2>(T one, T2 two)
{
      return float.Parse(one.ToString()) + float.Parse(two.ToString());
}

Which would you prefer?

 

Enjoy, and remember.

Code Like you have to support it.

SQL Server Reporting Services ? Ad Hoc integrated with ASP.NET

10. September 2009

So I ran into a couple of different issues when setting up advanced reporting scenarios with reporting services. While reporting services runs fairly well in the server report situations but lacks flexibility in application integration scenarios. Having to hard code datasets for each report and hard code fill and get methods seemed to lack flair to me. I wanted a more robust and elegant solution. So I came up with an idea that allowed me to take preset report segments and load them dynamically into a report definition before passing it to the renderer.

You start by setting up a blank RDLC with header and footer. This allows you to keep formatting the same through the report. You can use global variables or parameters in the header and the footers. Most of the time this will be standard for the application and template for the company.

You load the RDLC from a file stream into a XDocument.

private Stream Load_FileStream()

{

Stream MasterReport =  
new FileStream(Server.MapPath("~/Report/Master.rdlc"),FileMode.Open,FileAccess.Read);

return MasterReport;

}

Using LINQ you can search the nodes for the report items node in the body. This is where the guts of the report is stored.

private Stream PrepReport()

{
XDocument ReportDoc = XDocument.Load(XmlReader.Create(Load_FileStream()));
IEnumerable<XNode> hold = ReportDoc.DescendantNodes().InDocumentOrder();
XElement BodyItems = 
(XElement) hold.Where(n =>
                           n.GetType() != typeof (XText) && 
                           ((XElement) n).Parent != null &&
                           ((XElement) n).Name.LocalName.ToUpper() == "REPORTITEMS" &&
                           ((XElement) n).Parent.Name.LocalName.ToUpper() == "BODY").SingleOrDefault();
            BodyItems.Add(NewNodes(ReportDoc.Root.Name.Namespace));
return CreateMemoryStream(ReportDoc);
}

You can then use LINQ to XML to insert a new node package to add tables, sub-reports, or graphs. In this example I add a sub-report with a parameter passed to it.

 

private XElement NewNodes(XNamespace @namespace)

{
    var holder = new XElement(@namespace + "Subreport",
     new object[] {
     new XAttribute("Name", "Subreport1"),
     new XElement(@namespace + "Parameters",
     new XElement(@namespace + "Parameter",
     new object[]{
          new XElement(@namespace + "Value","=Parameter!Period.Value"),
          new XAttribute("Name", "Period")
 })),
new XElement(@namespace + "ReportName", "NameHere"),
new XElement(@namespace + "Top", "0.25in"),
new XElement(@namespace + "Width", "7.25in"),
new XElement(@namespace + "Left", "0.125in"),
new XElement(@namespace + "Height", "0.25in")
 });
return holder;
}

The width value will change for the orientation of the paper, and the top will change based on how many reports you insert. The height is set to a quarter inch because sub-reports auto expand to the content in them. All that is left now is to send the Report the a memory stream and into the renderer.

private Stream CreateMemoryStream(XDocument doc)
{
         MemoryStream memStream = new MemoryStream();
         XmlWriter writer = XmlWriter.Create(memStream);
         if (writer != null)
        {
                doc.Save(writer);
                writer.Close();
         }
         memStream.Position = 0;
         return memStream;
} 

This will package the report file into a memory stream and return it. Make sure you reset the position or the read will start at the end and give an invalid RDLC error. Once packaged you provide the UI to this the same way you would with a static report in an application. The example here is ASP.net.

That will provide the basis for an ad-hoc report even if your own unique twist on a private report integration.

 

Happy coding, and remember to code like you have to support it.

The full code sample looks like this.

   1:  private void GenerateReport()
   2:  {
   3:              ReportViewer1.LocalReport.LoadReportDefinition(PrepReport());
   4:              ReportViewer1.LocalReport.DisplayName = "Set what you want the export file name to be.";
   5:              ReportViewer1.LocalReport.LoadSubreportDefinition("SubReport",
   6:                                                                new FileStream(Server.MapPath("~/Report/Subreport.rdlc"),
   7:                                                                               FileMode.Open, FileAccess.Read));
   8:              ReportViewer1.ReportError += ReportError;
   9:              ReportViewer1.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing;
  10:              ReportViewer1.LocalReport.Refresh();
  11:              ReportViewer1.ZoomMode = ZoomMode.PageWidth;
  12:              ReportViewer1.Focus();
  13:  }
  14:  private void LocalReport_SubreportProcessing(object sender,
  15:                                                       Microsoft.Reporting.WebForms.SubreportProcessingEventArgs e)
  16:  {
  17:  //This is where you provide the data sources for you subreports.
  18:              e.DataSources.Add(new ReportDataSource("Something", "MethodCallHere"));
  19:  }
  20:   
  21:  private void ReportError(object sender, Microsoft.Reporting.WebForms.ReportErrorEventArgs e)
  22:  {
  23:  //Error Handling and Report Logging here
  24:  }
  25:   
  26:  public class _Default : System.Web.UI.Page
  27:  {
  28:              protected void Page_Load(object sender, EventArgs e)
  29:              {
  30:              }
  31:   
  32:              private Stream Load_FileStream()
  33:              {
  34:                  var MasterReport = new FileStream(Server.MapPath("~/Report/Master.rdlc"), FileMode.Open,                             
                                               FileAccess.Read);
  35:                  return MasterReport;
  36:              }
  37:   
  38:              private Stream PrepReport()
  39:              {
  40:                  XDocument ReportDoc = XDocument.Load(XmlReader.Create(Load_FileStream()));
  41:                  IEnumerable<XNode> hold = ReportDoc.DescendantNodes().InDocumentOrder();
  42:                  var BodyItems = (XElement) hold.Where(
  43:                                                 n =>
  44:                                                 n.GetType() != typeof (XText) &&
  45:                                                 ((XElement) n).Parent != null &&
  46:                                                 ((XElement) n).Name.LocalName.ToUpper() == "REPORTITEMS" &&
  47:                                                 ((XElement) n).Parent.Name.LocalName.ToUpper() == "BODY").SingleOrDefault
  48:                                                 ();
  49:                  BodyItems.Add(NewNodes(ReportDoc.Root.Name.Namespace));
  50:                  return CreateMemoryStream(ReportDoc);
  51:              }
  52:   
  53:              private XElement NewNodes(XNamespace @namespace)
  54:              {
  55:                  var holder = new XElement(@namespace + "Subreport",
  56:                                            new object[]
  57:   
  58:                                                {
  59:                                                    new XAttribute("Name", "Subreport1"),
  60:                                                    new XElement(@namespace + "Parameters",
  61:                                                                 new XElement(@namespace + "Parameter",
  62:                                                                              new object[]{
  63:                                                                                      new XElement(@namespace + "Value",
  64:                                                                                                   "=Parameter!Period.Value")
  65:                                                                                      , new XAttribute("Name", "Period")
  66:                                                                                  })),
  67:                                                    new XElement(@namespace + "ReportName", "NameHere"),
  68:                                                    new XElement(@namespace + "Top", "0.25in"),
  69:                                                    new XElement(@namespace + "Width", "7.25in"),
  70:                                                    new XElement(@namespace + "Left", "0.125in"),
  71:                                                    new XElement(@namespace + "Height", "0.25in")
  72:                                                });
  73:   
  74:                  return holder;
  75:              }
  76:   
  77:              private Stream CreateMemoryStream(XDocument doc)
  78:              {
  79:                  var memStream = new MemoryStream();
  80:                  XmlWriter writer = XmlWriter.Create(memStream);
  81:                  if (writer != null)
  82:                  {
  83:                      doc.Save(writer);
  84:                      writer.Close();
  85:                  }
  86:                  memStream.Position = 0;
  87:                  return memStream;
  88:              }
  89:   
  90:              private void GenerateReport()
  91:              {
  92:                  ReportViewer1.LocalReport.LoadReportDefinition(PrepReport());
  93:                  ReportViewer1.LocalReport.DisplayName = "Set what you want the export file name to be.";
  94:                  ReportViewer1.LocalReport.LoadSubreportDefinition("SubReport",
  95:                                                                    new FileStream(
  96:                                                                        Server.MapPath("~/Report/Subreport.rdlc"),
  97:                                                                        FileMode.Open, FileAccess.Read));
  98:                  ReportViewer1.ReportError += ReportError;
  99:                  ReportViewer1.LocalReport.SubreportProcessing += LocalReport_SubreportProcessing;
 100:                  ReportViewer1.LocalReport.Refresh();
 101:                  ReportViewer1.ZoomMode = ZoomMode.PageWidth;
 102:                  ReportViewer1.Focus();
 103:              }
 104:   
 105:              private void LocalReport_SubreportProcessing(object sender,
 106:                                                           Microsoft.Reporting.WebForms.SubreportProcessingEventArgs e)
 107:              {
 108:                   //This is where you provide the data sources for you subreports.
 109:                  e.DataSources.Add(new ReportDataSource("Something", "MethodCallHere"));
 110:              }
 111:   
 112:              private void ReportError(object sender, Microsoft.Reporting.WebForms.ReportErrorEventArgs e)
 113:              {
 114:                     //Error Handling and Report Logging here
 115:              }
 116:  }


Reporting

Tyson Development Conference 09 - Setup

10. September 2009

This past week has been less focused on code for me and more focused on getting stuff setup for the TDC09.
If you are not familiar with the TDC09 let me explain. Tyson Development Conference 2009 is a pet project of mine. I programmer for Tyson and had the idea with a couple friends at work that an internal version of TechEd would help Tyson IS overall. So I took it to the powers that be. They were all sorts of behind it, and now I am organizing it. It has turned into a lot of fun. I am getting to meet people I have never seen, and talk with groups like Microsoft and INETA for the speakers. So far it is 8 tracks, 6 sessions per track and filled with great stuff.
That has been most of my free (not at work) time as of late. Hopefully next weeks blog will be more Code based as I am having tons of fun with Dynamic report engines.
See you next week.

Community

Test Driven Development ? Not for the faint of heart.

10. September 2009

I started coding in C# about a year ago and almost immediately found that once I had completed a project I wanted to go back and streamline and improve it. When time allowed I started trying to do this and found that the code was very hard to verify functionality. I also found that some of my design choices were pretty novice, due to that the code was very hard to enhance. 
I got introduced to the idea of test driven development by a good friend Rob Tennyson. He presented on the topic at the Tyson Foods internal .NET user group. This peaked my interest for two reasons. One, It would allow for avoiding the novice mistakes in design and class layout. Two, it would allow for my code to have automated verification of functionality.
I set out to work TDD into my everyday process and hit several brick walls.
1. You end up making things public for testing that should not be otherwise, or putting test code into the finished product (neither is a workable solution in my book). I am using NUnit and I didn't want to have a reference to a testing package in my production code. Adding a dependency to the production code that other developers will have to deal with was not my idea of a stable codebase.
2. Being a beginner in TDD as well as C# I didn't know what I didn't know so by that lack of code and language knowledge I repeated some novice mistakes in design. Not as many as before but still a few. Some would argue that I gained knowledge and that is why I see those bottlenecks and design issues more clearly and to that my only reply is "yeah prolly".
3. Abstraction is a premium but sometimes too much work. I write a lot of small applications, an editor here, a website there. While I do work to abstract a lot of my code and provide interfaces in the right places for a small application putting in the level of seams needed for proper TDD would be building an elevator in an outhouse.
4. I found it increasingly difficult to find answers in my hunt for TDD utopia. I read several books on the subject and found that I was more often than not provided with contradictory rules to apply, or methods to use. Microsoft's "Test-Driven Development in Microsoft .NET" by James W. Newkirk and Alexei A. Vorontsov gave great baseline examples and presented the basics of TDD very well, however it fails to provide good solid base for TDD in the real world. The application that they base a lot of their examples around ignores some fairly large aspects of the TDD mindset like separation of integration testing and design testing.

With the miles behind me and a TDD utopia still nowhere in sight I have found several good ideas.

1. Kent Beck's TDD by Example is a great resource for TDD on the intermediate to advanced level.

2. Not everything needs to be designed using TDD, some things are just too trivial.

3. TDD is a design pattern, and it should be used as such. If you want automated testing use automated tests, but if you want TDD programs before one line of code is written have a test list and priority assigned to them.

I am working on a TDD project currently with Jay Smith and Rob Tennyson to write a checkers application using only TDD and having no UI or Data Layer. Building Logic first, then the UI, and finally adding a data layer to detail how to handle those real world integration concerns.

Just Remember Code like you have to support it.

C#, .NET, Productivity, Unit Testing, Design Patterns

Batch File and Command File running in Visual Studio

10. September 2009

So I know there are probably places to find this out there but I wanted to throw this out there because I had a hard time finding it.

Batch files are used for a lot of things for deployments and normally you would have to some these from the window explorer instead of in VS. I say why leave VS if you don?t have to?

Go to Tools ? > External Tools

image

This will open a new dialog that you will have some items in or not.

image

Hit Add and type in the name you want it to appear on your right click menu as, Navigate to or type in the path to cmd.exe, and type /K to the Arguments then with the cursor still in arguments click the arrow to the right and select Item Path. Click the arrow to the right of Initial Directory and select Item Directory. Make sure to click the ?Use Output window? option. Your finished dialog should look something like the above picture. Hit apply and OK.

Remember the count of the new item as it will be needed later. For my example this would be 6.

 

Then to put this on your right click menu. Right click the grey space near a toolbar to get the toolbar customize menu and click customize.

image

This should open a new dialog like the one below.

image

 

Click Context Menus. This will add a bar to the toolbar temporarily. Go to the Commands tab on the dialog and scroll down to tools. In the pain to the right select the External Tool with the number that you wrote down / remembered from earlier. For me this was 6.

image

Click and Drag the External Command you selected to the toolbar that was added. It needs to go under Project and Solution Context Menus, and then under Item. the position under item is just preference on where you want it in the right click menu.

image

The name will not be External Command #, it will replace that with the name you typed in.

 

Then when you have a batch file you can right click it, and choose your new option and it will run it, but output into the output window of Visual Studio without having to leave the IDE.

 

Enjoy.

Visual Studio 2008, Productivity