Monday, 2 September 2013

Building an assessment app in two days -- second commit.

The second commit is where I need to start thinking about the app a bit more. We're going to establish a few basic data model classes. They'll change as the rest of the code is written, but this commit will make a start on it.

Our situation gives us a slightly unusual need:

  • The students are all in groups already
  • The software hasn't been written yet, so the students are not in the database
  • We can't use their UQ logins (institutional policy reasons)
  • But we have all the students' GitHub usernames in a spreadsheet

When students log in, they need to be able to get their groups — which means the groups need to be entered before the students have created their accounts in the database.

That means we're going to need a concept of a "pre-enrol", so that when a student has logged in, they can automatically find both the course and their group, in this case using their GitHub username.

Although I'm writing this initially for our course, I'll try to make the data model reasonably general.

Things you'll notice about the data model

  • There are lots of Refs. This is part of my handy library. A ref is a reference to a data object. It might be the object itself; it might be a Future that will return the object when a database fetch has completed. It might be a LazyId if all we have so far is the ID of the object. There are quite a few possibilities for what a Ref can be.

    Ref is a monad, which means that it has flatMap and map methods that I'm going to use extensively, and ensures that at the end of an algorithm I'll still have something that meets Ref's contract.

    It's what I call an "ad-hoc" monad, however, because we haven't predetermined the specific kind of Ref we're going to end up with.

    More information will go up on handy's documentation site (And there's a paper I want to write on this style of app development soon.)

  • Each of the data classes extends HasStringId.

    This means a little more than just that it has a string id. Ref.getId looks for an "implicit argument" that can produce a canonical id for an object. (For instance, so that if you use Integer ids, Ref(classOf[Foo], 10:Int) and Ref(classOf[Foo], "10") resolve to the same item.)

    Within the handy library, there's an appropriate object GetsStringId for handling this for objects whose canonical IDs are Strings.

    (In the database layer, however, we're going to be converting to and from MongoDB's BSONObjectID class. I just don't want to expose object IDs in the API.)

So, in this commit we have some incomplete data classes:

  • User

    A user in the system. This inherits from one in handy-appbase-core, and includes types for Identity and PasswordLogin (though we won't be using the PasswordLogin for now)

  • Identity

    A social login identity, such as a GitHub account. (Or, in time, LTI for logging in directly from Blackboard, but university policy prevents us from doing that yet.)

  • Task

    Well, if we're asking them to do a peer critique, maybe we'll have other tasks for students in time.

  • Course

    A course (we'll try to open this up for others too)

  • Preenrol

    A way of pre-registering students for courses if all you have is a social identity

  • Group

    A group, for the group critique

  • GroupSet

    Sometimes, in courses, students are in more than one group. For instance, they may have a tutorial group as well as a project group. Or their group may change every so often, but you'd like to preserve the historical groups they've been in in the past so you can look back on their previous work.

    GroupSet will support this

  • GPreenrol

    Preenrol for groups

  • Question

    The critique is going to need a survey form of some sort, which will be made up of questions. We'll establish the different kinds of question in a later commit.

    (Likewise, there's an Answer trait)

  • Critique

    A critique

  • CritTask

    The task of doing a critique

No comments: