Domain Modeling


I haven’t drawn any entity DB diagrams since college, so I had to brush up a little with a few articles.

I’ve drawn some simple diagrams for the DB design, which encompasses the feature set up to 0.1.0. I also threw in a few tables for the Study Group entity, even though that’s not slated to appear yet in 0.1.0. Doing the diagrams made me realize a few things that were missing from the user stories.

DBDiagram

First, I realized that I hadn’t thought through carefully about the relationships between some of the entities… for example, the fact that a class could (and should have) several study groups that belong to it, and that the entity that a study group should actually belong to is the class (the course, that is). In the “real world”, the teacher would be creating a class, and then creating study groups for that class, and assigning students to them. Student are only in one study group for a particular class, but their study groups will likely be different in other classes.

Second, just a small thing, but it would be nice if the user had an alias, instead of showing their first name and last name, and/or their email as their username. This should be added into the My Account story.

Ah, feature creep.

I’ve just finished a desktop application that solves the riverboat velocity problems. The reason behind creating this app was to explore how the problem domain would be programmed, and to also serve as a basis for how the problem should be solved when it is presented using ASP. As I’ve mentioned before, the UI — whether a website or a desktop window — should not have an effect on how the problem is actually modeled and solved; therefore, I should theoretically be able to use the same class (or module) I designed and plug it into the website.

Here are screenshots from the app. First, we have a picture of the app when it starts:

Riverboat Problem Solver Startup

After the Solve button is clicked, the solutions appear on the bottom of the screen:

Riverboat Problem Solver Solution to Defaults

Any of the parameters to the problem can be changed. The new solutions will appear when the Solve button is pressed again:

Riverboat Problem Solver Solution to New Problem

Implementing this application actually brought up a number of hairy issues. One thing that I realized is that the “answers” were not as straightforward as I thought. For example, for the time to cross the river, you could say that the answer is 1.25 hours. But there are actually 3 sub-answers that make up that answer — the value 1.25, the units the value is in (hours), and how many significant digits are shown as the result. I remember taking physics, and my teacher (and the textbook) heavily emphasizing expressing the appropriate amount of significant digits, based on the information known.

What I originally thought of as one output is actually 3 outputs. For the units, we can go in two different directions — we can allow the student to specify their units, or we can force the student to answer in the units specified. The latter is commonplace in the physics classroom, so we can get away with that. The significant digits issue is a much harder one, though, for many reasons, including the fact that intermediate calculations need to carry an extra significant digit, which is eventually rounded with the final result. If we are truly modeling problems and sub-problems as recursive composites (i.e. problems that have sub-problems which are problem in and of themselves), the “correct” answer for a given problem, in terms of significant digits, is dependent on whether that problem is the original problem or a sub-problem. In this sense, the problem has to be aware of itself and what it is, which complicates things.

For now, it seems the simplest route to ignore the significant digit issue, but we may revisit it if time allows, as our “solution” wouldn’t pass muster with physics teachers. But this isn’t the point of the project. :)

Finally, the way things are implemented currently aren’t abstract enough. That is to say, I’ve solved the riverboat problem, but if I had to solve a different kind of problem, I could use basically nothing from what code I’ve written. Ideally, we want a framework for solving problems and making solutions so that the same framework could be used for different kinds of problems in different kinds of classes.

I’ve really wanted to design this framework now, but again, in the interests of time, and because this isn’t the point of this project, we’re going to forego designing a very detailed, robust framework, and just try to be as flexible as possible while putting priority on getting the site as a whole working.

Now that I’ve selected the riverboat velocity problems as the problem domain, and understood what is involved with solving the problem, I need to come up with a way to abstract the solving of this problem. As it turns out, the concept of solving a mathematically-based problem is inherently the same as what a computer procedure or function does. You have a set of inputs, which you run through some kind of algorithm, and produce a set of desired outputs.

Modeling a problem

Accordingly, I could just map a riverboat velocity problem onto this directly, such as a programming procedure akin to:

Vector CalculateResultantVelocity(Vector boatVelocity,
      Vector currentVelocity);

The strength of this approach is that it’s simple, straightforward, and easy to code. But there are several problems with this approach. The biggest weakness is that it’s just too simple. The reality is that many problems in physics (and other domains) are actually composed of other smaller problems. You often find that solving a problem involves breaking down a large problem into several steps or components and solving them. For example, here is a diagram of a problem which is actually done in two steps.

Under the hood of a problem

Each step has its associated input and output — and notice that the output of the first subproblem becomes the input of the second subproblem. Even a simple equation like

a = 2 * ( 3 + 2 ) – 4 / 2

can be broken down to individual arithmetic operations, arranged in particular orders. The point is that for a complex problem, part of the solution is breaking down that problem into appropriate components, each of which are simpler to solve.

So what does this look like for a riverboat velocity problem? Here’s a diagram for calculating the resultant velocity of the boat and river current:

Modeling the resultant velocity problem

There are several inputs — the speed and direction of both the boat and the river current. The output we are aiming for is the resultant velocity, both speed and direction. As it turns out, this problem can be broken into two parallel components — calculating the resultant magnitude of the velocity (or speed), and calculating the resultant direction. The first problem only needs the magnitudes to solve, while the 2nd requires all four inputs.

The two respective problems are actually are just geometry/trigonometric calculations applied to a real world situation. You could argue that translating from “Calculate Resultant Magnitude” to “Use Pythagorean Theorem” isn’t a problem — that both algorithms are the same thing mathematically. But you could also argue that part of the problem in solving the real world problem is knowing which formula to apply, and which parameters apply to which information you have. In fact, some of the other riverboat problems require only arithmetic — what students get wrong is which values to plug in.

What consequence does this have for programming these problems? One of the patterns that emerge immediately from looking at the last two diagrams is that the problem and its subproblems are recursive in nature. That is, there really is nothing to distinguish a subproblem vs. its parent problem. They are all just problems, really — they have inputs and outputs, and an associated algorithm that is operated on to convert between the two.

This means, in programming speak, that we’ll probably want to model the “idea” of a problem as a class (actually an interface) that both subproblems and problems derive or implement. And, that a problem can have child problems (the subproblems). I’m not all too sure right now whether a problem also needs to have a reference back to its parent problem, but the answer will probably emerge later as coding begins.

The point of this exercise was to do a little thought before coding, but not so much that we fall into an analysis paralysis funk. It will be interesting what kind of class design eventually emerges after a few iterations on the problem domain, and how flexible it will ultimately be, when trying to add support for other algorithms and problems that are very different.

The title of these updates have subtly been changed from “Weekly Update” to “Project Update.” Well, not so subtly anymore I guess. But since my work schedule seems to fluctuate a lot on a week-to-week basis, the updates won’t be consistently one week apart.

One step forward, two steps back

My project has hit a few snags here and there, but they were inevitable snags, which I suppose is better than avoidable snags. I don’t think that this month’s commitments are in any jeopardy, though. Here is the status of each area:

  1. Develop paper prototypes. I started some sketches for a few pages, but started feeling like I was lacking some context. Then it occurred to me that I’m not following the usual process I’ve come to be used to in my web design consulting, which is to start with a sitemap proposal. Although a sitemap at this point is likely to be changed many times as the site is developed, it helps to have that big picture in mind. The power of the web is in interaction, and so when designing the UI, extra care has to be given to establish the user in the appropriate context.To make a long story short, the plan now is to put a draft sitemap together before I do more work on the paper prototypes, which should be done within the week.
  2. Learn problem domain (DONE). I pretty much have nailed the understanding I need for the riverboat velocity problems I will start with, as referenced in the last post.
  3. Setup development environment. As mentioned earlier, running Visual Studio 2005 and IIS in XP Pro has been insufferably slow on my laptop, which makes me think that I will need to use my more powerful desktop instead as my development machine. The huge problem I have now, though, is that I need to upgrade my desktop to XP Pro. I shelled out a lot of cash to buy an XP Pro upgrade, but there is no way to revert back to XP Home from XP Pro. Essentially I have to do a clean install of XP Home on my laptop to free up my XP Pro license key (Microsoft’s EULA for XP is one install on one computer), because there is no previous OS to fall back to. Which is a huge pain since I need to backup all my files and reinstall all my software. Anyway, it looks like I have no choice, but I’ll need a full day to reinstall in case things don’t go smoothly during the process, so either this weekend or next weekend. I’ll suffer with the laptop until then. The only other thing I need to setup on the development environment is source code control (SVN). I’ll need to setup an SVN server, which I prefer to do on my desktop, after I’ve done the XP Pro upgrade. I already have VS 2005 with Resharper running on my laptop and desktop, so everything else is setup for now.
  4. Finish ASP book. I’ve been reading Microsoft Press’ ASP.NET 2.0 Step by Step book, but liking it less and less as I go through it. It doesn’t seem to be much of a rigorous book, mostly taking the reader through trivial examples. On top of that, following the instructions in the book for one of the chapters is repeatedly causing VS2005 to crash. This is all the more irritating since VS takes over 1 minute to restart on my slow laptop.I’ve decided to skim through the rest of the book, and instead start reading another book, Programming ASP.NET by O’Reilly. I’ve always had good experiences with O’Reilly books, and this one is co-authored by Jesse Liberty, who also wrote Programming C#, which I really liked.
  5. Model problem domain and solve problems algorithmically. I should clarify what this task is. When designing an application, the real design task is to take one’s understanding of the application domain, and figure out how to model it. Any problem that an application is trying to solve should be explainable without reference to program- or implementation-specific details. For example, I should be able to describe how a riverboat velocity problem should be solved, independent of whether it will be solved with a web-based application or a desktop application. I should also be able to program an application component that can solve a given riverboat velocity problem, without any code that deals with web pages. My main goal with this task is to come up with a basic, but robust and flexible design and architecture that will accommodate more than just riverboat velocity problems. My goal is also to implement a component which solves the riverboat velocity problems within the framework of that architecture. Sound too abstract? Hopefully it will make sense in my next planned post, which will introduce my thoughts on the domain model for this problem, and some of the complexities associated with it.

 Upcoming

  • Map out the problem domain
  • Create draft sitemap
  • Start new ASP book
  • Start paper prototypes
  • Migrate XP Pro to desktop machine

Well, I finally took the plunge and sat down to understand what’s involved with solving riverboat problems. Here is the basic premise:

Riverboat Velocity Problem Diagram

A boat is going from one end of a river to another. We assume several ideal conditions; for example, that the river is nice and straight, and that going from one end to another is always the same distance, as long as we are going directly across.

Here is the problem — we know the speed and direction of the boat. But there is also a river current that is perpendicular to the direction of the boat, which is either going up or down the river. So we know what the speed and direction is of the current. Finally, we know the distance between one shoreline of the river to the other.

 There are several questions that can arise from this setup:

  1. From the perspective of an observer standing stationary on the shoreline, what is the effective speed and direction of the boat (also known as the resultant velocity)?
  2. How long does it take to cross the river?
  3. How far upstream or downstream will the boat travel in the process of crossing the river due to the current?
  4. What is the effective distance travelled by the boat in one crossing?

Problem #1 involves vector addition, but actually a much easier form of it, because we already know that the two vectors we are adding are perpendicular (or normal) to each other. This makes the magnitude of the resultant vector easy to calculate with the Pythagorean theorem.

Finding the direction of the resultant vector requires trigonometry. Again, since we know the we have a right triangle, it’s not too hard to calculate the angle. In short, theta, as shown above in the diagram is equal to the inverse tangent of the current speed divided by the boat speed. Or,

theta = inverseTan ( currentSpeed / boatSpeed )

Not too bad.

Problems #2 to #4 are ridiculously simple arithmetic problems involving only multiplication and division. The only difficulty is in understanding the problem correctly and knowing which values to use.

My goal will be to use these 4 problems as a starting template for an instructional unit. There are variations that can complicate the problem. For example, we might ask what angle and velocity the boat should go in order to have a resultant velocity which is perpendicular to the river, and negates whatever drift is caused by the river current. This would definitely be harder, but the immediate goal is to get something working — we can always expand on what we have later.