SoatDev IT Consulting
SoatDev IT Consulting
  • About us
  • Expertise
  • Services
  • How it works
  • Contact Us
  • News
  • July 31, 2023
  • Rss Fetcher
Photo by Lukas Tennie on Unsplash

In this article, I would like to show one of the most convenient ways to manage the state of an object using a protocol-oriented approach and generics.

This approach is widely used in marketplaces, the banking environment, the service sector, and so on, and assumes that for each state of the object, it is predetermined into which state it is allowed to convert.

Consider an example:

  • You ordered a product on Amazon, and your order is assigned the status Initiated
  • After the purchase, your product enters the state of the need for payment (ReadyForPayment)
  • After payment, it enters the processing state (Pending)
  • After checking the availability of the goods, the fact of payment, and transferring it to the delivery service, your order enters the Delivering status
  • After delivery of the goods, the status changes to Delivered, with the possibility of returning the goods within 30 days
  • After 30 days, the status of the product changes to Finished, and the possibility of returning the goods ceases

In addition to the above positive cases, there are also possible pre-foreseen negative cases, such as:

  • After ordering the goods (status ReadyForPayment), payment for the goods was not made within 10 minutes, and the order was put into the Cancelled status
  • After processing the order (status Pending), it turned out that the product was out of stock, which is why the status of the order changed to CancelledWithRefunded
  • After exceeding the pre-announced delivery time, you requested a refund, and the order status changed to CancelledWithRefunded
  • After receiving the order, the product turned out to be of inadequate quality, and you also requested a refund in exchange for returning the product. The order status changed to Refunded

In more detail, a possible status change map is shown in the figure:

The designed system is required to support status routing and the ability to change / scale at the request of the business.

Let’s start with the most important unit of the system being designed:

struct Order<T> {}

As a generic parameter, we will use the order status. Let’s create for each order status, by the requirements described above, its own object:

struct Initiated {}
struct ReadyForPayment {}
struct Pending {}
struct Delivering {}
struct Delivered {}
struct Finished {}
struct Cancelled {}
struct CancelledWithRefunded {}
struct Refunded {}

The cancellation/refund capability implementation will be done using the “Strategy” design pattern. This will reduce the effort to change the statuses for which the business provides the possibility of cancellation/refusal/return of goods.

Let’s create our own protocol for each of the negative scenarios:

protocol Cancellable {}
protocol CancellableWithRefund {}
protocol Refundable {}

Taking into account the current statement of the problem, we will provide the possibility of canceling/refusing/returning goods for previously created statuses:

struct Initiated {}
struct ReadyForPayment: Cancellable {}
struct Pending: CancellableWithRefund {}
struct Delivering: CancellableWithRefund {}
struct Delivered: Refundable {}
struct Finished {}
struct Cancelled {}
struct CancelledWithRefund {}
struct Refunded {}

This completes the design of the system skeleton. Let’s move on to designing status visibility zones. The generic component of the order will help us with this.

1. According to the task statement, the Initiated status can only be changed to ReadyForPayment:

extension Order where T == Initiated {
var readyForPayment: Order<ReadyForPayment> {
Order<ReadyForPayment>()
}
}

2. ReadyForPayment status changes to Pending after successful payment:

extension Order where T == ReadyForPayment {
var pending: Order<Pending> {
Order<Pending>()
}
}

3. Pending status after checking the availability of goods, the fact of payment and transfer it to the delivery service changes to Delivering:

extension Order where T == Pending {
var delivering: Order<Delivering> {
Order<Delivering>()
}
}

4. The status of Delivering changes to Delivered after delivery of the goods:

extension Order where T == Delivering {
var delivered: Order<Delivered> {
Order<Delivered>()
}
}

5. Delivered status after 30 days excision changes to Finished:

extension Order where T == Delivered {
var finished: Order<Finished> {
Order<Finished>()
}
}

6. Statuses that provide for Cancellable in advance can be changed to Cancelled:

extension Order where T: Cancellable {
var canceled: Order<Cancelled> {
Order<Cancelled>()
}
}

7. CancellableWithRefund statuses can be changed to CancelledWithRefund:

extension Order where T: CancellableWithRefund {
var canceledWithRefund: Order<CancelledWithRefund> {
Order<CancelledWithRefund>()
}
}

8. Statuses that provide for the possibility of returning Refundable goods in advance can be changed to Refunded:

extension Order where T: Refundable {
var refunded: Order<Refunded> {
Order<Refunded>()
}
}

The system is ready. Now, we can use the constructor to collect any movement of statuses within predetermined possibilities.

For example, an order for which payment has not gone through moves like this:

let cancelled = Order<Initiated>().readyForPayment.canceled

The order for which it was delivered to the client moves like this:

let finished = Order<Initiated>().readyForPayment.pending.delivering.delivered

One of the important aspects: at each stage, the order movement occurs according to a pre-implemented routing. You cannot move an order from the Pending status to the Finished status bypassing all other intermediate statuses (if this was not allowed by your transition map).

Project sources can be found here.

And finally, don’t hesitate to contact me on Twitter if you have any questions. Also, you can always buy me a coffee.


State Management Using Protocol-Oriented Programming + Generics was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.

Previous Post
Next Post

Recent Posts

  • Marjorie Taylor Greene picked a fight with Grok
  • TechCrunch Mobility: Uber Freight’s AI bet, Tesla’s robotaxi caveat, and Nikola’s trucks hit the auction block
  • OpenAI upgrades the AI model powering its Operator agent
  • Startups Weekly: Cutting through Google I/O noise
  • Microsoft says its Aurora AI can accurately predict air quality, typhoons, and more

Categories

  • Industry News
  • Programming
  • RSS Fetched Articles
  • Uncategorized

Archives

  • May 2025
  • April 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023

Tap into the power of Microservices, MVC Architecture, Cloud, Containers, UML, and Scrum methodologies to bolster your project planning, execution, and application development processes.

Solutions

  • IT Consultation
  • Agile Transformation
  • Software Development
  • DevOps & CI/CD

Regions Covered

  • Montreal
  • New York
  • Paris
  • Mauritius
  • Abidjan
  • Dakar

Subscribe to Newsletter

Join our monthly newsletter subscribers to get the latest news and insights.

© Copyright 2023. All Rights Reserved by Soatdev IT Consulting Inc.