OperationResult pattern

      2 Comments on OperationResult pattern

Communication between layers/modules/subsystems works best when API is simple and self explanatory. Pieter Hintjens wrote a great article about API design.

For today\’s article we will focus on point 9: Keep it Simple to Use

Introduction

This post is an extension of following post https://localwire.pl/throw-exception-at-me/. I found worth sharing my thoughts on this subject too 🙂

Sample Scenario

IList<User> = container.GetUsers("S*")

Developer A wrote \”GetUsers(string pattern)\” method in UsersModule. Developer B uses it.

Question: When B will ask A \”Zero means \’no records\’ or also \’error connecting to database?\’\” ?

This is simple scenario where API is not well defined. It introduces uncertainty and questioning. It will make maintenance harder.

Solution 1

Developer A: I will throw exception if something bad occurs.
Developer B: So I have to handle your DB issues ? In UI!?
Developer C: I will be forced to do \”great refactoring\” in my module since it depend \”heavily\” on your methods….

Solution 2

Developer A: Let\’s return a boolean status. GetUsers method will return a tuple. A list and \”tiny\” boolean flag.
Developer B: Great. I just check flag and know what to do.
Developer C: It\’s polluting the API. It\’s like extra wrapper in boolean flag…..

Alternative solution

How about considering every public method return object in UsersModule as \”OperationStatus\” ? We explicitly say that all methods are operations therefore they have status.

OperationStatus<IList<User>> = container.GetUsers("S*")

All developers have clear understanding what UsersModule can return. It\’s an OperationResult by definition.

This pattern was occurring so often that I decided to add OperationResult to HandlyLib. Here is the code:

When to use it

I would recommend using it in communication between layers. It has some overhead. Data has to be packed in extra \”status\” frame. I doubt it\’s worth doing that in in-module data flow. On the other hand it is worth investing time and effort to introduce it module-to-module communication, because it give us one and single way of handling statuses.

Go even deeper

You can go even deeper and introduce Convention Tests (still looking for source of this term – mail me if you know something). It\’s fairly easy to do so with CodeWatch.

We tell CodeWatch to ensure that all public methods in UsersModule return OperationResult

This way we can keep our code-base is more structured and better-defines form.

Follow me:

2 thoughts on “OperationResult pattern

  1. Michał Wilczyński

    OperationResults/OperationStatuses are definitely a way to go in as you mentioned “communication between layers”. With Ports and Adapters approach it’s even better – done by default, either through REST or WCF, because we’re somehow forced to do so by technology.
    CQRS is also promoting such approach with its Query and Command segregation (we intend to have some result of command or found entities of a query).
    Thanks for sharing your thoughts on this. 🙂

    Reply
    1. Pawel Post author

      🙂 I was thinking about this problem for a really long time. Few years ago I tried OperationResult and it seem work quite fine 🙂

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *