This blog entry is intended to communicate my experience of developing iteration one of our translation software class project to my current and future Csci 3081W classmates with the hope that we can all learn something from it. Enjoy!
Overall, I feel writing the solution to iteration one went quite well for my partner and myself. We have very busy schedules, so getting together often during the development was difficult for us. We first sat down for a meeting for a couple of hours the Thursday a week before the due date, in order formulate our high level, initial plan. We used that time to hash out what classes we wanted, and what functionality they should have. We also discussed what tests would be necessary to ensure proper behavior of each supporting functionality. We also took some time to decide and code how and where we thought the regular expressions and their corresponding terminal types should be stored.
I found myself a little disoriented and slow at the beginning of this meeting, as I did not yet have the grasp of C++ or regular expressions I needed. I will certainly be sure to prepare better (if possible) before a planning meeting in the future. Otherwise the meeting went well and we were able to create assignments for the two of us to complete over the weekend. Our design was modular enough such that each of us could work on pieces of the project independently. The idea was to get all the supporting classes and methods for the scan function written and tested by Monday.
Over the weekend I designed two classes, one was very small and uninteresting, and created extensive tests for the functionality of the larger. I also wrote the function for eating up ignorable characters in the source text and its' tests. My partner wrote all the regular expressions we needed and a huge amount of corresponding tests. I did what I could to write my tests before writing classes and methods, but honestly, I am not in the habit. I ended up writing some tests after some implementation, and things worked out... for the most part...this time.
We were both able to separately develop, test and commit our code over the weekend without many problems. We only had to exchange an email or two with one another to communicate our problems and progress. Two of my tests that were attempting to build an EOF token were failing mysteriously, and we suspected that it had something to do with a regular expression. But by Monday we were confident that we had all the functionality that the scan method needed and all was left was writing that method. This was left for my partner to complete as well as investigating the failing tests.
And that's where he hit a minor snag. It turned out, due to our lack of experience with C++ STL containers, that the data structure we had picked to house our regular expressions and their corresponding terminal types, did not behave the way we had previously thought. Our implementation of the scan method was dependent upon that structure storing items in a certain order. He therefore had to pick a new standard container to use and rebuild the data.
He also discovered that our EOF regular expression was built incorrectly and once corrected, that fixed my mysterious tests. There were also issues with escaping some characters in some of our regular expressions. After correcting these issues and writing the scan method, our code passed all of our tests as well as the tests given to us for the scan function. This "integration" step seemed to have the most issues.
Retrospectively, we could have tested our simpler modules a bit more extensively to discover these problems sooner. For instance, we could have tested the data structure we initially built to discover we had things stored in an improper order. But since we did do a good amount of testing, my partner was able to discover the source of our problems quickly. This enabled him to make some simple modifications, and subsequently our code functioned well.
I hate to admit it, but that's about when we made the final decision to "emulate pure blocks" and use 4-space indentation. We had already been doing both of these on our own, for the most part, but we had yet to have the formatting conversation. (Keep in mind we have not had a face to face meeting since the initial planning meeting. This is still all via email.) We also discussed the use of white space, and how to deal with single expression while/for/if statements. After we had made our decisions, I went through the code making sure we were consistent with our formatting and making the necessary changes. My partner also added comments where appropriate.
Looking back, it would have been much easier if we had made these design decisions earlier, but in our defense, our planning meeting did happen before the class where all of that was explained. That isn't to say that we couldn't have stopped to make that decision earlier. Lesson learned. This proved especially true when we met up the final time about three hours before the iteration was due to "clean" our work up.
We took that time to write our implementation plan, retest everything on a lab machine again and again, and to compare the grading rubric to our almost final product. This is where we discovered that our indentation in some places looked different on different editors! In Emacs (the editor I used for formatting) everything looked fine, but when we'd open our code in gedit or vim, we had eight space indents in some spots where there should have been four. I had previously tried to customize my Emacs to indent four spaces, appropriate to the structure of the code, when I hit tab on a line. Or so I thought? We ended up getting some advice to find and replace all tabs with four spaces, and that did the trick. I'm still not entirely sure what I did to Emacs.
This all went down within an hour of the deadline, so that got a tiny bit stressful. Sometimes I think Emacs is a little too powerful and advanced, but once I advance, I'm sure I'll appreciate those qualities. We probably should have had our last iteration meeting a tad earlier. But things looked great by about 4:00 PM and all tests were passing, including the couple more for the scan method that my partner had written. So we made our tag and committed everything with a good amount of confidence.
This wasn't my first time working on a project in pairs, but it was my first time working with a repository. My partner and I didn't do much "pair-programming", that is both of us together at one machine, with one person typing at a time and the other thinking about logic and layout and keeping an eye out for mistakes. The time that we spend doing that was nice. Typing and syntax errors get caught right away for the most part. Also, when there's debugging to be done, it's very helpful to have two different brains on the case concurrently.
On the other hand, it was efficient to plan out and divide work to be done separately. I think we could have spent more time designing and analyzing before we did that though. For example, we could have discussed what kinds of tests we were going to develop more specifically. Even better, we should have written general framework for those tests together, to be fleshed out individually later. I suspect the integration of our individual work into the scan method would have gone smoother.
I mostly enjoyed the use of svn during the course of this iteration. All the basic functionality proved very convenient and useful. We had things designed such that we didn't have to deal with any conflicts, but I bet when that comes up, that functionality will come in quite handy. We did have some issues trying to revert a single file to a previous version while attempting to fix our formatting issue. It's not the most intuitive thing about svn and it requires a "reverse merge". Frankly, I'm still a little lost on the subject.
As expected, some things about our approach worked well and others not as much. There are a few things I would change about how we went about our business. First, I will make sure I am better prepared when my partner and I sit down to have our initial design meeting. Then we can make better use of the limited face-time that we have to flesh out our plan more thoroughly. We also need to be a little more specific and detailed about our testing plan.
Second, we should be consistent and comprehensive on all fronts, from the very beginning. It's much easier to comment and format properly as you go along, as opposed to getting things functioning, then adding these elements all at once later. It is truly also very helpful to get ALL of the proper tests written before I implement a method or class. You really do have a better grasp on how your code should work afterwards. Sometimes I need to experience something to a certain extent before I can entirely heed good advice. Coding is the fun part, but it's much more fun when it goes smoothly.
Last, my partner and I should sit down and code together earlier and more often. I'm not a huge fan of surprises during "crunch time". I do feel that given the circumstances we did a decent job of dividing the work and getting things done individually. But I'm sure we could benefit from a touch more collaboration.
There was also a fair amount of our process that worked well. Although we could step it up a bit, most of our unit testing and test-first approach proved to work well enough to get the project completed without major or difficult hang-ups. The iteration was simple enough so that our division of responsibility and individual work went smoothly. We communicated effectively through email and repository logging. When we did get together, we managed to work together to solve our problems efficiently by minimizing idle time. We tried to be sure both of us were doing something useful at all times. We will continue these practices.
Overall, it seems this iteration was designed to be technically simple, so that we could spend time working out our process. When we ran into problems due to our process, we weren't penalized as much as I feel we might be when the iterations become more complicated. So we must take what we have learned and apply it early and consistently in future iterations. That way we can be successful for the remainder of this project.