COS 333: Comments from Final Reports

Mon Dec 17 16:06:47 EST 2012

The following comments are taken from final reports in previous years; many thanks to the writers for sharing their experiences. The emphasis is on things that were a good idea, or that in hindsight would have been a good idea. He that hath ears to hear, let him hear; there is a stunning amount of truly good advice here.

New from 2012

StackOverflow is perhaps one of the most useful forums that we have ever encountered. Nearly every question that we had was answered on StackOverflow at some point, and usually the answers were exceptionally detailed.

Stack Overflow is a godsend. Apple's documentation was helpful too, but Stack Overflow was amazingly helpful. We did have to take Stack Overflow with a grain of salt, because older versions of iOS and Xcode have their own quirks and different features and best practices.

Ironically, writing a real-time 3D game with no networking for graphics (COS 426) took far less time and was much easier than writing a turn-based board game using networks. Networking is much harder than 3D graphics.

Debugging code is harder than writing it, which means that adding more features takes more time than you initially expect. We figured out that it's better to aim for a polished product rather than an app with lots of unfinished, buggy features -- there's a difference between what you want to add and what you should add when deadlines are involved.

Meeting in person and working as a group in the same room was very helpful for getting work done. When one of us was stumped with a bug, often someone else would have experienced the same issue and would sometimes be able to chime in with an answer. It also allowed us to quickly discuss what we wanted the app's behavior to be in specific situations. Also, because we had designated that time for work, meeting together encouraged us to continue working on our next goal even after implementing our current goal.

We realized that the best people to make design choices were users themselves. Hence, we consistently had mini-launches, in which we asked friends to use our product (without any guidance from us) and give us feedback. This allowed us to get input from people removed from the development process, who actually were seeing the product for the first time and interacting with it from a new user's point of view.

There is nothing more rewarding than the accidental discovery that a friend has decided to use your product for a second time - because it matters. To future 333ers of the world, Hack on.

We highly recommend that future students come into the class with a group already formed and a rough idea of the problem they would like to address. It is imperative to start early: the earlier you start, the more you can accomplish and test!

Github made group development incredibly painfree. We rarely if ever pair programmed, and weren't in the same rooms much either. But its merge functionality was awesome and (along with careful planning) allowed us to all work on what we wanted to when we wanted to.

Although we were all most familiar with Java and appreciated its abilities to integrate with various libraries and the GWT framework, we would definitely be willing to find ways to accomplish our goals in another language in order to avoid having to deal with GWT.

we would highly recommend investigating the documentation and other resources available for a tool or framework before deciding to implement it into your system.

In retrospect, we really should have made talking with OIT our first priority, even before diving into any implementation details such as learning Django; it would have saved us a significant amount of effort and stress and just required a little more planning and forethought.

Javascript certainly isn't the cleanest or nicest language to work with.

Figuring how to deal with someone else's code was perhaps one of the biggest learning experiences we had during the course of this project.

Another critical strategy was to reach out to others, both within our group and to those outside of the group.

When designing a new app that is fundamentally a utility app (as opposed to, say, a game), it is easiest for users if all the controls and behaviors are exactly as they'd expect from other apps.

We had been trying to develop independently of each other (meaning, we were all coding in different physical locations) and we realized just how much this hurt us when we actually coded together for the first time pretty late into the project. We were able to get a monstrous amount of work done simply by having other people around to make decisions with and discuss problems. We should have done this from the beginning.

We would definitely program together in the same room much more often; once we started doing that more, the rate of progress increased dramatically. This is not only because we can ask questions and collaborate on code if we get stuck; it's also because when developing disparate components that are supposed to interface with each other, like a server and a client or even two controllers or models, it is useful to know exactly what the behavior is instead of stumbling around guessing at what certain functions do.

Use Heroku or some other easy deployment service. You want to spend all of your time working on your application, not trying to debug deployment issues.

If your project follows a client/server model, develop both together. It's much easier to hook up the client and the server when they're being programmed in a unified way rather than splitting them up and hoping the interface lines up in the end. This is usually taken for granted with web applications in HTML, but is especially important for mobile apps. Build a barebones prototype and add functionality from there, rather than building all the functionality first.

Establish conventions with naming variables and functions (we struggled with that). Establish areas of ownership where you can, but also work across the product wherever possible.

Watch out for features that rely on other peoples' APIs and documentation. You may find yourself facing unexpected, arbitrary constraints.

The fact that each group member could work individually most of the time significantly increased our productivity. Rather than being dependent on someone else to make progress, or only being able to work when the group met as a whole, we each could check out and modify our own version of the Git repository.

There are simply too many unforeseen challenges and unexpected feature requests that will come up in order to be able to make a perfect schedule of milestones. That said, however, I think our group was very good at keeping on track. Though the goals of each week often diverged from our initial plan, we did have goals for each week that helped keep us moving forward.

We also took away a lesson on the importance of a solid foundation when building a large code base. The fact that we put a lot of extra thought into the initial architecture of how our code would work paid significant dividends toward the end of the semester. Because we had developed solid foundations, we were able to build lots of cool features on top. We also learned the importance of well-defined APIs; with a group of four different programmers all working concurrently, if APIs are ill-defined, a lot of time can be wasted by both programmers trying to get their code to synch up.

This project also exposed us to a lot of aspects of the software engineering process that we hadn't really seen in other classes, concepts like planning an architecture and collaborating on a common code repository.

The process of learning, in and of itself, was a major challenge as GWT is not particularly well documented.

We needed to enforce strict version control and documentation throughout this project. Since more than one person was contributing to the project at any one time, it was imperative that we set up good documentation so that others could understand what we had implemented.

It is extremely helpful to start planning early. This gives you more time to make design decisions and think about the best way to implement the project before you write a single line of code. We also believe it is helpful to keep a schedule and implement a few features per week, instead of trying to implement the entire project towards the end.

If you are stuck on an individual task and cannot figure it out reasonably quickly, you should immediately ask your group for help.

Next time we would try to give a working version of our project to potential users sooner, so that we could gather feedback and use it to improve our product. We did not share our project with anyone outside our team until the week we presented, at which point we had limited time to make changes based on the user feedback we received.

We should have launched earlier and worked faster--especially in the first weeks of the project.

Having weekly meetings with our TA was very helpful in meeting milestones, as showing your work to an outside observer is always inspiration enough when it comes to making progress. That is, deadlines are really very helpful.

It has been particularly nice to hear from our peers who have seen the site; the feedback has been great, and it just feels really good to have made something that can be so useful to so many people.

We found that the ability to constantly be in touch via chat programs and text messaging was vital to the success of the project.

Having a solid idea that is achievable and marketable (in both monetary and nonmonetary way) is the most important thing to enjoy this class fully.

It would have been better if we created a schedule that took into consideration other courses (e.g. the weekend right before the Networks Router assignment was not particularly productive).

We wished we had done more over spring break. Start early, use spring break wisely, and think about implementing the larger concepts before considering small cool features.

Something else that was suprising was the difference between Google's documentation on Google Web Toolkit and Google App Engine. We found that the App Engine documentation was straightforward with clear guidlines on how to do any and everything. Guides were more straightforward and self help books for Web Toolkit just seemed overly complicated and confusing.

Choosing to start with Google Web Toolkit primarily on the "Java" label for programming language was a big mistake. We did not take into account the complexity of the system or how everything would work. Switching to Python and Google App Engine early was the best decision we could have made.

Start early and ask questions. If anything, fail quickly! As soon as you know the path you're on may be too painful or complicated, switch. You'll thank yourself later.

User feedback helped us focus on the most important things and highlighted many places where our UI needed tweaking.

With regards to our milestones, it suffices to say that we were never ahead of schedule.

Although our individual assignments tested successfully before integration into the final product, there were more issues than we expected when we put all of our individual pieces of code together. We spent most of reading period fixing integration bugs and testing the final product.

We also did not leave enough time for preparing our presentation. We did not factor into our schedule that we would need more than a trivial amount of time to put together our demo for the teaching staff. We would offer this advice to future groups: you need more than a working product to show off, make sure you leave time to plan out and practice a polished presentation.

It took us a lot longer than we expected to get acquainted with XCode and with the iOS programming environment since it was quite different from what we had been in contact before.

One task we assigned ourselves for spring break was to familiarize ourselves with the languages and tools we would be using.

In COS 226 and 217, the assignments never required knowledge outside of what was learned in class. We simply had to be creative in applying it. The programming assignments were like puzzles to be solved rather than things to be built. For this project, a significant amount of time was spent figuring out how to do things, either by searching on the internet or "guestimating" with experimental code.

Planning

We believe that we might have been able to get a little bit more accomplished if we had been able to get a clear grasp of the goals and requirements for our project.

If we were starting from scratch and repeating our project, it seems like one of the most significant and worthwhile changes would be to spend more time perfecting each stage of its development rather than simply going into the next stage.

One thing we wish we could get another shot at was initial planning - the second time around, we would focus more heavily on input from the general population in terms of design and functionality.

One of the best decisions we made in organizing the project was to meet several times to plan out the project in detail before writing our first line of code. In our first meeting, which was well before spring break, we first came up with our project idea. Then we debated the best architecture for the system and the best way to divide it into pieces. These debates forced us to think through many of the important details early on, reducing the number of "surprises" that we encountered later in the semester. Once we figured out these aspects of the project, we sat down as a group to develop the interfaces between the user-interface web pages, the middle layer, and the database. Although some changes to these interfaces were necessary, especially because we made feature changes as the project went on, the interfaces stayed intact for the most part. Because of the continuity of the interfaces, pieces of the project that we wrote separately (like the web pages and the database) came together with little effort.

The long term nature of this assignment and the division of labor among multiple developers, made the approach of careless and unplanned hacking impossible. Rather than storming ahead to finish the project as quickly as possible, this project was completed by continuously taking two steps forward and one step back. This required a significant amount of planning, and the willingness to stop and clean up, refactor, and sometimes delete code completely.

I learned the hard way about the importance of having a strong initial design. Several times in this project, we changed our main interface in order to allow for more functionality. While I believe these changes were good in the long run, there was a lot of work involved re-writing to fit the new interface. I think our project would have greatly benefited from a more well thought-out initial design/interface.

If we were to do it over again I think we would need to spend a lot more time working on our initial design and stick to it even in cases where there is an obvious improvement if this improvement requires significant changes to the current architecture.

As a side note, when writing the design document, the process of writing the plan felt tedious and unnecessarily detailed for such an early stage of development. However, looking back, having a detailed and well-thought out plan before we started coding allowed us to avoid some possible problems along the way. The original plan put everyone on the same page and gave everyone the same expectation of the design of the website.

Our design experience showed that, although you can have an acceptable, working design concept at the very beginning, opportunities to make the design simpler (for the programmers and the end users) pop up all through the production process, and you must take advantage of them.

Our early design work was essential in laying out a framework for our code. However, at times the project suffered from overplanning. Too often, we relied on preconceived ideas about how the code would work; without sitting down and writing code, it was impossible to know the technical constraints that would inevitably influence our implementation.

We started too late. We just barely came up with a topic before spring break, and as far as planning, we had nothing more than a rudimentary initial meeting until after the break, which left us with effectively seven weeks to write code. Having known that we would have to do this project since the beginning of the semester, we certainly could have gotten started with the planning before and (maybe) during spring break, which would have made things significantly less rushed afterward. This problem was compounded by the fact that we were all busy with independent work and other projects during the second half of the semester

Scheduling

I think that you need to be more realistic (pessimistic?) when doing the initial timeline. It's better to plan for something being done on April 20th and being pleasantly surprised when it is done on the 14th than plan for the 14th and be working fervently on the 20th to get it working a week late.

Our intent was to have a fully functional version by April 1st (which soon became April 29th) and we planned for many unique features that flopped for various reasons.

We soon learned that as college students, schedules work better in theory than they do in practice. Progress on our project was interrupted by work in other courses, as well as independent work and thesis deadlines.

We underestimated the amount of time required to set up the environment -- i.e. waiting for other people to activate our accounts through the CS department and set up the SQL database.

Because no one in our group was familiar with any of these programs [Python, Django, SQLite, Apache], the set-up process for our web site took us over a week and quickly put us behind schedule.

We had a lot of trouble setting milestones at the beginning of our project because we literally had no idea what we were doing. We jumped into the deep end of the pool without floaties or a lifeguard. Because we did not know what was really going on at first, we indiscriminately set unrealistic goals for every week. Looking back now at the initial proposal, we can just laugh at how fast-paced our original schedule was.

We have met or exceeded each of the project milestones, in part because we made an effort to start seriously working on the project early in the semester. We had much of the planning and interface work completed before the end of spring break, and we had our initial prototype completed almost a week before the goal date.

Thinking that we were going to get anything done over Spring break was a mistake seeing as we were scattered across the country.

We started early. We had 1 - 2 meetings before Spring Break, and then daily on-line meetings throughout Spring Break itself. If we had started any later, we would have been in a lot of trouble.

We now know that it is always better to assemble the final product sooner rather than later. The project was just very easy-going at first, and all of a sudden when we put together the product with a full database, we were rushed.

I was surprised with how time consuming just setting things up could be. For example, when I went to the Friend Center to set up the database, I thought it would take an hour or two to get ready to program. However, talking to CS staff, working out driver problems, shifting through FAQ after FAQ ended up taking a very long time. Also, the Java connection to the MYSQL Database was very clunky and tedious to program in.

I feel like our initial schedule was very poorly designed. I feel like we guessed fairly badly at how long things would take to implement as well as what things we would decide to focus on implementing. As a consequence of the fact that we needed to make constant progress, I feel like we created things out of order but I don't know of any other way we could have done it and still had anything to show at our weekly meetings.

We started with the core structure, and then kept adding Christmas ornaments on the tree until it was full. At any point along the way, we would have been able to stop, which was a nice reassurance when we started out.

Working Together

We settled into a routine of meeting as a group at 1:30 pm on Wednesdays and working until late. It was a brutal schedule, but we found these sessions to be very productive, and we were generally able to finish what we had set out to do at the beginning of the week. There's no better way to code and debug than to have the person who wrote the code you're using sitting right next to you.

There has *got* to be a time when the whole group can meet (outside of the meeting with the TA) each week to really get a handle on where they are and what needs to be done. It was also very helpful for us to have clearly defined 'roles' (in addition to the project manager) so that someone was 'on point' for various aspects of the project.

The necessity of leadership was immediately apparent. For the first few weeks we would make plans to meet at a certain time, and then as the time elapsed each of us would independently realize that we didn't know where the meeting was supposed to be. Having someone step up and make most of the easy decisions, definitely facilitates building a project like this one.

Probably the most important learning experience was figuring out how to work on a team towards building a sizable CS project. The necessity of leadership was immediately apparent. For the first few weeks we would make plans to meet at a certain time, and then as the time elapsed each of us would independently realize that we didn't know where the meeting was supposed to be. Having someone step up and make most of the easy decisions, definitely facilitates building a project like this one.

We met in person at least once a week. In addition to our weekly meetings with Bill (after which we would always stay and talk to coordinate), we occasionally met an additional time if it was felt that it was necessary. During our final push, much of the work was done when we were all in the same room. Working together in person was definitely very helpful, as it made coordination easy.

We would probably try to put more effort into spending more time coding together (as in, side-by-side) on some of the parts. Breaking the work into parts and working individually sounds great in theory, but when you are not sure how the parts of a website will ultimately work together, it's much easier when there is verbal communication as interconnecting parts of a site is being built side-by-side.

Programming projects benefit tremendously from working meetings. You get so much more done if all of you just sit in the same room and code. We really should have done a lot more of that.

We were honest with each other about what we we had time for. Each week, before we took on our assignments for the week, we made sure to consider how much other work we had. There were weeks when some of the members of the group were not able to contribute at all, but it was not a problem since it was known beforehand. Thus, other group members with less work were able to compensate.

It takes some time and effort to think weeks ahead, but the rough skeleton of the game plan is very important as the group goes forward. Without this general idea of what should be completed by when, it is easy for a group to lose focus in the middle of a busy semester and find themselves far behind in their project.

Coding

From the very beginning, we agreed on a general style of naming and organizing our files, code, and variables. As a result, all of the files in our project have natural, intuitive names and have homogeneous capitalization and abbreviation patterns, and our functions and variables are likewise. We also chose to store code that performs similar tasks together (all code that communicates with the database, for example, is in a subdirectory labeled "dbaccess"). As a result, we believe that throughout our project we succeed in conveying an idea of the code's substance through its style. This is, in general, a most helpful tool in a group setting.

Cascading style sheets offer a good lead-in to the look and feel as a whole, since CSS really tied everything together. It was our plan from the beginning to leave this until the end, since it was the most likely to change over time and the least crucial to the site's functionality. In retrospect, it would have been a much smarter idea to decide on a set of font and table classes at the beginning.

The modularization of the program structure helped a lot. At various stages, major components were restructured or reimplemented but since it was so modular, these changes didn't affect any of the other components.

We learned that modularity is a great boon when implemented. As an example, we made the authentication functions (though not the variables because they had to be visible) very modular (we never ran the same segment of code twice without putting it in a function). This much better than just placing the code somewhere in a file, because we actually made several changes to the code and tweaked with the timeout period. We are very confident that those changes are uniform across the website, which we would not have been had the code been scattered about.

Because of good modularity, changes in one part often had no effect on other parts, and if it did then the necessary changes were easy and natural. Each person knew their portion well enough, too, that many times a verbal description of problematic behavior was all that was needed for a person to pinpoint a bug.

Our inability to create a working system on each of the group member's computers was definitely a great problem. All the parts were tested separately as they were developed and as new features were added. However, the final product could only be tested once all the parts were put together at the end, and some features that worked independently did not always work in the final product.

Languages

Another thing I gained from this project may not be a very positive one, but I really got to experience all of the biggest problems with Java like never before. Working on a big project like this forces developers to use packages, which is very difficult and frustrating, and it is hard to get them working correctly. Another huge problem is the classpath issue at compilation time. It is very difficult to get all the build paths correct, and even to run the whole project, in order to get all of our third party libraries running all kinds of classpath issues need to be resolved.

Java's classpaths are a heat-seeking land-mine: come anywhere near them and you are in trouble.

Swing code would often cause heartbreaking and fundamentally bizarre errors that resulted either in progress stagnating for a period of time or in the need to rework large parts of the program. Furthermore, in several cases the group's lack of experience with Swing resulted in creating parts of the program in an unnecessarily complex or time-consuming manner.

Another major surprise was the improvement in the speed of the course browser after the migration from Java to PHP.

Debugging in PHP proved to be a endless task at some points during the project.

I've become familiar enough with PHP to call myself fluent at an intermediate level, which is especially nice since the language is one of the more common ones that we didn't cover in class.

Python has especially become a close friend of mine, and it is a language which I feel combines many of the best elements of each other language I've learned.

I spent almost all of my time working on the GUI, in Javascript and PHP. If there was one thing I go back and tell myself from the beginning, it's to always read the documentation first. HTML/CSS/Javascript is a really tricky combination; the usual debugging technique of "tinkering" is guaranteed to make things worse.

My advice for a future COS 333 student would be to spend a good few hours in the beginning of the project reading up on how PHP and SQL actually work as it makes things far easier than just googling things as they come up.

Version Control

It probably would have been a good idea to have a system where we sign out code to edit it, so everyone knows not to edit the same code at the same time.

This project also marks the first time I'd used a CVS server. Looking back on it now, I don't know what I would have done without it. It helped us synchronize our efforts and really increased our capacity to work cooperatively.

Once all the somewhat arcane configuration had been done, however, CVS was an absolutely indispensable tool for our cooperation as a group, and we used it for the remainder of the project almost without thinking about it at all.

On several occasions, one of the group would accidentally wipe out the work of another due to overwriting a file that had been changed. In most cases we were able to restore from backups, but data was irretrievably lost more than once. Even if data was not overwritten, functionality could break down if two people were working on related files simultaneously. ... After learning our lesson the hard way a couple of times, we all became mindful of backing up old files before uploading new ones, and sending group emails detailing the files that we were working on at any given time. If we were to start over again, we would use a CVS from the beginning, as it would be both easy to use and more reliable than our group email methods.

Using SVN was wonderfully easy.

Testing

Test scripts for each basic module were developed simultaneously with the module and were a great help in debugging.

We made an effort to test our project as we developed rather than waiting until the end of the semester to begin testing. This philosophy of, "test early, test often", turned out to be a good strategy because it gave us confidence in our code and it reduced the likelihood of us having to make major changes at the last minute.

Due to some unfortunate choices in implementation, the program runs much more slowly than we had originally hoped.

We started with a small core set of features, then built them larger. This had two benefits. First, it allowed us to have a close set of friends as our user base early on so that we could get constant feedback, not only on the site, but bugs we missed.

We tried to fix bugs as soon as we found them, which usually made life easier down the road.

One other thing that we learned about PHP and javascript is that it's very difficult to test and debug the code completely. The hardest part about PHP is that if you have a syntax error in your PHP and it's nested within a loop that rarely gets executed, it will not get an error until that inner loop is executed. This places a particularly strong burden on the programmer to manually test all code rigorously.

Another important lesson that we learnt was the importance of testing. No matter how confident you are in a piece of code to work, and no matter how short it seems, it is always prudent to not proceeed until you have tested the code written so far to your satisfaction. Often you would find that adding further functionality increases the number of potential pitfalls in your earlier version, making you go back to testing the code that you thought you had already tested. If you had indeed done a good job of testing this earlier version, you can then focus on ironing out the problems introduced by the new code.

We learned to never trust anything that came from the front end and to put all error checking on the back end.

Although using 3rd party code is crucial in developing a powerful application in a reasonable amount of time, consistent and thorough testing is important in avoiding complicated bugs and ensuring security of your site.

It is easy to forego testing when under time pressure, but it is an unwise decision.

Start early, plan carefully, and test thoroughly.

The Real World

The administrative interface that we put together at the beginning was not particularly complex, however, it did require repeated and varied calls to the database, which was a good way to become familiar with the back-end.

We also learned that it is much easier to write code on a machine that you have full control over. Patience and spare time before a deadline are a must in these situations, we were lucky to catch this issue early in our development stage, otherwise things could have gone very badly.

When developing in a less familiar language, don't be afraid to throw out code when you find a new and better solution -- it will save you time in the future and you still learned something from implementing the old code.

Future students should anticipate some difficulty and plan ahead accordingly if they require copyrighted materials (maps, pictures, etc.) for their project. Being upfront and honest with the owner by telling them what it will be used for will generally prevail, though it can take some time.

Certain tasks are often more difficult than they seem. In particular, the parts of the project that seem complicated will almost certainly become even more complicated once the coding begins. Starting early on the most difficult parts of the project will pay off in the end.

If there is a manageable feature that could be added to the project that would make the application useful to a whole new audience, it should definitely be considered. Never become so focused on the coding that you lose sight of the end-product and the interests of the consumer.

Having done this program, I have a new appreciation for all real world application programming. The only types of programs I have been exposed to so far were simple programs like "compress this" or "create this little algorithm." To make a jump to "make this system and make sure it never crashes and accounts for all user inputs" was just a huge jump.

Probably the most valuable lessons we learned from this project came the day of the demo, during which we naively decided to add a few more features to our code hours before presenting the website. Falling victim to Murphy's law, we found ourselves with a major bug within minutes of the project. The scrambled effort to fix it interrupted our presentation planning. Though we were fortunate enough to fix the bug in time for the demo, our demo suffered because of it. We have all thus learned the hard way that ample testing should occur well before the day of the demo so we can prevent dramas such as the one we lived through.

This was the first piece of software we wrote for an actual user base, meaning that most of the specifications for end functionality came from our users, rather than arbitrary decisions on what we thought might be useful. The consultation process resulted in a number of surprises, most notably the customer's desire for a feature which we hadn't encountered in any of our searches through the literature or heard of previous to our work.

I think the lesson I learned the most was simply: listen to your peers and users, even if it means throwing away something you spent a lot of time on.

The Bottom Line

Working with the users was an enjoyable experience, and we are glad that we could provide them with something that will be useful in real-world applications.

This project has been a very positive experience for us all. To see an idea all the way through, from its inception to the final product is an incredibly satisfying feeling. Furthermore we have learned much about groupwork, interfaces, php, mySQL, and much more along the way.

In the past when I've worked with groups, especially in computer science, I've felt that we got in each others' way a lot. With this group I really feel that we helped each other a lot, gave each other suggestions, and really used our other group members to our advantage to help make our project better.

All in all, though, it was a wonderful experience. I am amazed at how well it turned out, and I am very pleased with the work of our group. It may not sound that impressive to say that the things that went right far outweighed the things that went wrong, but in the seemingly chaotic world of developing software, I'd say that's pretty good.

Overall, however, we all feel it was one of the most enjoyable projects we've been involved in at Princeton, and also one from which we have gained the most practical skills.

I really love what we've built.