InterviewLegend

OOD and Machine Coding

Alex Chen35 min readUpdated 86 real interview reports
In this lesson
  • Run Workday's object-oriented and machine-coding round in order: clarify, name classes, fix signatures, extend, test
  • Build an in-memory, tenant-scoped key-value store as clean Java classes
  • Solve two medium Workday problems: minimum swaps to sort, and a bracket validator

Workday builds enterprise software on Java and Spring, and its most consistently reported technical round reflects that. You get a domain, model it as objects, then make those objects run. The prompt is a small system, such as a ride-hailing app, a payments-and-cards model, an inventory manager, or the multi-tenant storage that a SaaS platform lives on. You clarify what it has to do, draw the classes, and define the methods. You write enough code to make it work. Then the interviewer changes the requirement to see whether your model bends or breaks. This lesson runs that round in order and works three problems from inside it. One is a tenant-scoped key-value store built as a class. The other two are medium algorithm problems that match Workday's easy-to-medium coding bar.

The Workday angle
Workday grades the shape of your objects and the way they survive a new requirement. Algorithmic exotica matter far less, so budget your prep to match. Candidates who pour every hour into hard dynamic programming and then fumble a class diagram, or return a mutable list where the follow-up wanted an immutable one, get filtered out despite strong puzzle skills. The coding bar itself is correctness, clean Java, and edge cases you name before the interviewer does. The distinctive weight lands on modeling a domain as classes and defending it as the requirements move under you. Rehearse the design-then-build motion until it is muscle memory, then keep your algorithm reps at a comfortable medium rather than chasing the hard tier.

How Workday runs the OOD and machine-coding round

The round moves through five beats. Do them in order, and don't start typing the moment you hear the domain. First, clarify. Restate what the system must do and pin down the operations and their contracts. What does a read return when the key is absent? Does a delete report whether it removed anything? Does an update replace or append? A minute of clarifying questions reads as senior signal. Nobody takes it as stalling. Second, name the classes and interfaces. Identify the entities: the one that owns state and the ones that model records. Say the relationships and cardinality out loud. One tenant owns many keys. One customer owns many cards.

Third, fix the method signatures before the bodies. Decide the public surface, the arguments, the return types, and what each method promises, because the signatures are the contract the interviewer will push on. Fourth, build extensibility in from the start by keeping responsibilities separate and state private, so that when the requirement changes you add a class or a field rather than rewrite the core. Fifth, back it with tests, or at minimum narrate the cases you would write: the empty read, the overwrite, the double delete, the isolation boundary. Workday's interviewers reward a small system you can defend as it changes far more than a clever one-shot answer.

A machine-coding answer at Workday looks like Java that would survive code review. Pseudocode falls short. The first problem below takes this shape as a Java class: state kept private, a nested map for per-tenant isolation, and methods whose contracts are obvious from their signatures.

java
final class TenantStore {
// tenant id -> that tenant's own isolated key/value bucket
private final Map<String, Map<String, String>> data = new HashMap<>();
void put(String tenant, String key, String value) {
data.computeIfAbsent(tenant, t -> new HashMap<>()).put(key, value);
}
String get(String tenant, String key) {
Map<String, String> bucket = data.get(tenant);
return bucket == null ? null : bucket.get(key);
}
boolean delete(String tenant, String key) {
Map<String, String> bucket = data.get(tenant);
return bucket != null && bucket.remove(key) != null;
}
List<String> keys(String tenant) {
Map<String, String> bucket = data.get(tenant);
if (bucket == null) return List.of();
List<String> out = new ArrayList<>(bucket.keySet());
Collections.sort(out);
return out;
}
}

The through-line of this round is one question: does your design absorb the next requirement. Keep state private, keep each class doing one job, and name the contract of every method. Then, when the interviewer bounds the history or adds a concurrent writer, you extend the model instead of tearing it down.

Machine coding: a tenant-scoped key-value store

The cleanest way to feel the machine-coding round is to build the thing Workday's own product is made of: isolated storage per tenant. Many customers share one running system, and no customer may ever see another's data. The same key can hold different values under different tenants. A read for one tenant must be blind to the rest. Stripped of the SaaS framing, this is a map of maps behind a small class, with put, get, delete, and keys as its public surface. What the interviewer watches is whether you keep the isolation airtight and the method contracts honest.

1

Tenant-Scoped Key-Value Store

MediumCommonly asked
Problem
Design an in-memory TenantStore that isolates every tenant's data. Implement four methods:

- put(tenant, key, value) stores value under key for that tenant, overwriting any existing value. It returns nothing.
- get(tenant, key) returns the stored value, or null if that tenant has no such key.
- delete(tenant, key) removes the key for that tenant and returns true, or returns false if the key was not there.
- keys(tenant) returns that tenant's keys as a list sorted ascending, or an empty list if the tenant is unknown.

The same key may exist under different tenants with different values, and no operation for one tenant may ever read or change another tenant's data.

Input: put("acme","currency","USD"); put("hooli","currency","EUR"); get("acme","currency"); get("hooli","currency")

Output: "USD", then "EUR"

Both tenants store the key "currency", but each read sees only its own tenant’s value, so the buckets never bleed into each other.

Input: put("acme","locale","en_US"); delete("acme","locale"); delete("acme","locale")

Output: true, then false

The first delete removes the key and reports true. The second finds nothing to remove and reports false.

How this uses the pattern

Keep a map from tenant id to that tenant’s own map of key to value. Every method looks up the tenant bucket first, so isolation falls out for free: a missing tenant is simply an absent outer entry. Sort the keys only at read time in keys(), and skip sorting on every write.

Tenant-Scoped Key-Value Store

Loading...
Click "Run" to execute your code

Test Cases

Input: [["TenantStore",[]],["put",["acme","currency","USD"]],["put",["acme","locale","en_US"]],["put",["hooli","currency","EUR"]],["get",["acme","currency"]],["get",["hooli","currency"]],["get",["acme","timezone"]],["keys",["acme"]],["delete",["acme","locale"]],["delete",["acme","locale"]],["keys",["acme"]]]Expected: [null,null,null,null,"USD","EUR",null,["currency","locale"],true,false,["currency"]]
Input: [["TenantStore",[]],["get",["ghost","x"]],["keys",["ghost"]],["delete",["ghost","x"]]]Expected: [null,null,[],false]
Input: [["TenantStore",[]],["put",["t","k","v1"]],["put",["t","k","v2"]],["get",["t","k"]]]Expected: [null,null,null,"v2"]
Input: [["TenantStore",[]],["put",["a","role","admin"]],["put",["b","role","viewer"]],["get",["a","role"]],["get",["b","role"]],["delete",["a","role"]],["get",["a","role"]],["get",["b","role"]]]Expected: [null,null,null,"admin","viewer",true,null,"viewer"]
Input: [["TenantStore",[]],["put",["z","gamma","3"]],["put",["z","alpha","1"]],["put",["z","beta","2"]],["keys",["z"]]]Expected: [null,null,null,null,["alpha","beta","gamma"]]
Input: [["TenantStore",[]],["put",["one","only","1"]],["keys",["one"]],["get",["one","only"]]]Expected: [null,null,["only"],"1"]
The Workday angle
The tenant store is Workday's platform in miniature, and isolation is the property the round is really testing. Multi-tenant SaaS lives or dies on the guarantee that one customer's data is invisible to another. That's why the map-of-maps matters. The outer key is the boundary. Interviewers press on the contracts next. What does get return for an unknown tenant? Is delete idempotent? Is keys stable? Clean answers show you designed the surface on purpose, instead of grabbing the first structure that compiled.
Take it further
Now two requests write the same tenant at once. Ask how you would keep the store correct under concurrent writers, since a plain HashMap corrupts under simultaneous mutation. The Java answer is a ConcurrentHashMap for both the outer and inner maps, with computeIfAbsent creating a tenant bucket atomically so two threads cannot each install a fresh one and lose a write. That is the same immutability-and-concurrency pressure Workday puts on the document-version task, applied to storage.

Minimum swaps to sort an array

Beside the design round sits Workday's straight algorithm bar. It's easy to medium, and graded on a correct, clean solution more than raw speed. A reported phone-screen prompt is the minimum number of moves to sort an array, and the sharpest version asks for the fewest swaps of any two elements. The brute force keeps swapping the smallest misplaced element home, and it happens to be optimal. The elegant answer reads the count off the permutation directly. An array is a set of cycles, and each cycle of length k costs exactly k minus one swaps.

2

Minimum Swaps to Sort an Array

MediumSometimes asked
Problem
You are given an array arr of distinct integers. In one move you may swap the elements at any two positions. Return the minimum number of swaps needed to sort the array into ascending order.

Because every element is distinct, there is exactly one sorted arrangement, and the question is how few swaps reach it.

Input: arr = [4,3,2,1]

Output: 2

Swap 4 and 1, then swap 3 and 2, and the array is sorted. No single swap and no zero-swap arrangement can do it, so two is minimal.

Input: arr = [2,3,1]

Output: 2

The three elements form one cycle, and a cycle of length three costs two swaps.

How this uses the pattern

Map each element to the position it must end up in, which turns the array into a permutation. Decompose that permutation into cycles: elements already in place are cycles of length one and cost nothing, and a cycle of length k needs exactly k minus one swaps to resolve.

Minimum Swaps to Sort an Array

Loading...
Click "Run" to execute your code

Test Cases

Input: [[4,3,2,1]]Expected: 2
Input: [[1,2,3]]Expected: 0
Input: [[2,3,1]]Expected: 2
Input: [[5]]Expected: 0
Input: [[2,1]]Expected: 1
Input: [[1,5,4,3,2]]Expected: 2
The Workday angle
Minimum swaps sits at Workday's easy-to-medium coding bar, with a clean invariant underneath. The round rewards that kind of reasoning over speed. A naive read simulates swaps. What the interviewer wants is a different insight: sorting is a permutation, and a permutation is a disjoint union of cycles. Say that out loud and count the cycles in one pass. You get the optimal answer and the argument for why it's optimal. Workday grades that clear reasoning above a fast brute force.
Take it further
What if the values are not distinct? Ties break the one-to-one mapping from value to target position, so the cycle count is no longer unique and the clean formula stops being exact. Resolve ties with a stable tiebreak. Pair equal values to the sorted slots that keep the most elements fixed. That takes a more careful assignment than a plain cycle walk. Flagging that the whole method rests on distinct values is part of the signal too.

A bracket validator that reports where it fails

The valid-parentheses validator is a reported Workday coding prompt, and interviewers rarely leave it at a plain true or false. A sharper version also asks where the string first goes wrong. That turns the classic stack into one that carries indices. The structure is the same push-openers, match-closers scan, and the twist is deciding, precisely, which position to blame when a closer has no partner or an opener is never closed.

3

Bracket Validator: First Failing Index

MediumCommonly asked
Problem
You are given a string s made only of the six bracket characters ()[]{}. Return -1 if the string is balanced. Otherwise return the 0-based index of the first character where validation fails, defined as:

- a closing bracket that has no matching open bracket, or whose most recent unmatched opener is the wrong type, fails at its own index, or
- if the scan finishes with unmatched openers left over, the failure is the index of the earliest such opener.

An empty string is balanced, so it returns -1.

Input: s = "([)]"

Output: 2

At index 2 the closer ) meets a most-recent opener of [, which is the wrong type, so validation fails there.

Input: s = "(()"

Output: 0

The scan ends with the opener at index 0 still unmatched, so its index is the reported failure.

How this uses the pattern

Push each opener with its index onto a stack. On a closer, if the stack is empty or its top is the wrong type, that closer’s index is the answer. If the scan completes with the stack non-empty, the answer is the index stored at the bottom of the stack, the earliest opener that never closed.

Bracket Validator: First Failing Index

Loading...
Click "Run" to execute your code

Test Cases

Input: ["([])"]Expected: -1
Input: ["([)]"]Expected: 2
Input: ["(()"]Expected: 0
Input: ["))"]Expected: 0
Input: [""]Expected: -1
Input: ["()]"]Expected: 2
The Workday angle
The bracket scan is a stack in a Workday costume, and the follow-up is where the round earns its memory reputation. The reported prompt attaches a pointed question: if the input is huge and the heap overflows, how do you still validate it. That turns the exercise from an algorithm into a resource-awareness test. Workday often presses a working solution on how it behaves under load. Carry indices cleanly first, and you leave yourself room for the harder part.
Take it further
Now the input is enormous and will not fit in memory. A same-type bracket language like only parentheses needs no stack at all, just a running counter that must never dip below zero, which is constant memory. With multiple bracket types, you have to remember the order of openers. You can still stream the input character by character instead of loading it whole. In the pathological all-openers case, the stack is unavoidably large. Name that limit honestly. The interviewer grades whether you separate what needs memory from what doesn't.

Common questions

What does Workday's machine-coding round test?

It tests whether you can turn a domain into clean objects and then defend them when the requirement moves. You clarify the operations and their contracts, name the classes and their relationships, fix the method signatures, keep state private so the model extends cleanly, and back it with the cases you would test. The tenant-store problem above is the shape it takes: a small system where the interviewer will press on isolation, idempotent deletes, and concurrency, so a design that answers those cleanly is the signal.

How hard is the algorithm bar next to the design round?

Easy to medium. It's graded on correctness, clean code, and edge cases you name yourself. Minimum swaps to sort rewards seeing the cycle structure and stating why a k-cycle costs k minus one. The bracket validator rewards a careful stack that carries indices, plus a sensible answer to the memory follow-up. Both reward clear reasoning about the invariant and the resource behavior over raw speed.

Should I write these in Java?

Yes, by default. Workday is a Java and Spring shop, the machine-coding round expects idiomatic Java, and the follow-ups lean on language internals like how a HashMap behaves and how you keep returned objects immutable. Interviewing in Java lets you answer those follow-ups fluently instead of translating them, which is why the static example above is Java even though the runnable solutions here are language-agnostic.

Key Takeaways

  • ✓Workday’s signature round runs in five beats: clarify the operations and contracts, name the classes and interfaces, fix the method signatures, keep state private so the model extends, and back it with tests. The grade is whether your design absorbs the next requirement. A first answer that works is only the start.
  • ✓The tenant-scoped key-value store is the machine-coding round in miniature. A map from tenant to that tenant’s own map makes isolation correct by construction, and the outer key carries the guarantee. The concurrency follow-up (ConcurrentHashMap, atomic bucket creation) is the load pressure Workday always applies.
  • ✓Minimum swaps to sort is a permutation split into cycles, where a cycle of length k costs exactly k minus one swaps. Counting cycles in one pass gives both the optimal answer and the one-line proof of optimality, which Workday grades above a fast brute force.
  • ✓The bracket validator is a stack that carries indices. A closer that cannot match fails at its own index, and leftover openers fail at the earliest one. The huge-input heap-overflow follow-up is the memory-awareness test Workday is known for.
Had your Workday interview?Tell us what they asked. Reviewed before it goes in, never with your name.
Workday interview guide

Know what Workday asks before you walk in.

10 coding · 3 system design · 15 behavioral questions

Get Premium$49 a year · Cancel anytime
Or start freeNo card.

Get their questions first.

InterviewLegend is independent and not affiliated with or endorsed by any company it covers.