Throughout this book, I’ve tried to keep the focus on the specific code that relates to the architectural principle in question. If each chapter had reams and reams of code covering a lot of the plumbing code, it would detract from the subject matter. Consequently, most of the code that would be necessary for a simulation to actually run has been omitted from the chapters themselves. All of this code can be found here, in the GitHub repo:
This appendix covers sections of code that were too bulky or tangential to make sense inside the chapters themselves.
Chapter 1
This section will cover the creation of the third-party API proxy that we used in the chapter.
Let’s start with the third-party APIs (in fact, for our purposes, we will only need one, although we should bear in mind that there will be more).
We’ll start by creating a directory for our code (Listing
A-1).
mkdir software-architecture-by-example
cd software-architecture-by-example
mkdir booking-api
Listing A-1Terminal – Create Directory for the Chapter and the API
Now that we have a directory, we can create our API project (Listing
A-2).
Listing A-2Terminal – Create New API Project
This gives us the default Weather Forecast API. Let’s first rename a couple of files:
WeatherForecastController.cs to ExternalTicketBooking.cs
WeatherForecast.cs to TicketInformation.cs
We’ll start with the contents of the file
TicketInformation.cs (Listing
A-3).
namespace booking_api
{
public class TicketInformation
{
public string EventCode { get; set; }
public DateTime EventDate { get; set; }
public decimal Price { get; set; }
public string SeatCode { get; set; }
public int Quantity { get; set; }
Listing A-3Code – TicketInformation.cs
This is simply a class to hold the ticket information and will be serialized and passed back to the caller as a JSON object. The only other thing that we’ll need to do to create our
mock API is to create a controller (shown in Listing
A-4); I’ve added mine to a
Controllers subdirectory.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace booking_api.Controllers
{
[ApiController]
[Route("[controller]/[action]")]
public class ExternalTicketBookingController : ControllerBase
{
private static Random _random = new Random();
private static int _capacity = 1200000;
private static string _eventCode = "GLS_21";
private static DateTime _eventDate = new DateTime(2021, 06, 23);
private static decimal[] _prices = new [] {
100.50m, 260.65m, 540.10m
};
public ExternalTicketBookingController()
{
}
[HttpGet]
public IEnumerable<TicketInformation> GetTickets()
{
var tickets = new List<TicketInformation>();
for (int i = 0; i < _prices.Length; i++)
{
tickets.Add(new TicketInformation()
{
EventCode = _eventCode,
EventDate = _eventDate,
Price = _prices[_random.Next(_prices.Length)],
SeatCode = "NA",
Quantity = _capacity / _prices.Length
});
}
[HttpPost("{seatCode?}")]
public async Task<IActionResult> ReserveTicket(string seatCode)
{
await Task.Delay(1000);
if (_random.Next(10) == 1)
{
return BadRequest();
}
return Ok();
}
[HttpPost("{seatCode?}")]
public async Task<IActionResult> PurchaseTicket(string seatCode)
{
await Task.Delay(2000);
if (_random.Next(10) == 1)
{
return BadRequest();
}
return Ok();
}
}
}
Listing A-4Code – ExternalTicketBookingController.cs
We essentially have three possibilities here: we can retrieve the available tickets (since this example is not a seated event, the tickets are returned grouped by price), we can reserve a ticket (providing an optional seat code), or we can purchase a ticket (again, with an optional seat code).
The reserve and purchase methods have delay and potential failure built in so that we can simulate some of the real-world conditions of a real third-party API.
The takeaway from this is that we now have three endpoints. If you’re following along, you should see where this API is listening (Figure
A-1).
In my case (and likely in yours unless you explicitly change it), I’m listening on https://localhost:5001. The way that we’ve configured the routing, the endpoints will be as follows:
https://localhost:5001/externalticketbooking/gettickets
https://localhost:5001/externalticketbooking/reserveticket
https://localhost:5001/externalticketbooking/purchaseticket