Module 10 · Capstone: Professional Java Project ⏱ 20 min

Capstone Kickoff: Requirements and Domain Model

By the end of this lesson you will be able to:
  • Translate a written brief into candidate entities, attributes, and relationships
  • Tell a domain model apart from a class diagram, and explain why both exist
  • Sketch a first value-object class in Java from an entity you identified

Every project that fails, fails the same way first: somebody started typing before they understood the problem. In a graded exercise you can guess at the requirements because the test is fixed and waiting. In a real codebase the requirements move, the stakeholders disagree, and the model you build either absorbs that change or cracks under it.

This capstone is different from the lessons before it. There is no single correct line to type. You will take a messy written brief — the kind a client actually sends — and turn it into a domain model: a map of the real-world things your program has to represent. The model is the skeleton everything else hangs on. Get it right and the code almost writes itself; get it wrong and no amount of clever Java will rescue you.

flowchart LR
  A["Written brief<br/>and user stories"] --> B["Highlight the nouns<br/>and the verbs"]
  B --> C["Nouns become entities<br/>verbs become methods"]
  C --> D["Domain model<br/>entities + attributes + links"]
  style D fill:#3776ab,color:#fff
The modelling pipeline: mine the brief for nouns and verbs, then promote nouns to entities and verbs to methods.

The brief: a small lending library

A community library wants software to track its collection. Here is the whole brief, exactly as a volunteer might email it:

We lend books to members. Each book has a title, an author, and the year it was published. A member joins with a name and gets a member number. When a member borrows a book we record who took what and when it is due back. We need to find books by author and see which books a member currently has.

That paragraph is your raw material. It is dense with nouns (book, member, year, name) and verbs (lend, borrow, find, see). Before you write a single class, you will mine it — and the discipline of doing so is the whole point of this lesson.

Nouns become entities, verbs become behaviour

Read the brief hunting for nouns. Book and Member surface immediately, and so does the act of borrowing. Each noun that has its own identity — one you would point at and say this one, not that one — is a candidate entity, destined to become a class. Book and Member qualify; title and year do not, because they describe a book rather than standing on their own.

Verbs are the other half. Find books by author and see which books a member has are actions, so they will become methods later — the things your objects can do. Keep the two channels separate for now: nouns map to structure, verbs map to behaviour. Mixing them up is how classes grow methods that belong on the wrong object.

Exercise

From the brief above, which noun is a candidate ENTITY — a real thing with its own identity — rather than just an attribute describing something else?

Main.java — a first Book value object, straight from the brief. Real, compiling Java.
public class Main {
    // A Book is a value object: it carries data that identifies one title.
    static class Book {
        private final String title;
        private final String author;
        private final int year;

        Book(String title, String author, int year) {
            this.title = title;
            this.author = author;
            this.year = year;
        }

        String getTitle()  { return title; }
        String getAuthor() { return author; }
        int getYear()      { return year; }

        public String toString() {
            return title + " by " + author + " (" + year + ")";
        }
    }

    public static void main(String[] args) {
        Book first = new Book("Clean Code", "Robert Martin", 2008);
        System.out.println(first);
    }
}
Exercise

The object holds what the constructor was given. Read the program and predict its exact output (three lines).

public class Main {
    static class Book {
        private final String title;
        private final String author;
        private final int year;

        Book(String title, String author, int year) {
            this.title = title;
            this.author = author;
            this.year = year;
        }

        String getTitle()  { return title; }
        String getAuthor() { return author; }
        int getYear()      { return year; }
    }

    public static void main(String[] args) {
        Book b = new Book("Clean Code", "Robert Martin", 2008);
        System.out.println(b.getTitle());
        System.out.println(b.getAuthor());
        System.out.println(b.getYear());
    }
}
erDiagram
  BOOK ||--o{ LOAN : has
  MEMBER ||--o{ LOAN : makes
  BOOK {
    string title
    string author
    int year
  }
  MEMBER {
    string name
    int memberId
  }
  LOAN {
    string dueOn
  }
An entity-relationship view of the library: a Member makes many Loans, and a Book is involved in many Loans.

Three views of the same system

The model you just sketched is not the program — it is one of three views, each at a different distance. The domain model lives in the world: a library has books and members, and members borrow books. A class diagram is the same idea tightened into software terms: Book has fields title and year, and a Loan references a Book and a Member. The code is the diagram made executable.

Beginners skip straight to the code and lose the why. Drawing the model first forces every assumption into the open — is a loan its own thing, or just a date stamped on a book? — where a stakeholder can correct it for the price of an eraser, not a refactor.

Speak the domain's language

The names you choose are not cosmetic. If a volunteer calls a borrower a member, your class should be Member, not User or AccountHolder — because the moment the code's vocabulary drifts from the domain's, every conversation between developers and stakeholders needs a translation step. This practice goes by the name ubiquitous language: one shared vocabulary that appears in the brief, the model, and the code.

It also points the model toward honesty. If you cannot name an entity without borrowing a word from databases or frameworks — Record, Row, DTO — that is usually a sign you have not yet understood what the thing is in the domain.

Exercise

A volunteer says 'just make a loans table and we are done.' Why is that premature at the modelling stage?

The classic trap: attribute or entity?

Modelling has a recurring failure: confusing a thing that describes with a thing that is. An ISBN looks important, so beginners promote it to an Isbn entity with its own class and behaviour. But an ISBN has no lifecycle of its own — it is never created independently, never lent out, and exists only to identify a book. It is an attribute, a field on Book, not an entity.

The test is identity and lifecycle. If something is created, changed, and tracked through time on its own, model it as an entity. If it merely describes one thing, keep it as a field. Getting this wrong multiplies your classes — and every extra class is a place for bugs to hide.

Exercise

An ISBN uniquely identifies a book and even has a format you can validate. Should it be its own Isbn ENTITY?

Main.java — a Loan models the relationship between a Book and a Member. Real, compiling Java.
public class Main {
    static class Book {
        private final String title;
        Book(String title) { this.title = title; }
        String getTitle() { return title; }
    }

    static class Member {
        private final String name;
        Member(String name) { this.name = name; }
        String getName() { return name; }
    }

    // A Loan models the relationship: one Book lent to one Member.
    static class Loan {
        private final Book book;
        private final Member member;

        Loan(Book book, Member member) {
            this.book = book;
            this.member = member;
        }

        String describe() {
            return member.getName() + " borrowed " + book.getTitle();
        }
    }

    public static void main(String[] args) {
        Book b = new Book("Dune");
        Member m = new Member("Mara");
        Loan loan = new Loan(b, m);
        System.out.println(loan.describe());
    }
}
flowchart TD
  Q["A noun appeared<br/>in the brief"] --> D{"Does it have its own<br/>identity and lifecycle?"}
  D -->|"yes"| E["Model as an ENTITY<br/>its own class"]
  D -->|"no"| A["Model as an ATTRIBUTE<br/>a field on another class"]
  style E fill:#3776ab,color:#fff
  style A fill:#b45309,color:#fff
The attribute-or-entity test: does the noun have its own identity and lifecycle?
Exercise

Two books, same data. Each is its own object. Predict all three lines before you check — this tests whether a noun you model as an entity keeps separate state per instance.

public class Main {
    static class Book {
        String title;
        int copies;

        Book(String title, int copies) {
            this.title = title;
            this.copies = copies;
        }
    }

    public static void main(String[] args) {
        Book a = new Book("Dune", 3);
        Book b = new Book("Dune", 3);
        b.copies = 5;
        System.out.println(a.copies);
        System.out.println(b.copies);
        System.out.println(a == b);
    }
}

Recap

  • A domain model maps the real-world things your program represents; it is drawn before code so assumptions are cheap to change.
  • Mine the brief: nouns with their own identity become entities (classes); verbs become methods; descriptive nouns become attributes (fields).
  • The domain model, a class diagram, and the code are three views of one system at different distances — model the problem first, never the storage.
  • The attribute-or-entity test is identity and lifecycle: a thing with a life of its own is an entity; a thing that only describes is a field.

In the next milestone you will turn the Book and Member entities into properly encapsulated classes that refuse to hold invalid data.

Checkpoint quiz

In a domain model, what does a verb in the requirements brief (such as 'find books by author') usually become?

Why sketch a domain model before writing any classes?

Go deeper — technical resources