Programming lesson
Mastering User Stories in C# OOP: Build a Food Delivery App Like Arriba Eats
Learn how to implement user stories in a C# console application using object-oriented programming. This tutorial walks through registration, authentication, restaurant management, and order tracking for a food delivery system like Arriba Eats.
Introduction: Why User Stories Matter in OOP
In May 2026, food delivery apps are more popular than ever. Whether you're ordering a pizza or tracking a driver's location, these apps rely on solid object-oriented programming (OOP) to manage users, restaurants, and orders. For CAB201 assignment 2, you'll build a text-based prototype called Arriba Eats using C#. This tutorial helps you implement user stories step by step, focusing on OOP principles like encapsulation, inheritance, and separation of concerns.
User stories are short descriptions of a feature from the user's perspective. They guide development and ensure you build what the user needs. By implementing each story incrementally, you'll create a robust system that can later evolve into a GUI or database-driven app.
Understanding the Assignment Context
The Arriba Eats assignment involves three user types: customers, deliverers, and clients (restaurant owners). Each has unique attributes and actions. The current prototype uses a console interface, but code must be separated from UI logic for future migration. Data stays in memory, so focus on class design and object interactions.
Think of this like a multiplayer game: each user is a player with a profile, inventory (orders), and abilities (status changes). Your job is to model these players using OOP classes.
Step 1: Registration – Building the User Base
User stories 1, 5, 6, and 7 cover registration. All users share common fields: name, age, email, mobile, password. Customers also have an X/Y location; deliverers have a license plate number; clients have restaurant name, style, and location.
Design a Base User Class
Create an abstract User class with shared properties. Then derive Customer, Deliverer, and Client classes. This follows OOP inheritance and reduces code duplication.
public abstract class User
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public string Mobile { get; set; }
public string Password { get; set; }
public User(string name, int age, string email, string mobile, string password)
{
Name = name; Age = age; Email = email; Mobile = mobile; Password = password;
}
}
public class Customer : User
{
public double X { get; set; }
public double Y { get; set; }
public Customer(string name, int age, string email, string mobile, string password, double x, double y)
: base(name, age, email, mobile, password)
{
X = x; Y = y;
}
}Similarly, create Deliverer with LicensePlate and Client with RestaurantName, Style, RestaurantX, RestaurantY. Use an enum for restaurant styles: Italian, French, Chinese, Japanese, American, Australian.
Registration Flow
In the console, ask the user to choose their role, then collect required fields. Store users in a List<User> or dictionary keyed by email. Validate unique emails to prevent duplicates.
Step 2: Authentication and Profile Viewing
User story 2 requires login with email and password. Story 3 lets users view their own details. Implement a simple authentication method: loop through users, find matching email, verify password, and return the user object. Once logged in, display their info.
For story 4 (logout), just set the current user to null. This is straightforward but essential for security.
Step 3: Restaurant and Menu Management
As a client, you need to register your restaurant (story 7) and view its details (story 8). Also add menu items (story 9). Create a Restaurant class with a list of MenuItem objects. Each menu item has a name and price.
public class MenuItem
{
public string Name { get; set; }
public double Price { get; set; }
}
public class Restaurant
{
public string Name { get; set; }
public string Style { get; set; }
public double X { get; set; }
public double Y { get; set; }
public List<MenuItem> Menu { get; set; } = new List<MenuItem>();
public List<Rating> Ratings { get; set; } = new List<Rating>();
public double AverageRating => Ratings.Count > 0 ? Ratings.Average(r => r.Stars) : 0;
}Link the restaurant to the client via a Client property. When a client logs in, they can add menu items and view their restaurant.
Step 4: Customer Browsing and Ordering
Stories 10-14 involve listing restaurants, sorting, viewing menus, and ordering. Use LINQ to sort by name, distance, style, or average rating. Distance is calculated using the Euclidean formula: Math.Sqrt((x1-x2)^2 + (y1-y2)^2).
For story 15, create an Order class with a list of OrderItem (menu item + quantity), status, customer, restaurant, and deliverer. Status can be an enum: Ordered, Cooking, Cooked, BeingDelivered, Delivered.
Step 5: Order Lifecycle – From Client to Deliverer to Customer
Stories 18-29 track the order status. The client changes status from Ordered to Cooking to Cooked. The deliverer claims an available order (story 21) and sees distances (story 22). The deliverer sets status to AtRestaurant, then the client marks as BeingDelivered, and finally the deliverer marks as Delivered.
Implement a OrderManager class that holds all orders and provides methods to update status. Use events or a simple observer pattern to notify relevant users? Not required for console, but good OOP practice.
Step 6: Ratings and Customer History
Story 30 allows customers to rate a restaurant with a comment and star rating. Create a Rating class and store it in the restaurant. Story 17 shows customer stats: location, number of orders, total spent. Calculate from the customer's order history.
Keeping UI Separate
Create a ConsoleUI class that handles all input/output. The business logic classes (UserManager, OrderManager, etc.) should not directly call Console.ReadLine or Console.WriteLine. Instead, the UI calls methods and displays results. This separation makes future GUI migration easy.
Testing Incrementally
Implement one story at a time. Use Gradescope's expected output to verify. Start with customer registration, then login, then restaurant browsing. Each story depends on previous ones. Use a menu loop that displays options based on the current user role.
Conclusion
By breaking down the assignment into user stories, you can build a complete food delivery system step by step. OOP principles like inheritance, encapsulation, and separation of concerns keep your code clean and extensible. As trends in 2026 show, apps like Arriba Eats are everywhere – mastering these skills prepares you for real-world software development.
Remember to test each story thoroughly. Good luck with your CAB201 assignment!