Monday, December 10, 2012

Week 15 - Wrap Up (Dec 2 to Dec 9)

The final week of the semester has come and gone. This is the 7th time for me. One more year before I graduate and what I can say looking back is that I have somehow managed to find less time for myself with all of my classes. I feel like I keep taking fewer and fewer hours every semester, and I end up with more and more work.


The last test was trickier than the previous tests in my opinion, but that was to be expected because the material gets trickier and more nuanced as the class goes on and we have had less time to experiment and learn those concepts than we had for earlier concepts. I think the tests were fair. Although the daily quizzes could be a bit of a nuisance when the quizzes didn't cover the day's reading -- especially when a quiz covered a reading from several lectures ago and that reading is not fresh in your mind. Overall, the quizzes were another good tool to keep people on track with the material, encouraging students to study the tricky topics between every lecture, rather than waiting until the test is imminent.

Lectures



Overall I have a pretty positive opinion of the class. The lecture style was good for keeping everyone alert and learning, and was extremely clear. The papers were excellent reading. (The textbook on the other hand was dry and outdated.) The projects started off very simply and taught us the foundations of C++ and Object Oriented Programming (OOP), and then built upon those concepts. I wouldn't say the projects were particularly challenging on average, with the exception of the last project. Mostly they involved learning a simple concept and then building around that. I feel like I learned a lot about C++ and got some valuable experience and knowledge about C++ that benefitted me immediately because I was taking Computer Graphics this semester as well, wherein all the projects were in C++. Some knowledge of the trickiness surrounding certain concepts in C++ like copy constructors and copy assignment definitely bailed me out of some tricky problems that I saw other students [who had not worked with as much C++] struggle with. Immediate payoff is very validating.


One negative to the lecture style that poses a lot of questions to the students is that the learning is very instructor-driven, which can be a bit stifling to the types of learners that would prefer to digest an idea, interact with it (perhaps by experimenting with the code), and ask questions which explore tangential subjects. There were definitely topics that could have been explored in more detail and I wish I had been able to ask questions in the heat of the moment but we move pretty quickly through every detail that it's hard to really slow down and address some possibly interesting questions.

Programming Labs 



The programming labs were generally a good learning experience, at least as far as the implementation of the project was concerned. I understand that testing is important, but the fact that I spent nearly half of my programming hours devising unit tests is, I think, a problem. For instance, sometimes you want to create a function which encapsulates some extremely simple functionality. Maybe it wraps another method. There are a lot of circumstances where being required to write 3 unit tests per method, no matter how simple, is extremely frustrating. There are also functions which don't lend themselves to unit testing at all. For instance, functions that generate text output. Instead of writing directly to the console or a file, I found myself constructing strings in the unit test code which have to exactly match the output of the function, down to the number of newlines. Isn't that what acceptance tests are for? Weren't we running acceptance tests anyway?

I would recommend slightly relaxing the requirement for unit testing. Default constructors shouldn't need testing. Constructors which do trivial assignments of arguments to variables in the class and no other code, really shouldn't need testing either. Functions that output text shouldn't need testing. Functions that simply return the value of an instance variable most likely don't need explicit unit testing. The threat of getting a serious reduction in the lab's score scares us into doing all of these things, rather than focusing on unit testing the functions that are likely to be incorrect, and especially the functions that are more likely to break as the functionality is extended.

I even became aware that some people were attempting to circumvent the requirement to test all their methods by making "simple methods" into complicated #define macros! They engineered around the problem of testing simple code, but ironically they made their "simple" code much more likely to break (and more difficult to debug)! I hope examples like this help to expose the flaw in the requirement, and that the requirement will be relaxed to be something like "write at least 3 unit tests for non-trivial methods" (and define trivial methods as you see fit).

For Computer Graphics, I spent about 40 hours on one project. This project had many parts, and a lot of opportunities for exploring and expanding the programs for extra credit. Every half hour or so you feel like you solved an interesting problem, added a small feature, or fixed a funny detail of the code. I don't view any of that time as wasted, and it was so rewarding that I actually plan to continue to work on several of the projects from that class. Unfortunately, I hardly remember my solutions to any of the projects in this class except the most recent one, which I will surely soon forget the details of.

Sadly, the projects for this class were simply not inspiring. I suppose that is to be expected for a class which is essentially an introduction to C++.

Skills Learned



Skills we learned in the class:
  • C++
  • CppUnit
  • Git/Github. I like that there is a class which actually requires using source control in a sane way (i.e. not in a way that involves pushing to an repository that belongs to the instructor, for instance, where you don't have direct control over problems that arise). Using a VCS, especially a DVCS, is a good skill to have. My opinion is that Git should be required for programming labs beginning with a freshman- or sophomore-level required class.
  • UML Diagramming. Nice to do, not too time consuming, good for designing solutions to OOP projects.
Skills we should also learn in the class (since we're already making the effort to learn Git):
  • Make (Makefiles). This doesn't even really need to be explicitly taught. Providing a Makefile with the project would probably be enough. Students will be smart enough to figure out how to update a simple makefile to add to the list of files that get compiled. My Graphics class did this and it worked very well. This allows students to turn in a project without worrying especially about how their files are named, because the grader will simply run "make" instead of a predefined build command, using the students' Makefiles.
  • Multiple-file projects (when you have a lot of classes, we should make additional C++ files and update the Makefile as above -- also, executable code should be by-and-large in .cpp files, not in .h files. Even though the latter makes compiling much easier, it is bad style and confusing to teach this way in a class where most students are seeing C++ for the first time.)

Workload



There are some classes that are really hard, and that difficulty translates to the time you're likely going to spend on projects and studying. And then there are some classes that are just very time consuming. I've had some of both in my time at UT. I'm happy to say that there is less busy work as time goes on, and that as the classes get harder they also get more interesting. I very rarely find that the projects I do these days are a poor use of my time.

Unfortunately, this class toed the line between productive learning experience and busy work. The first labs were helpful to get oriented in C++ but they took way too many hours for what they were. For the first couple of labs, 75% or more of my time was spent writing unit tests, or updating the issue tracker in GitHub.

I think the class website is very accurate about the amount of time you'll spend on this class, in all categories. I was just a bit disappointed that the hours spent programming were mostly spent in mechanically devising unit tests, rather than in solving interesting problems. I wouldn't have minded 20-hour-a-week programming assignments if the assignments were legitimately interesting, as they were in computer graphics.

I expected more interesting and inspiring projects from a class which is numbered as Senior-level (371) and named "Object-Oriented Programming." Most of the OOP we covered in this class is covered in a standard Data Structures class taught in Java, and there is so much more to learn about OOP. I wish we had gone into more depth in that regard.

I know I sound like I'm complaining about the class more than I am praising it. Simply put: what was good about this class was good, and there's not much more to say about it. In fact, most of the class was good. I'm simply hoping that students who take this class in the future will benefit from the professor's consideration of these criticisms.

Sunday, December 2, 2012

Week 14 - Off to the Races (Nov 26 to Dec 1)

This week was the combination of too much to do and the premature celebration of the end of the semester.

As we approach the end of the semester we all tend to get sucked into festivities. Celebrating the last midterm before finals, going out with your clubs for banquets, and hanging out with friends and playing video games because you can afford a little break. It doesn't always work out that you can afford that break, but you try to fit it in anyway...

So, this week, my honor society had officer elections -- which tend to drag on and on every semester (but at least there's free food!). Of course, I ran for President, and although I know I wouldn't be a horrible choice, I lost to a better candidate for the 3rd semester in a row. I wouldn't say I wasn't trying, but not getting elected is a favor to me because it means less unnecessary responsibility for next semester. I'll still have one more chance before graduating next December.

On top of spending an extra 3 hours for elections on Wednesday night (yeah, pretty inefficient), I had an exam on Wednesday afternoon in my hardest class, Computer Architecture (EE 460N). And of course, I had the Life project to finish.

Between working alone on this project, and Thanksgiving holidays filling up the weekend, I was no where close to done with the project by Wednesday morning and I REALLY needed to study for my test that afternoon. I was fully prepared to submit my half-baked solution on the project so that I wouldn't get a zero and I could just move on with my life, but when Professor gave us a key piece of code we needed for the project and announced a 24-hour extension, I felt like my life had been saved.

I managed to get the project done after spending several all-nighters this week, and ended up missing rehearsal because I took a nap that ran too long, but I think in the end it was worth it.

Next week I have a paper, two projects, and 3 tests. Gonna be FUN! [1]

[1] For certain definitions of fun.

--------

I've learned a few important lessons from this week:

* Don't take holidays for granted. Make sure you get your work done ahead of time or your neck will be on the chopping block.

* Don't work alone if you're given the option to work with a partner (unless you can't help it). The time you save just by having someone to keep you focused and prevent you from spinning your wheels is probably even more useful in a college setting than in a work setting, because HERE we are surrounded by a million-and-one things to distract us, not the least of which is our other classes. On the other hand, I didn't feel guilty about spending some time exploring some other concepts of the class which weren't strictly necessary for the project, because I didn't feel like I was wasting a partner's time.

* It's okay to make sacrifices for more important things. I'm going to go into more detail about this one, below.

If I had tried any harder to get the project done on time instead of studying for my test, I probably would have failed my test. As things were, I was well-prepared for both my test and the officer election. I would have learned the material from the project one way or another and I probably could have afforded that setback in my grade for this class. The test was way more important.

I also went into the Thanksgiving break knowing that it was important for me to spend time with my girlfriend, my parents, and my best friend while I can, and I will cherish the memories of a nice relaxed Thanksgiving break in the long run, no matter how I ended up doing on the project.

See, the things that stay with us in the end are the good memories, and those silly little setbacks we have along the way will always get buried in more important memories. Maybe you end up with a mediocre grade on your transcript, but 10 years from now you probably won't remember exactly how that happened.

Do what you need to so you don't fail your important classes, and no matter what grade you get, make sure you learn the material that is most important to you at the end of the day. Maybe it's okay to blow off a homework assignment every now and then so that you can take a sanity break and play some of that video game you bought in the Autumn Steam Sale. But remember above all to make time for the stuff that's important to you and the people you love.

Some wisdom from a legendary philosophy professor:
http://www.pickchur.com/2011/03/golf-balls-in-the-jar-the-philosophy-professor/

Monday, November 26, 2012

Week 13 - Thanksgiving Break (Nov 19 to Nov 25)

This past week was Thanksgiving week and that means that we only had one day of class. Unfortunately I couldn't leave campus before Wednesday evening, due to a computer graphics project which for some reason I was unable to get to compile on either my Windows or Linux machines.

Anyway, during the break, I was able to find some time between eating and socializing with my family and friends to try to digest the project. I got a good start on the ConwayCell and FredkinCell classes but I'm not sure I really have a sound strategy for the Cell container class. I think I'll be able to figure it out but I'm hoping for a bit of a class discussion to recap the intended function of Cell, since that's obviously the core challenge in this project, and I want to make sure I understand it before I spend a lot of time trying to implement it and later finding out that I did it totally wrong.

---

This class has won me over as a convert from Mercurial to Git (in certain situations). I still feel the same way about Mercurial, though: it is much easier to learn, it is much simpler to accomplish basic tasks, and it works infinitely better on Windows for much less effort. However, I was working on a project in the Linux computer lab and since my Windows dev box crashed this week, I knew I would only be working in Linux. So, even though all my other graphics projects used Mercurial, I used Git for this one, and found that the power and flexibility it gave me was worth the extra complexity in the commands.

The use case for Git in this situation was more like insurance that I would always have a recently saved, working version of the project, which incrementally implemented more features. Essentially, in this case, there would be no branching and merging, and it was unlikely I would want to revert, so I was using it for its most basic features. Once you start getting into the more complex stuff, I think that the analogy

Mercurial : Git :: Python : C++

You give up a bit of power for expressiveness, but when you need to execute complex tasks quickly, the expressiveness is what you are going to care the most about.

Having gotten comfortable with both systems, I feel like there is actually very little difference in the actual functionality, and my preference for which one to use is going to depend mostly on the project's platform. If I'm on Windows, I will still hands-down prefer Mercurial. On Linux, it will depend on what I need my VCS to do for me, and how I plan to use it.

Sunday, November 18, 2012

Week 12 - Taking it Easy (Nov 12 to Nov 18)

This past week was pretty mild across all of my classes. I got to celebrate my birthday in peace, and since the deadlines for my projects are somewhat more spread out this time around I finally have a chance to relax and work through the projects relatively slowly. I can finally be careful not to miss out on the details.

I'm enjoying the discussion in class, although if you asked me to group the lectures into one phrase I wouldn't be able to say, exactly. I guess that means I need to review the material a bit more.

I'm looking forward to working on the next project alone. Compared with working alone, pair programming has been more interesting, in many cases more fun, and sometimes more productive. However, with Thanksgiving break coming up I think it will be easier for me to work on the project on my own time rather than try to squeeze in time to work with someone else. And this will give me a chance to see how programming on my own for this class stacks up against pair programming. I imagine I will struggle a bit more, but I am looking forward to the challenge.

---

My desktop computer's HDD is malfunctioning a bit, but it hasn't been too much of a problem yet. I'm keeping regular backups in case of imminent failure and I've ordered a replacement. I'm just not looking forward to having to set up my computer from scratch again in the middle of the semester. It shouldn't take too long but it's definitely time that could be spent studying or working on my projects. I hope all goes well with the hard drive replacement and OS reinstall.

Sunday, November 11, 2012

Week 11 - Private Testing (Nov. 5 to Nov. 11)


Another week gone. I'm glad to be done with the second test. The most recent project was pretty rough to get through as I had several projects due Monday, Tuesday and Wednesday evenings, in addition to the makeup test on Monday. Another thing which made this project somewhat difficult to get through is that I had implemented a more complex form of this same project in CS 315H a few years ago.

Fortunately, my partner Zesen was very accommodating of my schedule and we were able to complete the entire project without too many hangups.

I enjoyed the design component of this project. I would have expected that more of this course would involve designing classes and actually writing code in object oriented style, but the amount of experience I'm getting with C++ is also very valuable, even if it's not precisely what I thought I was signing up for.

My birthday is Tuesday, so I'm happy that this week is going to be relatively light for once.

---

I read a blog post about how unit testing private functions is supposedly evil. The primary argument seems to be that you shouldn't care about implementation details when testing, but I think that is a somewhat closed-minded approach. There are many algorithms that have a very simple public interface but which might contain relatively complex components in some implementations that should be tested individually. It could be rather difficult to know if the test of the public interface is getting good code coverage, or it may be extremely difficult to construct tests which adequately test the nested components. More likely, the algorithm is so complex that in order to make it readable, and thus maintainable, you would want to refactor the method into several utility functions. Sometimes refactoring makes sense because a number of public methods may have to handle the same functionality and thus refactoring private methods allows for code reuse, which is always a good thing.

About that latter point, the writer of the blog had stressed that if you find the need to refactor relatively complex behavior into private methods, why not refactor that same functionality to public methods in a helper class, so that the functionality can be tested in that way? I can't even think how to rebut that point except that the author seems to be missing the point. Some of these private methods might modify the state of the object directly, and do so in such a way that calling these functions without executing any other part of the algorithm might leave the object in a bad state, or a state which doesn't make sense from any external interface.

So yes, I agree that unit testing functions which are not part of a public interface will break encapsulation, but it seems that this author (and many others) are saying that these methods shouldn't be tested at all!

I think that any sufficiently complex implementation warrants tests of one kind or another. Perhaps I can simply write a static method, check(), which runs a bunch of "unit tests" on the private methods of a class. Calling this method will create instances of the class as necessary and test behavior of the implementation details that warrant testing. The method will return true if the tests all pass, and the method will be meaningless to anyone who wants to just use the class rather than verify that it passes its own correctness checks.

Of course, this method could be removed or conditionally-compiled out in production code to clean up the interface. If it is removed though, the information about the correctness tests on the class disappears and this seems like a poor option. I wonder why no one has devised a test framework which allows the testing of private methods, even if the philosophy seems to be that it would be a bad idea. If it's such a bad idea, shouldn't developers be allowed to shoot themselves in the foot if they so desire? I hardly see how this would be the case, but it seems there is enough of an argument for unit testing private functions that the functionality shouldn't be so easily overlooked.

Here's an article which summarizes the pro's and con's of private testing:

I think my final opinion on the matter is going to be the one which seems most in line with the unit testing philosophy, and is the opinion that I started off with: "Anything that can break, should be tested." Furthermore, those tests should be as direct as possible and not have to go through the middle layer of a public interface, if the code in question is in fact a private method.

Sunday, November 4, 2012

Week 10 - Fall Back (Oct 29 to Nov 4)

This program has forced me to look at things in a new way. I disagree with the design not through feeling that the expected implementation is wrong but that it lacks the kind of features I would expect to see in a reasonably complete program. I feel like the structure of the programs in this class require a minimum of implementation work and the amount of emphasis on testing is taking us away from the actual concepts at hand now. At first, it was good to have us focus on unit tests, but now the fact that unit testing is mostly a pain has caused me to limit my designs in some pretty serious ways.

In the real world, would you really unit test a method with a trivial function? Probably not.

Anyway, the make up test was once again moved from Friday to Monday. This is again outrageously inconvenient for me with the mass of projects that I typically have due at the beginning of the week. This time my project deadlines are going to keep me from studying for the test, or studying for the test (and taking the test) will prevent me from making my deadlines. I know there's not much you can do but to plan ahead but when every minute of your week is already absorbed in other school things there's not much you can do.

Senior year as a double major sucks because even if you take the minimum number of hours possible, you still don't have time to sleep.

Sunday, October 28, 2012

Week 9 - Burnout Recovery (Oct 22 to Oct 28)

This week opened up with a nice hearty exam. The kind of exam that is designed to be so unlike any previous exam or homework ever given in the history of the class so there's absolutely nothing you can do to study except know the material inside and out and pray.

I can see the pro's to giving a test like that but overall it seems a bit unfair when you can look at your test grade and say: When I practiced with the test that was given last year, I aced it without studying, and then after studying for days, I failed the actual test? What? There's too much variability in what people will know after studying that some people get lucky and other people get screwed.

---

Luckily, OOP has reasonable, well-designed tests by comparison.

But after finishing up project 4 and recovering from the last couple of weeks of not getting enough sleep and being totally burned out, I look back on this test and it seems similarly inconsistent. Luckily when it's a project you're talking about, it's much easier to sort out the confusing issues over a long period of time but what I'm talking about is design.

I find it hard to believe that the same professor who teaches a software design class would also teach a class where good design is so readily ignored. I'm sure not a single student in this class who has ever worked with C/C++ would say that the way we're organizing the code in a reasonable way. We write all of our code in a single .h file! I mean, I understand that this makes it easier for the grader in a sense, but it makes it much more difficult for the students to deal with, and we're learning bad habits.

We've gone through the effort of learning Git/GitHub, Doxygen, UML diagrams, etc. And for some reason, we aren't using Makefiles? Why not provide us with a simple Makefile for every project and explain briefly how it works, and tell the students to update the Makefile with additional source files and header files as needed, and then encourage us to use that. Then the grader only has to type "make" and then he can test our programs. So, rather than requiring a set of files and ONLY those files, we can turn in AT LEAST the required files and any code files needed to compile our programs. This way we are free to design freely and organize our programs in a way which makes the most sense for our implementation.

In earlier projects this was a minor inconvenience, but in the next project, we are given no starter code or guidance for how to design our custom creature, "Best." I would like to put all the creature definitions in files and have a constructor which takes in a filename and reads the creature from the definition. I have no idea how they're planning to test the creatures since they said to just put the definition of the creature in the comments of the code. This doesn't make any sense.

Normally I can get around the strange restrictions the project turn in policy has been putting on us but when we're kept in the dark like this, I feel like it's very likely we're going to lose a ton of points and not know why until it's too late.

Even asking on the class forum for help hasn't yielded any usable information. =[

Pressing forward...