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 great deal of good advice here.
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
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.
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.
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.
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.
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.
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 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.
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.