InterviewDB Experience

Cost Estimation OOD: Extensible Pricing Engine for Variable Services

Interview Experience

Problem

Design a cost estimation engine for a platform that offers multiple services (e.g., compute, storage, network). Each service has its own pricing rules. The engine must support adding new service types without modifying existing code.

python
from abc import ABC, abstractmethod

class ServicePricer(ABC):
    @abstractmethod
    def estimate(self, usage: dict) -> float:
        pass

class ComputePricer(ServicePricer):
    # $0.05/hour per vCPU, $0.01/GB-hour RAM
    def estimate(self, usage: dict) -> float:
        # usage: {"vcpus": int, "ram_gb": float, "hours": float}
        pass

class StoragePricer(ServicePricer):
    # $0.023/GB-month
    def estimate(self, usage: dict) -> float:
        pass

class CostEstimator:
    def add_service(self, name: str, pricer: ServicePricer) -> None: ...
    def total_cost(self, usages: dict[str, dict]) -> float: ...
ce = CostEstimator()
ce.add_service("compute", ComputePricer())
ce.add_service("storage", StoragePricer())
ce.total_cost({"compute": {"vcpus":4,"ram_gb":16,"hours":720},
               "storage": {"gb":100}})
-> (4*0.05 + 16*0.01)*720 + 100*0.023 = ...

Follow-ups

  1. Which design pattern does this use, and why is it appropriate here?
  2. How would you add tiered pricing (first 100 GB at rate A, next at rate B) cleanly?
  3. How do you handle currency conversion if services are priced in different currencies?
  4. How would you add a discount system without modifying the ServicePricer interface?

Full Details

Problem

Design a cost estimation engine for a platform that offers multiple services (e.g., compute, storage, network). Each service has its own pricing rules. The engine must support adding new service types without modifying existing code.

python
from abc import ABC, abstractmethod

class ServicePricer(ABC):
    @abstractmethod
    def estimate(self, usage: dict) -> float:
        pass

class ComputePricer(ServicePricer):
    # $0.05/hour per vCPU, $0.01/GB-hour RAM
    def estimate(self, usage: dict) -> float:
        # usage: {"vcpus": int, "ram_gb": float, "hours": float}
        pass

class StoragePricer(ServicePricer):
    # $0.023/GB-month
    def estimate(self, usage: dict) -> float:
        pass

class CostEstimator:
    def add_service(self, name: str, pricer: ServicePricer) -> None: ...
    def total_cost(self, usages: dict[str, dict]) -> float: ...
ce = CostEstimator()
ce.add_service("compute", ComputePricer())
ce.add_service("storage", StoragePricer())
ce.total_cost({"compute": {"vcpus":4,"ram_gb":16,"hours":720},
               "storage": {"gb":100}})
-> (4*0.05 + 16*0.01)*720 + 100*0.023 = ...

Follow-ups

  1. Which design pattern does this use, and why is it appropriate here?
  2. How would you add tiered pricing (first 100 GB at rate A, next at rate B) cleanly?
  3. How do you handle currency conversion if services are priced in different currencies?
  4. How would you add a discount system without modifying the ServicePricer interface?

About This Question

This is a candidate experience report from a zoox interview during the phone round.

It covers the following topics: Coding, Ood, Phone .