I am about to show just how much of an amateur I am. The lightbulb has finally come on in my head regarding the value of object-oriented programming. It has taken awhile for it to sink in, and I most certainly don't have it all figured out yet, but I thought I would share some of the epiphanies I've had about it and how it's making my life as a programmer much easier.
I have been reading about object-oriented programming off and on for at least a year now, believing that it must be very important, but somehow was just not getting the concept. I can't tell you how many different explanations I read of what a class is. Enough that I could regurgitate a pretty acceptable explanation of them. Here's an example regurgitation:
Let's say that the concept of a car is a class. Let's also say that the concept of a compact might be a class that inherits from the car class. Likewise, the concept of a luxury sedan might be another class that inherits from the car class. My old, dirty-white, 2000 Nissan Altima in the garage downstairs is an instance of the compact class. It's definitely not an instance of the luxury sedan class. But it's an actual object. It's not the class. It's an "instance" of the class. Bottom-line, a class is a blueprint for an object.
A lot of articles and books that I read describe objects and classes just that way, and while I was hearing the words and could repeat them around the water cooler, I just wasn't getting it and couldn't see how it would help me as a programmer. Thankfully, I am starting to get it now. Here's how object-oriented programming is benefiting me.
Keeping It Simple
I am not good at multi-tasking. I can do it, but I hate it. My stress level increases, I make mistakes, and things fall through the cracks. The more details I have to manage at one time in any facet of my life, the poorer my performance. This is one of the reasons why object-oriented programming is saving my sanity. At my job, the problems we are trying to solve and the programs we are writing to solve them are considerably more complex than ones I have previously tackled. To successfully conquer big problems in programming, I am learning that the secret is in being able to break it down into smaller pieces and tackle each part individually. This sounds simple, but actually doing it, for me, is a skill I am getting better at only with practice.
I'll take an example from my real life. Cooking. I hate to cook. I hate the complexity of trying to prepare a full meal with several sides and get it all on the table, hot, at the same time. It makes me nuts. This is probably why I almost never do it. There's too much going on at once, and I almost always end up burning something.
The same thing was happening to me with my programming. Invariably, because we were iterating on our project and re-writing code, I had to be able to look back through code I had written weeks ago, regain an understanding of how it worked (because I had forgotten) so that I could make changes without breaking everything. Reading through hundreds of lines of code, for me, can quickly become overwhelming, even code that I have written. And yes, I do write comments in my code, but that alone is not enough for me. I need to be able to compartmentalize concepts, organize it, make it mentally-manageable. Object-orientation gives you a solid way to do this.
Going back to my cooking, it would be great, for example, if I could write a method (function, subroutine, whatever you want to call it) to heat food. The heatFood() method would accept two parameters - a food object and a desired temperature. Now, when I am writing the heatFood() method, I put all my concentration on solving the problem of how to heat food. I am not thinking about how to season food, mix ingredients, or any of the other myriad kitchen tasks involved in preparing a meal. I have isolated one logical piece of the process, broken it off as a problem of it's own - a simpler problem that is easier to solve. By doing this and focusing in on the smaller problem, I can concentrate better and not get overwhelmed with all the other details.
There are enough details, anyway, involved in just heating food. I might need to include logic that determines if the food object would be better heated in an oven, a microwave, or a toaster. I could include logic to determine how long the food will have to be heated to reach the desired temperature and how I will know when I have gotten there. Depending on the type of food, it may need a thermometer stuck in it. You get the idea. Now, let's say I get my heatFood() method working beautifully. When it's done, I am done with it. I can forget about it and move on to solve other problems. Later, when I need to heat food in my program, I don't have to think again about the specifics of how that is done. I just call my heatFood() method, and I get back heated food. Object-oriented programmers call this encapsulation.
Creating a Class
Now, in .NET, I can take this heatFood() method and make it part of a class. Let's call it the "FoodHeater" class. I am actually going to walk through the steps here of how this is done in Visual Studio 2008 Professional, because I didn't really find a lot of explanations online. I think the programmers who write about this stuff just assume it's obvious, but it wasn't to me. It actually took awhile for me to get this down. By the way, if you are like me, the first time you do this, you'll probably think, um...why? I found that, the more I did it, the more it made
sense. Once you have classes to use, you start to use them and find out how useful they are. If you are wondering whether you really need to start using object-oriented design, I guess my advice would be this. If you aren't overwhelmed by your own code, then maybe not, but if you are feeling overwhelmed because you code is getting immense and ummanageable and if you aren't organizing your code with objects yet, try it.
Ok, here we go.
So, assume I've got my basic ASP.NET website started in Visual Studio. The first thing I want is an App_Code folder to keep all my classes in. To get this, right click on the root of your project in the Solution Explorer, hover over "Add ASP.NET Folder" and choose "App_Code" in the sub-menu that pops up (see picture just above and to the right). Now, right click on the new App_Code folder and choose "Add New Item...". In the screen that pops up, choose "Class" and give your class a meaningful name. In my example here, I am going to call it "FoodHeater.cs" (see picture below). Later, I will be using the name "FoodHeater" to use this class in my program .
Writing Code for Your Class
There are a lot of things that you can do in a class. I am just going to show you a couple of things to get you started. If you get your foot in the pool and like it, you can explore online for more about it. Who knows, I may do more articles about this stuff, cause I think it's cool.
Ok, first of all, we know that this class is going to contain our heatFood() method. So, I'll go ahead and put that in. Wait, no I won't. Remember that I said I wanted my heatFood() method to accept a food object and return it when it was heated. Ok, well, I guess I need a food object. Let's make one. Here's the simplest class you will ever see. I am actually going to include it in my FoodHeater.cs file.
public class FoodObject
{
public string FoodName { get; set; }
public bool FoodHot { get; set; }
}
So, this class has two public "properties". If you are used to doing any code-behind at all in ASP.NET, the concept of properties may already be familiar to you. For example, you've used a property before if you have ever put an <asp:Label> control on your page and then set the value programmatically from code-behind like this:
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "Some new text for the label.";
}
Text is a property of the Label class. In the case of my FoodObject class that I created, I am creating FoodName and FoodHot properties that I may want to access later either to assign values to them or get values from them. That's why I've got "get;" and "set;" in brackets. By the way, there's an easy way to create new properties in your class using Visual Studio. Just type in the word "prop" and hit your Tab key twice. Go ahead try it.
Ok, let's get back to our FoodHeater class. Visual Studio has already given us a start on it when we created the FoodHeater.cs file. Now, I am ready to add my heatFood() method:
// methods
public FoodObject heatFood(FoodObject fo, double desiredTemp)
{
// TODO: write the code to do all the stuff required to heat my FoodObject "fo"
return fo;
}
Let's look at the first line of the method where it is defined. The keyword "public" makes this method available from anywhere in my application. The very next word "FoodObject" indicates the type of object that will be returned by this method. In this case, as we've already said, the method will return an "instance" of my FoodObject class we defined earlier. Then I have the name of the method "heatFood", followed by the parameters that the method requires. When the method is done with the passed in FoodObject "fo", it returns it back to the code that called the method.
I'm going to clean up my using statements at the top of the FoodHeater.cs file by right clicking them, choosing "Organize Usings", and then "Remove Unused Usings". Notice that they are all removed because I wasn't using any of them. You shouldn't do this until you are actually done writing your class, but it's a nice way to clean up your code when you are done. Here's the final FoodHeater.cs file:
/// <summary>
/// Summary description for FoodHeater
/// </summary>
public class FoodHeater
{
public FoodHeater()
{
//
// TODO: Add constructor logic here
//
}
// methods
public FoodObject heatFood(FoodObject fo, double desiredTemp)
{
// TODO: write the code to do all the stuff required to heat my FoodObject "fo"
return fo;
}
}
public class FoodObject
{
public string FoodName { get; set; }
public bool FoodHot { get; set; }
}
Ok, now just imagine with me that we wrote brilliant code to handle all the complexities of heating food and put all that in our heatFood() method. Now, we are done with that. We close this file and forget about it.
Let's go to our default.aspx page and use our new FoodHeater and FoodObject classes.
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
FoodObject meatLoaf = new FoodObject();
if (meatLoaf.FoodHot == false)
{
FoodHeater myHeater = new FoodHeater();
double desiredTemp = 350.0F;
meatLoaf = myHeater.heatFood(meatLoaf, desiredTemp);
}
}
</script>
See what we're doing? Granted, you probably wouldn't use the Page_Load event. I am just using it because it's pretty universal. Anyway, we're "instantiating" meatLoaf as a FoodObject. Then we are using our "FoodHot" boolean property that we created in the FoodObject class to test if the food is hot. If it's not, then we need to heat it, right? So, here comes our cool new FoodHeater class and the heatFood() method. To use the heatFood method, we need to instantiate the FoodHeater class first. That's "myHeater". Then we use our heater to heat the meatLoaf to 350 degrees. When the heatFood() method is done, it will return the heated FoodObject, so we assign the returned value back to meatLoaf.
Reusing Code
Now, let's say that you have a completely different project or website a few months later that needs to be able to heat food. You remember that you wrote this wonderful FoodHeater class for this project. Because you broke the problem down into smaller parts and wrote encapsulated code for each part, you now have this nifty FoodHeater class that you can reuse! All you do is go get your FoodHeater.cs file from the previous project, copy it into your App_Code folder in your new project, and use the class.
Better Intellisense
One of my favorite things about Visual Studio is the intellisense. You type in the name of an object, hit your period, and instantly you have a list of all the legal properties and methods of that object for you to choose from. It saves you from having to remember everything about everything. When you create your own custom classes, Visual Studio will do the same things for those. In the example default.aspx code-behind above, when I typed meatLoaf, Visual Studio new that it was an instance of the FoodObject class, so it got a list of valid properties for that class, and when I typed a period, I saw "FoodHot" and "FoodName" in that list (see picture at right). Again, once I get done with the creation of my class, I can forget about it. Visual Studio is going to help me remember the pertinent details with mental cues like this when it comes time to use the class.
Painless Refactoring
Ok, that's probably an exaggeration, but refactoring has become considerably less painful with my code that I have organized into well-encapsulated objects. By "refactoring", I am talking about the process of going back through your code and re-writing it to accomodate requests for changes, fix bugs, improve performance, whatever. Prior to objects, this process was VERY painful for me, especially with a complex project. Why? Because if the code is really complex, and if it's not split off into logical components, it's much more likely that I have to read through it like one long novel to understand it. If you are mentally-challenged like I am, you don't just have to read it. You have to re-read it....several times. Because there are so many ideas and concepts packed into one huge block of code, my mind gets overwhelmed, starts spinning, and I am having to mentally retrace my steps over and over to digest it all. However, if it's organized into small logical blocks or objects, I can take it one bite-sized object (or class) at a time. As I review a class, it's easier to digest because it's smaller and, assuming it's well-designed, everything in that class is there for one compact purpose. That means less concepts for my mind to have to digest at a time.
Conclusion
This article, as I am sure you guessed, was not intended for programmers already experienced with object-oriented programming. I am still brand new to it really. There are many things I know about it now that I haven't covered here. I am also quite sure that there's a lot about object-oriented programming that I have to learn. Still, this is the article I wish I could have found 6 months ago when I was still exploring this stuff and struggling to understand it. Hope it helps someone else out there.