DEV Community

Samuel Ko
Samuel Ko

Posted on

An example of Consumer-Driven Development

It's my first time sharing my experience.
Let me know if there's anything I can improve.

Introduction

"Consumer-Driven Development" is a made-up terminology.

In this mindset, we define what the "consumer" needs first, then orchestrate the application to satisfy the need.

The "consumer" here can be perceived as the presentation layer, such as API controllers.

Example

The existing architecture

We have an application.
It calls an API endpoint periodically and logs the data:

Component Diagram

The diagram is drawn using PlantUML.

PlantUML Text
@startuml Example App
skinparam componentStyle rectangle

cloud "API Endpoint"
cloud "Elastic"

rectangle "Application" {
  [Gateway]
  [API Client]
  [Repository]
  [Cron Job]
}

[API Endpoint] -> [Gateway]
[Gateway] --> [API Client] : HTTP Response
[API Client] --> [Repository] : Product DTO
[Repository] --> [Cron Job] : Product

[Cron Job] -> [Elastic] : Logs

@enduml
Enter fullscreen mode Exit fullscreen mode

The new business requirement

The API endpoint provides a field called status.
It can be Approved, Disapproved, Pending.

We want to log the total number of Approved products.

Solution #1 - The data-flow approach

Conceptual diagram

PlantUML Text
@startuml
skinparam componentStyle rectangle
skinparam defaultTextAlignment center

component [Repository] as "**Step 3**\nRepository"
component [CronJob] as "**Step 4**\nCronJob"

[API Client] -> [Repository] : **Step 1**\nProductDTO
[Repository] -> [CronJob] : **Step 2**\nProduct

@enduml
Enter fullscreen mode Exit fullscreen mode

Step 1:
We want to obtain the data from the API endpoint.
Therefore, we create ProductDTO.Status as a text field.

Step 2:
We want meaningful data in our domain object.
Therefore, we create Product.Status as an enum.

enum Status
{
    Approved,
    Disapproved,
    Pending,
}
Enter fullscreen mode Exit fullscreen mode

Step 3:
Let Repository do the translation.
(Note: Exception handling is omitted.)

var products = productDtos.Select(dto =>
{
    return new Product() { Status = Enum.Parse<Status>(dto.Status) };
});
Enter fullscreen mode Exit fullscreen mode

Step 4:
Finally, we can log the number of approved products in CronJob.

logger.Information(
    "Number of approved products: {ApprovedProductCount}",
    products.Count(product => product.Status == Status.Approved));
Enter fullscreen mode Exit fullscreen mode

Solution #2 - The consumer-driven approach

Conceptual diagram

PlantUML Text
@startuml
skinparam componentStyle rectangle
skinparam defaultTextAlignment center

component [Repository] as "**Step 2**\nRepository"
component [CronJob] as "**Step 1**\nCronJob"

[API Client] -> [Repository] : **Step 2**\nProductDTO
[Repository] -> [CronJob] : **Step 1**\nProduct

@enduml
Enter fullscreen mode Exit fullscreen mode

Step 1:
The consumer, CronJob, needs to know whether a product is approved.
Therefore, we create Product.IsApproved as a boolean field.

logger.Information(
    "Number of approved products: {ApprovedProductCount}",
    products.Count(product => product.IsApproved));
Enter fullscreen mode Exit fullscreen mode

Step 2:
The provider, Repository, will figure out how to populate the new IsApproved field.
To do so, we create ProductDTO.Status as a text field.

var products = productDtos.Select(dto =>
{
    return new Product() { IsApproved = dto.Status == "Approved" };
});
Enter fullscreen mode Exit fullscreen mode

Result

In solution #1, the enum value Status.Disapproved and Status.Pending are unused. We spent extra effort to handle exceptions when translating the text field into enum.

In solution #2, the use of boolean field makes the code much simpler. One could argue that it lacks data validation and scalability, but that is not within the requirement for today.

Conclusion

Using Consumer-Driven Development, we ensure that our effort is spent to meet the requirement, and nothing else.

Happy to hear your thoughts. 😉

Image of AssemblyAI tool

Transforming Interviews into Publishable Stories with AssemblyAI

Insightview is a modern web application that streamlines the interview workflow for journalists. By leveraging AssemblyAI's LeMUR and Universal-2 technology, it transforms raw interview recordings into structured, actionable content, dramatically reducing the time from recording to publication.

Key Features:
🎥 Audio/video file upload with real-time preview
🗣️ Advanced transcription with speaker identification
⭐ Automatic highlight extraction of key moments
✍️ AI-powered article draft generation
📤 Export interview's subtitles in VTT format

Read full post

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Dive into an ocean of knowledge with this thought-provoking post, revered deeply within the supportive DEV Community. Developers of all levels are welcome to join and enhance our collective intelligence.

Saying a simple "thank you" can brighten someone's day. Share your gratitude in the comments below!

On DEV, sharing ideas eases our path and fortifies our community connections. Found this helpful? Sending a quick thanks to the author can be profoundly valued.

Okay