In the Rippling phone coding interview, I was given a set of expenses and rules. I needed to run every rule against every expense and identify each rule that the expense violated.
An expense looked like this:
{
"expenseId": "1",
"itemId": "Item1",
"expenseType": "Food",
"amountInUsd": 250,
"sellerType": "restaurant",
"sellerName": "ABC restaurant"
}
Example rules included:
- Total expense should not be greater than 175.
- A restaurant seller should not have an expense greater than 45.
- An entertainment expense should not be charged.
The method to implement was:
evaluateRule(List<Rule>, List<Expense>)
For example, a $250 food expense from a restaurant violated both the total-expense limit and the restaurant-seller limit.
The interview focused on how I abstracted and implemented the rules. I considered putting each rule behind a Rule interface or protocol so that every implementation would decide whether an expense violated that rule. We also discussed making the rule engine extensible: adding a rule later should require a new Rule implementation without modifying the existing core logic. Overall, the problem emphasized OOP and extensible design rather than hard-coding a collection of if and else statements.
Discussion
Loading comments…