Skip to content

Thinking in things

50 minutesWeek 1, session 1No prerequisites

By the end of this page you can look at a problem and describe it as a set of things that know something and can be asked to do something, rather than as a list of steps. You can also say who should be responsible for each rule in a system.

There is no Java on this page. Not one line. This session is about a way of seeing a problem, and you cannot see it clearly while you are also worrying about semicolons. The code starts in session 2.

A cash machine, told twice

Here is a withdrawal at a cash machine, described the way you have always described programs.

Read the card. Look up the account. Check that the balance is enough. Check the daily limit. Subtract the amount. Count out the notes. Write a line in the log.

Seven steps in order. You could write that today.

Now here is the same withdrawal, described differently.

There is a card, which knows whose account it belongs to. There is an account, which knows its balance and decides whether a withdrawal is allowed. There is a cash drawer, which knows how many notes it holds and hands them out. There is a log, which records what happened.

The machine asks the card whose account this is. It asks the account to allow a withdrawal of fifty euro. The account decides, and says yes or no. If yes, the machine asks the drawer for the notes and tells the log.

Same machine. Same money. Nothing has been added and nothing has been removed.

What changed is where you put the boundaries. The first description cuts the problem into steps. The second cuts it into things.

That is the whole paradigm. Everything else this semester is consequences.

One problem cut into steps, and the same problem cut into thingsThe upper half shows five steps in a row, each joined by a line to a single shared store of data underneath, and the lines cross one another. The lower half shows three boxes named Card, Account and Cash drawer, each listing what it knows and what it does, joined to each other by two connections.Cut into stepsread cardcheck limitsubtractdispensewrite logthe balance, the daily limit, the notes, the logEvery step needs the data, so the data belongs to nobody in particular.Cut into thingsCardAccountCash drawerknows: whoseknows: balanceknows: notes leftdoes: identifydoes: allow, refusedoes: hand outEach thing keeps what it knows and decides what it does.

Look at the top half again. Five steps, one pile of data, and every step reaching into it. Nothing in that picture is responsible for the balance. The balance is just lying there.

A thing knows, and a thing does

An object is not complicated. It is two things bolted together, and it is worth saying the definition plainly because everything else rests on it.

An object holds what it knows and what it doesA single box named Account divided into two columns. The left column lists what it knows: the balance, who owns it, whether it is frozen. The right column lists what it does: accept a deposit, allow a withdrawal, refuse one.AccountIt knowsIt doesthe balancewho owns itif it is frozenaccept a depositallow a withdrawalrefuse oneWhat it knows is its state. What it does is its behaviour. One thing holds both.

The left column is called state. The right column is called behaviour. Those are the only two words you need this week.

Notice the third item on the right. An account can refuse. That is not decoration, it is the point. A thing that can only hand over its data is a container. A thing that can say no is an object.

Who is responsible?

Here is the question that turns this from a nice picture into a design skill.

Take any rule in the system. "A withdrawal cannot exceed the balance." Then ask two things.

Who should know this? The rule is about a balance. One thing in the system owns a balance. So the account should know it.

Who should decide? Whoever knows. If the account knows the balance and knows the rule, the account decides. Nobody else needs to.

Work through the cash machine and it resolves quickly. The daily limit is about the card, so the card knows it. How many notes are left is about the drawer, so the drawer decides whether it can pay out. The machine itself knows almost nothing. It just asks the right thing each time.

That is why "where does this code go" stops being a matter of taste. The code goes where the data is, because that is the only place the decision can be made honestly.

Verbs are not things

The most common first design has a class called WithdrawalManager or TransactionHandler or BalanceProcessor. It feels right, because withdrawing is clearly important.

Ask what it knows. Usually the answer is nothing. It holds no data of its own, so it spends its whole life reaching into other objects and changing their numbers for them. That is a step wearing a noun's name, and you have rebuilt the top half of the diagram with extra files.

If a class ends in Manager, Handler, Processor or Helper, stop and ask what it knows. There are real exceptions and you will meet one in Module 2, but they are exceptions and they still own something.

Ask, do not take

The second half of the paradigm, and the half most courses skip.

You do not reach into someone's wallet and remove fifty euro. You ask them to pay you, and they decide whether they can. If they cannot, they say so. The money never leaves without the owner's agreement, and the owner is the only one who has to know how much is in there.

Programs work the same way, or they should.

Reaching into another object compared with sending it a requestIn the upper half a box named Cashier sends an arrow that passes straight through the wall of a box named Account and changes the balance inside it, with no rule consulted. In the lower half the Cashier sends a request named withdraw to the boundary of the Account, and the Account decides and sends an answer back.TakingCashierAccountbalanceno rule was askedbalance = balance - 50The wall is open. The account never found out, and never agreed.AskingCashierAccountbalancechecks its own rulewithdraw 50yes, or no

In the top picture the cashier knows how an account stores its money, so if that ever changes, the cashier breaks. In the bottom picture the cashier knows only what to ask for. The account can change everything about how it works, and nobody outside notices.

The difference between those two pictures is the difference between a program you can change and one you cannot.

What it costs

This is not free, and you should hear that from me rather than discover it while resenting me.

You will write more files. You will spend time deciding what to call things, and some of those decisions will feel arbitrary. Following what happens during a single operation means reading three small files instead of one big function, which is genuinely harder the first few times.

For a fifty-line script that you will run once and delete, none of this is worth it. Write the steps. Go home.

It becomes worth it the moment somebody changes the requirements, which in this course is every week and at work is every day.

What this is not

\"So we are modelling the real world\"

Nearly, and the gap matters.

You are modelling the problem, not reality. A real bank has buildings, regulators, a marketing department and a coffee machine. None of those belong in your program. And in Module 3 you will build a Transaction and in Module 4 a Controller, neither of which is a thing you could point at in a bank.

Ask what needs to exist for this program to be correct and easy to change. That question keeps working. "What exists in the world" stops working around week six.

\"So object orientation is about inheritance\"

That is the part most courses lead with, which is why people finish them able to recite four words and unable to design anything.

Inheritance is one tool for sharing behaviour between classes, and Module 2 covers it properly, including when using it is a mistake. It is not what objects are for. If you finish this module able to design good classes and unable to spell extends, you are in a better position than the reverse.

\"This is the right way to write software\"

No. It is one way, and this course teaches it because it is the one you will meet most often and because it teaches you to think about design.

In week twelve you will write Java in a different style, where data does not change and you transform it instead of asking it to change itself. Some problems fit that far better. Knowing both, and knowing when each is awkward, is worth more than believing in either.

If you remember one thing. An object is a thing that knows something and can be asked to do something. Designing is deciding who knows what, and therefore who decides what.

Check yourself

Cut a problem you were not shown

A university library lends books to students. A book can be borrowed if a copy is available. A student cannot borrow more than five books at once. Overdue books carry a fine.

On paper. No Java, so nobody can hide behind syntax.

  1. Name three or four things. Not ten.
  2. For each, write what it knows.
  3. For each, write what it does, including at least one thing it can refuse.
  4. Write one sentence describing how a book gets borrowed, using only "X asks Y to ...". No thing is allowed to reach into another and change its data.

Then the hard part. The rule "a student cannot borrow more than five books" needs an owner. Whoever you chose, write down what that thing must already know in order to decide. If it does not know it, your design has a gap. Finding that on paper costs nothing. Finding it in week nine costs a weekend.

Bring it to the seminar. There is more than one defensible answer and the argument is the lesson.

Think about it

  1. Both descriptions of the cash machine are accurate, and the first one is shorter. So what has the second one actually bought, given that the money moves either way? Now suppose the bank adds an overdraft, and then a second kind of account with different rules.

  2. The account can refuse a withdrawal. That means the cashier has to cope with being told no. Has the cashier's job got easier or harder? Answer honestly, then say who you would rather be if the rule changes next month.

  3. You were told to ask what a class knows, and to be suspicious of one that knows nothing. Try to think of something in a program that genuinely has no data of its own but still deserves to exist as a thing. Bring the best example you can find, even if you are not sure it is right.

  4. The cash machine description gave the log its own box. A log only records what other things did. Does it know anything? Does it decide anything? Argue either way, and notice which of your two answers you would defend in front of the room.