Sunday, April 15, 2012

Elegant Copy Constructors and Assignment Operators

So recently I discussed the importance of adhering to the Orthodox Canonical Class Form, and in this previous week in class I learned of a very elegant way to complete two of these: the copy constructor and the assignment operator. As long as you are careful, these two methods can often be very simple to write and do not typically require a large amount of thought. Most problems arise when there are pointer variables as fields in a class. Using the default assignment operator will simply copy the address of the pointer over which results in two variables pointing to the same address. Honestly, I am having trouble recalling how I used to do this because this new method I have learned of completing these two tasks as nullified all of my old practices.

So let's say we have this class, my_object, and in this class we have only an int and an int* as private data fields for the class, like so: (Yes, it is stupid, but I am simply trying to show a point).

class my_object {
    private:
        int x;
        int* y;
};

Now, we do not want the default copy constructor or assignment operator, because they will both result in some nasty pointer bugs. We want each instance of my_object to have its own value of y, and more importantly a unique address for y! So, we will continue on to create the copy constructor using C++'s interesting syntax for initializing variables in the method declaration:

my_object::my_object(const my_object& that) : x(that.x), y(new int) {
    *y = that->y;
}

Notice that I accepted that as a reference, and that I simply initialized this->x to that.x, and that I created a new int on the heap and set its value to the value of that's y in the method body. How can we write an assignment operator that takes advantage of the copy constructor we just created? I would argue that this can be done precisely how Professor Downing enlightened me in class. First I will show it here and see if you can figure it out:

my_object::my_object& operator = (my_object that) {
    std::swap(x, that.x);
    std::swap(y, that.y);
    return *this;
}

In the words of Dr. Downing, "Beautiful!". Really, I truly believe this is a beautiful solution. We created the copy constructor that took care of the pointer copy issue, and simply passed the my_object by value in the assignment operator such that a correct copy is created, and we can swap the variables out of the object to get the proper assignment.

Monday, April 9, 2012

Interview With ARM

I had an interview with ARM last week, and I truly believe that if it were not for Dr. Downing's wonderful Object-Oriented Programming class, I would not have felt nearly as confident going into and during the interview. While Arm really is not the type of company that requires an army of computer scientists, it is interesting to see how they are currently looking to see how computer scientists will adapt to different environments and how they can apply an abstract view to different problems.

One of the recurring themes of the interview was the subject of a GUI they were interested in designing. Even though I do not have much experience with GUI's, I am still confident that I would be able to create one without a tremendous amount of difficulty. After all, it is just object manipulation and message passing. Regardless of whether an object is representing a frame on the monitor or some abstract data structure, it is still just an object that can be asked to do things and/or produce some result given a message or what state the object is in.

Pertaining to experiences in this particular OOP class, the interviewers were also interested in experience with version control software, issue trackers, and most importantly, proper documentation. The engineers loved to see that I have experience with git and svn, and loved the fact that I keep almost all homework under version control even more. Two of the code samples I sent were in fact projects from OOP, and they thoroughly enjoyed looking at code in which each function and method was documented well and easy to read.

While I do not have the job yet, I am anxious to see how the job will play out if I am hired. As of right now it seems I would be working mostly with engineers, and I am very curious of how my abstract brain can apply itself to the lower levels of the computer world.


Sunday, April 1, 2012

Avoiding Setters and Getters

For the novice programmer who is just beginning to delve in the world of object-oriented programming, setters and getters are typically the goto method of manipulating data fields of objects. Sometimes it is difficult to program without using setters and getters, specifically getters. It is often necessary to ask an object what kind of state it is in, or the value of some data field it holds. This is nice and all for testing and quick/dirty class creation, but it fails to shield the programmer and other objects from its implementation. Ideally all classes should hide all of the dirty details of the class and instead perform the computation that another class would use the value for in the first place.

In the current project in OOP, this has been a real chore, but this one of those projects that can be a disaster if designed poorly or a lot of fun if designed with good object-oriented design practices in mind. The project basically consists of a grid that holds creatures of different, or equivalent species. These species can turn, move around, and infect other creatures such that they are now the same species. In this picture, it is easy to see that there should be a grid, creature, and species class, in which the creature holds some form of a species.

The question is: How does the grid communicate with the different creatures on the board without simply asking for different data fields? How will the grid know which direction they are facing? How the instructions of the different creatures be passed around? The easy approach would be to have the grid simply ask for different data fields of the creatures and do all of the computation itself, but this is ugly and can lend itself to debugging disasters. It is much cleaner to give the creature some information based on what is in front of it and have it do some computations based on its own data to figure out what to do next , and then relay that information to the grid.

It is just lately that I have been forced to program without the use of getters and setters. While they do have their purposes in some cases, I am beginning to see how objects can communicate in a much more elegant and purposeful fashion if they are avoided.

Sunday, March 25, 2012

Redemption

So, we had our second test in OOP last week, and I would like to take the time to give a little feedback about it via Dr. Downing's request. I feel as though I did much better on that test than the first, coming out of the test feeling much more confident than I did with the first. For this particular test, I studied and focused far more on understanding the slides and quizzes rather than simply trying to memorize them. Really sitting down and trying to understand the difference between the different iterators and what was really happening in the examples proved to be very useful.

In some of the previous projects me and various partners ventured out a bit and tried our hands at declaring objects on the heap, even going so far as to create custom linked lists and understand how to manage them correctly. I think doing that and understanding what was going on during the construction and destruction of objects did a lot in helping to explain the two part process that happens when deallocating objects. That is, the objects are deleted and the memory the objects possessed is then freed.

I do think the test may have been a little one-sided on certain subjects. Many people said that if one did not understand one question, he or she would very likely not understand the surrounding three or four questions. I find this somewhat true, but I also believe that one could logically infer the answer from the other questions. Or rather, one could infer the logic to answer a question from analyzing similar questions.

One question I like to ask myself when asked questions dealing with language semantics pertains to asking how the language would act in certain situations if I wrote it. After all, programming languages are designed to be as eloquent and logical as possible, and in my opinion should have predictable functionality to the programmer. Then again, C++ can be very, very complicated, but I will take any mindset I can get that gives me more confidence in a test.

Sunday, March 18, 2012

The Beauty of Lists

So, if you take a look at my last post, you can see that I have taken a liking to the use of vectors over arrays in C++. While the current project in OOP naturally calls for a "has-many" relationship between two classes, I have found that there are other, possibly better options to use than vectors.

Lists, under the right circumstance, can prove to be a good option when random access is not required. This last week in another project from an operating systems course, a situation called for use of a linked list. It required a list of objects that was sorted under some characteristic defined in the class, and it required that addition of elements be as cheap as possible. Well, it turns out the C++ STL has a wonderfully built list already that I have only begun to scratch the surface of. In order to maintain the list in sorted order, it is as simple as overloading the "<" operator, pushing an object to the front of the list and then simply calling the sort function from list. i.e. someList.push_front(someObject) and then doing someList.sort(). While sorting vectors typically involves copying, for lists all that is required is rearrangement. Or in the words of the C++ reference:


The entire operation does not involve the construction, destruction or copy of any element object. They are moved within the container.


Sorting a vector, on the other hand, typically calls for the use of algorithm's sort unless a custom sort is created, but I really do not see why you would when creating comparison functions and using built-in sorts are so easy.

Some might argue that inserting into a list is actually more expensive than inserting into a vector. In some cases I could see this, because for small types it is extremely simple for the L2 cache to do its work on the entire vector (say if we are pushing to the front of the vector). For larger objects, as containers grow in size, this could prove to be a problem as the amount of copy calls grows. 


I would love to hear some points on the efficiencies of vectors vs. lists in the comments!

Monday, March 12, 2012

The Beauty of Vectors

After months of only using arrays in C++, I have recently started using vectors as my go-to basic data structure. While arrays are great for lower level code and tasks that require the highest level of efficiency, in most cases vectors will prove to handle things in a much simpler and more elegant way. I personally like that vectors provide the user with a way to retrieve the size of the vector. It is no longer needed to keep track of the size of an array with a separate variable, which can really make vectors easier to work with.

Often times when using simple arrays it can be a nuisance to deal with managing the objects they hold. Vectors also work magically with memory. When vectors go out of scope, it calls the destructor on the elements it holds. I would argue that using a smarter container like vector instead of an array decreases development time because it helps reduce programming errors.

One of the interesting caveats involved with using vectors is the way iterating is handled. At first glance, it can be easy to assume that a simple for loop from int i = 0 to some_vector.size() would work just fine.

for (int i = 0; i < someVector.size(); ++i)
    cout << someVector[i] << " ";

Well, it does, but the field that holds the size in vector is unsigned, so a type warning occurs at compile time, and that means there is probably a better way to do it. The first, simple fix, is to simply change the type of 'i' in the loop to an unsigned type so that the comparison i < someVector.size() will not result in a warning. Unsigned int will do, but it turns out vector actually uses the size_t type for this purpose, and that ends up being a far more correct solution than simply using an unsigned specified type.

for (size_t i = 0; i < someVector.size(); ++i)
    cout << someVector[i] << " ";

We can still do better by using iterators instead of using the standard for loop. Vectors have both a begin() method and an end() method that both return iterators. (Obviously begin returns an iterator to the beginning of the vector and end returns an iterator to the end). Hell, we could even use rbegin and rend which return reverse iterators. Here is the simplest way to use them in one for loop:

for (vector<T>::iterator it = someVector.begin(); it != someVector.end(); ++i)
    cout << *it << " ";

Notice that in this case we had to dereference the iterator object since it is simply pointing to the consecutive elements in someVector.

Anyways, vectors are proving themselves to be a very, very cool alternative to arrays. When using them just be careful that you initialize them properly if the initial size is known. Check them out! http://www.cplusplus.com/reference/stl/vector/

Sunday, March 4, 2012

The Orthodox Canonical Class Form

Every "good" programmer has heard it and knows it: the canonical class form, the "must-haves", the four methods every class needs to possess a certain degree of thoroughness in acting out its purpose. In case you have forgotten, I will go ahead and relist them again here:

1. Default Constructor
2. Copy Constructor
3. Assignment Operator
4. Destructor

While this explanation will be stated according to Timothy Budd's Introduction to Object-Oriented Programming book, I believe he does a great job of outlining each of these methods and iterating their purpose to the reader. The default constructor is used to initialize objects and data members when no other value is readily available. There is of course in most cases a default constructor, but relying on the default constructor is typically not a smart choice. The copy instructor is used in the implementation of call-by-value parameters. The assignment operator is rhetorical, and the destructor is invoked when an object is deleted. The copy constructor, to me, seems to always be the least necessary. How often do I actually need to copy an object when I already have access to the original? I typically pass objects as pointers, but I can see how working with others and failing to write a copy constructor could cause somebody to shoot themselves in the foot when passing values by value.
I am sure most readers have these four functions hardwired into their brains, but it is always good to reiterate! I personally fail to always take care of these things, and my goal is that this post will remind me to think through what I am doing and about the issues that can arise when the canonical class form is discarded. I would enjoy hearing some other purposes for the canonical class methods in the comments below!