Planning the 90 minutes

Part of the free Low-Level Design course on LogicWiz, in the chapter: The machine-coding round. The class-diagram exercises run in the app.

Week 11: Minute 70 and nothing runs

"It is minute 70. You have eleven classes and no main method. What do I run?"

Priya, ending a mock machine-coding round


Where 90 minutes go

Priya gave Arjun a mock problem: "Build SwiftKart's rider dispatch. Riders come on duty. Customers place orders. Assign a free rider to each order, and mark it delivered."

Arjun started well. Then he spent 30 minutes on a perfect class diagram. He wrote a generic Repository<T, ID> with paging. He began setting up Spring Boot and a database. At minute 70, nothing ran.

"I wanted to show I know real tools," he said. "Interviewers want to see a database."

They do not. A machine-coding round asks for a working, well-structured program in about 90 minutes, run on your laptop. The interviewer grades what runs and how it is organised. Setup time for a framework or a database earns nothing. It also leaves you less time for the parts that are graded.

The fix is a plan you follow every time, with a clock:

flowchart TD
  A["0 to 10 min: clarify and write the scope"] --> B["10 to 25 min: models, enums, interfaces"]
  B --> C["25 to 60 min: services and in-memory repositories"]
  C --> D["60 to 75 min: main demo, run it end to end"]
  D --> E["75 to 90 min: edge cases, one extension, tidy names"]

The order matters more than the exact minutes. Something must run by minute 75, even if it is small.

Set yourself three checkpoints and look at the clock at each one:

  • Minute 25: the models and interfaces compile.
  • Minute 60: one full flow runs, from placing an order to assigning a rider.
  • Minute 75: the main demo prints a success and a failure.

If you miss a checkpoint, cut scope at once. Drop a feature from your list, and tell the interviewer which one and why. Interviewers respect a clear cut much more than a late rush.

Minutes 0 to 10: clarify and write the scope down

Ask questions until you can list what the program must do. For rider dispatch, Arjun asked:

  • Is there one city zone or many? (Assume one.)
  • How do we pick a rider: nearest, or any free one? (Any free one first.)
  • Can an order be cancelled? (Out of scope.)
  • Is it a command-line program, or do we need an API? (Command line is fine.)

Then write the answers at the top of your main file as a comment. This becomes your contract. When you feel the pull to build something extra, check the list. If it is not there, you do not build it now.

💡 Tip: Say your assumptions out loud as you write them. The interviewer can correct you in minute 5, not minute 60.

Minutes 10 to 25: models, interfaces, then a skeleton

Start with the models: plain classes that hold data and guard their own rules, such as Rider and Order. Use an enum for fixed sets of values, such as order status. A string status lets typos like "DELIVERD" in; an enum does not.

Next write the interfaces for storage. A repository is a class whose only job is to store and find one kind of object. Here is the important part. The service depends on the repository interface. Only main knows which implementation is used.

public enum OrderStatus { PLACED, ASSIGNED, DELIVERED }

public interface RiderRepository {
    void save(Rider rider);
    List<Rider> findFree();
}

public interface OrderRepository {
    void save(Order order);
    Optional<Order> findById(String id);
}

These take five minutes and give the whole program its shape. Write method signatures with empty bodies if you need to. A skeleton that compiles is worth more than a diagram that does not.

Try it on the board. The starter is Arjun's first attempt: one class that does everything. Split it into a service, repository interfaces, an in-memory implementation and models.

Minutes 25 to 60: the core, kept in memory

An in-memory repository stores objects in a map inside the program. Nothing is saved to disk, and that is fine for 90 minutes. Because the service only sees the interface, you could add a MySQL repository later without touching the service. Say that sentence to the interviewer. It shows you know why the interface is there.

public class InMemoryRiderRepository implements RiderRepository {
    private final Map<String, Rider> riders = new ConcurrentHashMap<>();

    public void save(Rider rider) {
        riders.put(rider.id(), rider);
    }

    public List<Rider> findFree() {
        return riders.values().stream().filter(Rider::isFree).toList();
    }
}

Now write the main use case in the service. Do the happy path first: the normal case where every input is valid. Then add the errors that matter.

public synchronized Rider assignRider(String orderId) {
    Order order = orders.findById(orderId)
        .orElseThrow(() -> new IllegalArgumentException("No order " + orderId));
    Rider rider = riders.findFree().stream().findFirst()
        .orElseThrow(() -> new IllegalStateException("No free rider"));
    rider.markBusy();
    order.assignTo(rider.id());
    return rider;
}

Work in small steps. Write one method, run main, then write the next. A compile error found after five lines takes a minute to fix. One found after two hundred lines can take twenty.

Notice synchronized. Finding a free rider and marking them busy is check-then-act, from Week 10. Two orders must not get the same rider. Mention it even if the interviewer does not ask.

Minutes 60 to 90: a main demo, and what to skip

A main demo is a main method that builds the objects and runs the main flows, printing what happens. It is the first thing the interviewer runs.

public static void main(String[] args) {
    RiderRepository riders = new InMemoryRiderRepository();
    OrderRepository orders = new InMemoryOrderRepository();
    DispatchService dispatch = new DispatchService(riders, orders);

    riders.save(new Rider("R1", "Koramangala"));
    Order order = dispatch.placeOrder("C42", List.of("milk", "bread"));
    Rider rider = dispatch.assignRider(order.id());
    System.out.println(order.id() + " assigned to " + rider.id());

    try {
        dispatch.assignRider(dispatch.placeOrder("C43", List.of("eggs")).id());
    } catch (IllegalStateException e) {
        System.out.println("Rejected as expected: " + e.getMessage());
    }
}

It shows one success and one clear failure. That is often enough to prove the design works.

What to skip, unless the interviewer asks for it:

  • A real database, Spring, or any web framework.
  • A user interface. Printed lines are enough.
  • Login, logging libraries and configuration files.
  • Generic base classes "for later". Build for the requirements on your list.

Do not skip error handling, clear names or thread safety on shared state. Those are graded.

📌 Summary: Clarify and write the scope first. Write models and repository interfaces early, keep data in memory behind them, and have a main demo running by minute 75.

What Arjun learns next

Arjun now has a plan for the clock. But what exactly is the interviewer writing down while he codes? Next lesson: the rubric, small tests, and how to handle "now add X" without breaking what works.

Check your understanding

  1. It is minute 65. Arjun has a full class diagram and half-written services, but nothing compiles yet. What should he do next?
  2. Why should `DispatchService` hold a `RiderRepository` interface instead of an `InMemoryRiderRepository`?
  3. A candidate spends the first 20 minutes setting up Spring Boot and an H2 database "to look professional". What is the main cost?
  4. Arjun's `Order` has `status` as a `String`. Priya asks him to change it. What is the best reason?