Why I (Occasionally) Use Empty Statements
I was working on a class project this summer, and one of my classmates was questioning why I used something like this:
1: internal void Initialize()
2: {
3: ;
4: }
It's something programmers call an empty statement. He thought the lonely semicolon was odd, and seemed to think I shouldn't have it there. Well, here's what Microsoft says:
The empty statement consists of a single semicolon. It does nothing and can be used in places where a statement is required but no action needs to be performed.
Basically, while an empty statement literally does nothing in the compiled project, it does do at least two things for me:
- Indicates that this is NOT a forgotten statement, but rather one I either don't need right now or that I don't intend to implement, but left in place for consistency (maybe to match a coding pattern).
- Allows me to wire up things like event handlers that I don't have logic for, yet.
I'm not really sure where I picked this habit up from, but I think there is nothing wrong with using empty statements, even if some people think it's wasteful...
Using IEnumerable Is Better Than Returning Lists
Or so my experience lately has led me to believe. I rewrote an older application I had written (and parts of which you have seen before) to work with WPF. Part of the rewrite also involved coding to interfaces, rather than class constructs. I also had a nice opportunity to try out one of the more interesting facets of enumerations: return yield.
First, let's look at how I used to do this:
1: /// <summary>
2: /// Add a new Tutor node to the tutor file.
3: /// </summary>
4: /// <param name="tutor">Dictionary object containing relevant tutor data</param>
5: /// <returns>true if node added, false if node was not added</returns>
6: public bool AddTutor( Dictionary<string, string> tutor )
7: {
8: if ( tutor["first"] != String.Empty && tutor["last"] != String.Empty && tutor["email"] != String.Empty )
9: {
10: try
11: {
12: XDocument xd = XDocument.Load( String.Format( @"{0}\tutors.xml", PATH ) );
13: var lastnode = xd.Root.Elements( "tutor" ).LastOrDefault();
14: int temp;
15: if ( !lastnode.Equals( null ) && int.TryParse( lastnode.Attribute( "id" ).Value, out temp ) )
16: {
17: xd.Root.Add(
18: new XElement( "tutor",
19: new XAttribute( "id", temp + 1 ),
20: new XAttribute( "type", tutor["type"] ),
21: new XAttribute( "active", "true" ),
22: new XElement( "first", tutor["first"] ),
23: new XElement( "last", tutor["last"] ),
24: new XElement( "email", tutor["email"] ),
25: new XElement( "nick", tutor["nick"] )
26: )
27: );
28:
29: xd.Save( String.Format( @"{0}\tutors.xml", PATH ) );
30:
31: return true;
32:
33: }
34: return false;
35: }
36: catch ( Exception ex )
37: {
38: throw (
39: new Exception(
40: String.Format( "An error occurred. The tutor could not be saved. Details of this error:\n\n{0}", ex.Message )
41: )
42: );
43: }
44: }
45: else
46: {
47: throw ( new Exception( "Cannot add a null tutor to the datasource" ) );
48: }
49: }
It works, but it always felt pretty clunky, something that seemed to be proven out by less-than-stellar performance. When I had a chance to recode it, I made a conscious effort to think in terms of interfaces, and how to code to them.
After a few fits and starts, I wound up with this snippet in place of the earlier snippet:
1: /// <summary>
2: /// Returns an enumerated list of IMailable:MailablePerson objects, sans persons of the type specified by the <code>filter</code> parameter
3: /// </summary>
4: /// <remarks>The filter can be passed in as an empty string, if so desired, but cannot be a null object</remarks>
5: /// <param name="file">Path to the XML data file</param>
6: /// <param name="filter">A person type (role) to exclude from the list</param>
7: /// <returns>An enumerated list of IMailable:MailablePerson objects</returns>
8: internal IEnumerable<IMailable> GetMailables( string file, string filter )
9: {
10: file = String.Format( @"{0}{1}.xml", Properties.Settings.Default.PATH, file );
11: XDocument xd = XDocument.Load( file );
12:
13: // Method syntax (lambda expression)
14: var tuts = xd.Root
15: .Elements( DATA_NODE )
16: .Where( x => x.Attribute( "type" ).Value != filter );
17:
18: foreach ( var t in tuts )
19: {
20: yield return new MailablePerson(
21: t.Attribute( "id" ).Value,
22: t.Element( "first" ).Value,
23: t.Element( "last" ).Value,
24: t.Element( "email" ).Value,
25: t.Attribute( "type" ).Value,
26: false
27: );
28: }
29: // This should cover the edge case where no tutors match the filter value;
30: yield break;
31: }
Now, I don't know about you, but I will take the extra 18 lines I save in the new method any day. The new method also has the advantage of being able to be used for any XML file the matches my XML tree and will populate any object that implements my interface.
The most useful benefit of the new method comes from how and when the XML file is parsed. In the original method, extraction happens when I call the method, and I'm being given a rather bloated class type in List<> (I could have derived benefit from simply changing the return type to IList<>, but that's another discussion). By using IEnumerable, this method is actually returning a reference to what I want to call a "primed" datasource. The actual extraction occurs when something accesses the IEnumerable object returned by the method. In my case, I am loading a WPF ComboBox, so the extraction is actually postponed a bit until the constructor is fired.
Using the IEnumerable interface also lets me use the Iterator pattern. Each time through the foreach loop, I am returning one object to the calling object, and behind the scenes the runtime is calling the MoveNext() method supplied by the IEnumerable iterface. The end result seems to be a much snappier load in my application.
I'll add more stuff later, but for now, I hope you've maybe started to see why I like this "new" (to me anyway) method of coding...
Thinking About the Past...
Here's a friendly warning to y'all: this post has nothing to do with "techie" stuff. I just felt like posting something that's been rolling around in my head. Just so you know...
Anyway, I was sitting at home one day, just kind of mellow, hanging out. I got to thinking about how I had arrived at that particular moment in time. You know, what events had transpired to lead to me sitting there. Everything from, say, junior year of high school and back is pretty fuzzy, so I just kinda thought about the events I could remember. While I was doing this, I realized I had passed a major decision point in my life without ever realizing it. There was essentially one choice that decided what the next decade of my life would be like.
Coming out of high school, I had managed to complete a university prep program and was considering attending Michigan Tech for an engineering degree. Being a poor lad, it had seemed a safe bet to spend a few years at a community college, and then transfer to the big school, which would save me a LOT of tuition money. Not too difficult. A lot of students do this, and it works out just fine for them.
Once I had pretty much committed myself to staying local, it seemed smart to look for a job, since I was likely to have to pay for my tuition myself before too long. Plus all young people like having stuff, and I was no exception.
One thing I forgot to mention earlier was that part of my high school education involved attending a vocational school. So, in addition to my high school degree, I had a nice little certificate that said I was a certified C.A.D. (computer-assisted design) drafter. Back in the late 90's, this was a pretty good certification to have, since it seemed a lot of companies (at least in Michigan) were always looking to add more C.A.D. operators. That, and computers had not yet pervaded EVERYTHING, so being a bit computer savvy was a big deal.
So, after a summer spent mostly being a bump on a log, I started looking for a job. I put a resume in a few places, but wasn't really getting any nibbles. It happened that my older brother worked for Meijer (a retail chain local to the MidWest region) and was able to swing an interview for me (back then they were a bit more selective in their hiring practices. Now the only prerequisite is a pulse). So I wait for a week or two, then he tells me I have an interview a few days later.
Here is the part that triggered this little blog post:
On the day I was scheduled to go in for my interview at Meijer, I finally got a call from one of the businesses I had put a resume in at. They were interested in having me come in for an interview, maybe have me do some C.A.D. work for them.
(D'oh. This is painful just thinking about it, much less talking about it...)
Anyway. I had decided that working anywhere that might transition into full-time work was a bad idea, because I didn't want anything to keep me from transfering to Michigan Tech when I was ready. So, I politely told the nice lady on the phone that I had an interview with Meijer, and if they (Meijer) were willing to hire me, it would probably work better with my long range plans. So, being a dumbass, I declined their (the C.A.D. place) offer and went to work for Meijer.
Here's the rub: like a lot of college freshmen and sophomores, I didn't really take college seriously. I was meeting girls, hanging out, the whole stereotypical dumb-young-kid stuff. Problem is, this dumb-young-kid stuff eventually caught up to me, and I wound up dropping out.
So long, Michigan Tech...
I would go on to spend almost eleven years working at a job I grew to hate with a passion that cannot be expressed in words. I suppose part of that was knowing (maybe only subconsciously) that I could be doing something else if I had only tried harder.
Now, one of the reasons I consider this one of those "life-changing" moments is that I KNOW that I would be an entirely different person right now if I had in fact been hired at that place that was interested in C.A.D. work. See, I grew up in a small town in what could safely be called the B.F.E. (big f-ing empty), where, like, 85% of the people are of Dutch heritage and, like, 95% of the permanent residents are white. So, calling me "sheltered" would have been entirely appropriate.
Working at Meijer (and for a brief time, attending community college) introduced me to a whole host of people with ethnic and social backgrounds that I had never really experienced. You could call this "Tieson Gets a People Education." If I had worked at that shop doing C.A.D. work, I mostly would have been dealing with the kind of people I already knew. Not exactly a recipe for developing a broad world-view, no?
I can tell you for certain that working at a dead-end job for all those years definitely made it much more of a struggle to get from that wide-eyed punk who swaggered out of high school to the guy I am now, but I can't help but think that the humbling effect of being broke and struggling was necessary for me to be a better person. The friends that have come and gone, the people that I've loved in the blunted way I'm capable of, these people shaped me and made a difference in who I am. If everything had gone according to my original plan, I'd probably be better off financially, but I think I would be a lesser person.
The funny thing is that what was probably the poorest decision of my life was probably also the best thing that could have ever happened to me.
...
Serendipity. Hoo-rah. :]
A Discussion of Class
I seem to have to explain the concept of "classes" to a lot of programming students lately, so I got to thinking that a new blog post may be in order. So, if you happen to be a newbie programmer and are wondering exactly what a class is, tune in and follow along. Please ask questions at the end, too, if anything is not clear...
The Basics
"Class" is a term you'll hear thrown around a lot in any discussion of OOP, or object-oriented programming. I wrote a simple article about OOP a while ago, so if that term is new to you, follow this link and read that post first, then come back here. In a nutshell, OOP is a programming technique that seeks to create systems that can model real-world objects and the way in which we interact with them. An object has "attributes," or things that describe it, and "methods," or things it can do. Again, see my OOP article if you need something more in-depth.
Okay, so what the heck is this "class" thing anyway? Well, the analogy that most people are comfortable with seems to be "a class is like a blueprint." A class file represents the attributes and methods of an object within our system. It describes an object as it would exist in our system. When we want to manipulate that kind of object within our system, we create an "instance" of that class object. This would be similar to a contruction crew taking a blueprint for a house and actually building a home.
The Not-So-Basics
One thing that the C# language designers have talked about is that all class definitions are "types." They define type as the root classification of any object within a system. So, when you create a new class definition, you are defining your own custom "type." This makes sense if you think about how you would describe your objects to a colleague.
There are two relationships you need to be aware of when creating classes: is a and has a. Say, for instance, that you created a class called "Worker" and then created an instance called "worker1." When you describe worker1, you would say "worker1 is a Worker." Is a relationships indicate that worker1 is an object of type Worker.
Let's also assume that when you created your class that you defined a couple of attributes, say, "name," "pay rate," and "job title." We could then say that worker1 has a "name," worker1 has a "pay rate," and worker1 has a "job title." This relationhip, has a, says that our object is defined by those attributes. In other words, those attributes describe the object. For example, let's say that we wanted to represent Bob from Accounting within our system. We could say "worker1 is a Worker who has a name of Bob Smith, who has a job title of Accounting Manager, and who has a pay rate of $25.00 per hour."
Danger! Danger!
A common trap I see a lot of new programmers fall into is mistaking their class definitions (the class file) for an actual object. It is really important that a clear distinction is made between a class and an object. A class cannot be manipulated. It is nothing more than a description, like a diagram of a toad in an anatomy book. An object can be manipulated. If we stay with the same analogy, an object would be the actual toad in your dissection pan.
This seems like a good stopping point. Again, if you need anything cleared up, post your questions in the comments, or use the contact page to send me your questions. Thanks!
Fun with LINQ
Anyone who's read any amount of the content I've put on this site knows I love the C# language. It has a lot of capabilities I find really useful, like strong-typing, properties, generics, etc. I also like that C# has implemented one of the more interesting technologies Microsoft has developed recently: LINQ. LINQ stands for Language-INtegrated Query, and is a technology we can use to simplify the processing of structured data within the .NET Framework.
My favorite use of LINQ is building database applications. With LINQ, you simply build a database in MS SQL Server, connect to it in the Server Explorer window in Visual Studio, and then drag and drop your tables from the Server Explorer to a special DBML file. DBML, which stands for Database Markup Language, is used by LINQ to build classes out of your table definitions. The database column types are converted to their nearest C# equivalent. The fun comes together if you developed your database correctly using primary and foreign keys. If your tables were properly associated in the database, LINQ builds those associations into the LINQ classes it builds from the DBML file.
The LINQ classes have database connections built right into them. So, you can modify an instance of your class that was populated from the database, and then call a special LINQ function called SubmitChanges(). LINQ will process the class object and determine what attributes have actually been changed. It then builds LINQ queries to execute against the database, AND it only does that for the values that NEED to be updated. This can save you a lot of bandwidth over time.
Now, you could do this all by hand with the database tools .NET has had pretty much since the beginning. But WHY? LINQ does it just as well, and in a lot of cases BETTER, not to mention QUICKER.
LINQ also comes in handy if you want to parse a structured document, like, say, an XML file. LINQ has an entire library devoted to manipulating and creating XML documents. With a good understanding of building data structures, you can use XML and LINQ to entirely replicate the kind of functionality you get with a database.
The only major beef I have with LINQ is that you don't get something as nice as DBML for automagically transforming your XML into a class object. Which really makes sense if you think about it, since XML just defines structure, so LINQ would really have no idea what types to apply to your XML data, although it could be argued that other languages are capable of inferring data types from anonymous data.
Anyway, I think that is enough rambling for now. I should have some LINQ examples up sometime soon, hopefully before the month is out...
Cheers!
:]
Page:
12345Next
June 14, 2010
Loves me Louie