Implementing a great final project

Posted by john in Assignments, Announcements Add comments

Last revised: 22-Dec-2007, 2 PM: You are to implement the e-mail plus TWO (2) of the other features.

Original: 22-Dec-2007, 11 AM

NOTE: This page is the “official” version of the requirements for the final project. Please add comments here, not in the e-mail list. If we add information here, we will announce it via the e-mail list.

In this post we want to break down the 7 categories for “additional features.” The final project is your version of CCC from assignment 5, with additional features (the other option was to propose a new project with similar complexity to CCC, implement that, and then add the additional features).

One additional feature is required; you get to chose the other two.

A very important note: There is no “right” way to implement the following. What you are reading are requirements. We are not going to spell out the implementation, except to point you to certain places in the code. Part of your grade will be based on your ability to move from requirements to implementation.

Tips

  • “What is the simplest thing that could possibly work?” (Kent Beck)
  • “Don’t Repeat Yourself” (DRY - Dave Thomas and others)
  • get it working first
  • use good taste (if you get your code working, and it looks like a hairball, see if you can make it more understandable)
  • Don’t forget it’s Ruby; write like a Rubyist

Writeup

Please provide a writeup of what you have accomplished in the final project. Anything new should be described in terms of what the user experiences, and then in a separate section, you should explain how you did it. In other words, the writeup should have two sections:

  • Use Cases
  • Implementation

The easiest way to write is to think about your intended reader. For the use cases, the reader is someone who needs to know what is going to happen. The use case is essentially the “story” of the user experience, using the vocabulary of the application (Users, Playdates, Invitations, etc.), just as we did for the assignment overview. That reader might be someone in QA, a VP of marketing, or someone who is evaluating your product. For the implementation section, the intended reader is another developer. Explain to that reader what they need to know to understand, maintain, and modify your code.

It is hard for me to imagine that a writeup would be fewer than 4 pages (about 1000 words). Your writeup is key. Oftentimes your grader cannot see what you’ve done unless you tell the grader. So “crow” about the compelling nature of your features, the elegance of your UI, and the power of your implementation.

[Amy says: if you have a hard time figuring out how to write something of use to another developer, imagine telling someone in section how to do what you did, or complaining to them about all the things you had to try before you hit upon the thing that worked. Especially where your code is a little hairy or obscure, you want to explain why you did it that way instead of some other way that the other developer thinks, on first glance, would have been better. If the actual reason you did something was “I didn’t have time to do this any other way,” that’s still valuable information to provide, as it allows the future developer to distinguish between necessary and unnecessary complexity in your code. If you do not point out unnecessary complexity in your code, we will assume that you did not notice it, and from a grading perspective it is worse to do something nasty and not notice it than it is to do it and admit it. (Of course, it may just make sense to point out nasty bits in inline comments; not everything deserves a mention in your writeup itself. The point is not to leave ugly or ’smelly’ code in your project and hope we won’t notice it.) Think of your writeup as writing the first part of a good story about your project. You want the reader (QA, potential users, future developers, etc.) to be engaged, informed, sympathetic, and eager to be involved in the work of adding on to the story.

You DON’T want to write a sentence, run a word count, write another sentence, run another word count, and so on until you reach John’s 1000 word floor. If you tend to save the writeup until the very end and then sit staring at a blank screen wondering what to say, try keeping a log while actually at work on the project: jot down problems you’re facing, decisions you come to and why, expressions of frustration, notes about how long something took you to do, resources you found helpful, etc. Then when you get to the writeup you will have a wealth of raw material to use.]

Required

First, you must implement the distribution of invitations by e-mail. Here’s what that entails:

In InvitationsController#create, you probably have a line something like this:

Invitation.create!(:invitee_id => id, :playdate_id => params[:invitation][:playdate_id], :viewed => false, :accepted => false)

In addition to this, you must send that person an invitation by e-mail. That mean sending a link. What kind of link? It might be something like the following:

http://localhost:3000/invitations/invite/341

where 341 is the id for the invitation. Let us say that invitation 341 is for john@7fff.com.

The recipient of the e-mail clicks on the link. Since there is no action for invite in InvitationsController, you will need to write one. I click on it. If I am not already logged in, I should be given an opportunity to log in. If I *am* logged in, the software should check to see if invitation 341 is really for me. If it isn’t, I should get an appropriate error message.

When an invitation is viewed, the “viewed” attribute should be changed to “true” in the database.

Then the template for the invite action should show me the details of the invitation, and I should be able to submit a form that means I am accepting the invitation. Note that you might choose not to blend into this form adding/removing children from the playdate (there is an existing UI for that).

The best implementations will do the following: They will allow the invitee to add/remove children when they accept the invitation. It should be possible to click the invite link twice, and something reasonable should happen the 2nd time (perhaps just a message saying that you’ve already accepted the invitation, if that is the case). It should be possible for a new user (someone who only has an e-mail defined in the users table, but not first name, last name, password, etc.) to provide more registration information. If you will recall, in the original model, we require new users to pay, so this would be when we would do that. [DO NOT TRY to implement e-commerce! If you like, you can pretend that it’s implemented with a checkbox that says that the new user agrees to pay.]

Extra credit for the required feature

For a couple of points extra: It is problematic that the id’s for the invitation links are in a known sequence. This means that someone could very easily guess what other invitation links are, and could create spurious “view” or “accept” values. Add a column that represents a “globally-unique identifier” (you should be able to Google for this to get some ideas; a synonym is UUID), and put that id on the invitation links. For example, here is a link we use at Duffy’s Cliff to confirm a user:

http://www.duffyscliff.com/account/verify_user/OEeaw-64kD4p5yqcfjn_-F1HPPg

By this means, it should be virtually impossible to fiddle with someone else’s link.

And Implement Two of the Following

After each feature, I will provide a bit in brackets that “scores” the feature in terms of difficulty, potential to learn, and value for the application (10 means high value, 1 means low value. E.g., “Difficulty: 3, Learning: 1, App: 10″ would mean not too difficult to implement, you wouldn’t learn a lot, but it would be a great feature for the user).

1. User management: Adapt the login / registration code to use the acts_as_authenticated plugin (http://agilewebdevelopment.com/plugins/acts_as_authenticated). You should provide a means for the user to fully register (adding first_name, last_name, etc.). You may use either the RESTful version or the non-RESTful (it is claimed that since Rails is going RESTful, using the RESTful version is more in keeping with Rails best practices, but it seems to me that the dust has not settled on this yet; so pick one and don’t worry excessively about your choice). The best implementations will build on acts_as_authenticated so that the user can register during the acceptance of an invitation. The best implementations will study the migration provided by acts_as_authenticated, and will figure out a way to save the existing user data as it is migrated to the new scheme. This may be hard.

[Difficulty: 5; Learning: 5; App: 7]

2. Ajax: Ajaxify as much as seems appropriate. The very best implementations would implement a number of the following:

  • Updating sections of the page as appropriate
  • Replacement of a form with the results of that form after posting
  • In-page asynchronous notification of events (e.g., “Naomi has accepted your invitation for the playdate on 26-Dec-2007″)

A possibly neat use of Ajax would be to modify the creation of an invitation so that when the user invites to a playdate (/invitations/new) the page would detect when the playdate drop-down is modified, and then indicate dynamically (through an update of a <div>) who is already invited, and/or who has already accepted.

Yet another cool effect is to accept the form for the addition of a playdate, and then update the table showing all of the playdates right in place, with the newly-added playdate. One neat thing people do with this kind of update is to use the “yellow fade” effect to highlight the playdate that has just been added (Google for yellow fade effect to learn more about this).

By all means, write e-mail to the course list if you have other ideas. Amy and I are not the biggest Ajax people, so we would likely learn from your ideas in this department.

The best implementations will also ensure that your app degrades gracefully for those users who have disabled javascript or may be accessing the app through a non-standard browser. Be sure to mention anything you do in this regard in your writeup. If you don’t ensure graceful degradation, your writeup should explain why you don’t think it’s important to do so in a way that your ‘product people’ will understand and agree with.

[Difficulty: 5; Learning: 5; App: 2]

3. REST. Provide a REST interface for at least one of the models. Location would be a good place to start. More ambitious would be to get the “schedule” listing, in some form. The best implementations will implement nested resources, so that one can say /users/5/playdates or /users/5/playdate/10 and so forth. The very, very best implementations will use the UUID idea (see above under the required e-mail feature) so that the user id is not given. E.g., /users/OEeaw-64kC1p5XBcfjn_-F1HPPg/playdates/12 — this way you have a certain measure of “security by obscurity”).

[Difficulty: 7; Learning: 7; App: 4]

4. Implement the answer you gave for the question in Assignment 4.

[Difficulty: 3; Learning: 2; App: ?]

5. Add the ability to upload photos of the users and children. Photos of children should only be viewable by other users whose children are participating in a playdate with the that child. You may use the strategy outlined in AWDR (pp. 501ff), or use the attachment_fu plugin. See this tutorial: http://clarkware.com/cgi/blosxom/2007/02/24#FileUploadFu

Tip: For attachment_fu, on Windows, use RMagick.

If you plan to do this feature, you should probably do it first, because it may turn out that the install of ImageMagick is problematic.

[Difficulty: 3; Learning: 2; App: 4]

6. Implement ratings

There are a lot of things worth “rating” in CCC. Users might rate playdates, locations, the organizer of the playdate . . . There are a lot of ways to do this. You might try to implement it with your own design, and if you have a good idea for it, try it. There is also a plugin: acts_as_rateable (http://agilewebdevelopment.com/plugins/acts_as_rateable). You may find that the plugin limits you. For example, if you have two children, should you get two votes? etc. If you find the plugin limiting, you may need to decide whether to continue using the plugin itself as-is, use it but extend it, or take the general idea of the plugin and implement your own version. Be sure to explain all the choices you made in the writeup. If you choose to extend the plugin, it will be especially important to point out the changes you’ve made in the writeup, because other rails developers will assume the standard plugin functionality unless told otherwise.

It might be interesting to blend this with the Ajax option, so that ratings are applied immediately when someone clicks on a list of stars or some such.

[Difficulty: 7 (to get it right); Learning: 2; App: 3]

7. Something else. You must get approval from your grader. The original deadline for this was Dec. 19, but if you discover something you really want to try, we will consider it, though our bias will be to say “no” at this late date. If you are adapting Assignment 5 for the final project, you may only use one self-defined feature.

[Difficulty: ?; Learning: ?; App: ?]

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Login