DEV Community

Cover image for Introducing Gate Classes (Design Pattern)

Introducing Gate Classes (Design Pattern)

James Hickey on April 11, 2019

Originally posted on my technical blog Have you ever heard of guard clauses? Steve Smith discusses them in one of his Weekly Dev Tips here. Today...
Collapse
 
raimeyuu profile image
Damian Płaza

Thanks for sharing this pattern, looks really interesting. However, I feel worried about Invoke method signature of such Gate class. It communicates it's async and does not return anything (by returning Task) while in fact it implicitly throws exceptions here and there. I know that having a global exception handler is common practice, but I don't feel it's the best what we can do.

In fact, such Gate approach is quite common in functional programming, but it's encoded in method's signature by using Result type. Here's a good explanation with showcase of such approach: enterprisecraftsmanship.com/2015/0...

I am curious about your opinion :-)

Collapse
 
jamesmh profile image
James Hickey

Throwing exceptions in the non-application layer is a convention that some people just plain detest, and some find is just more pragmatic.

I wrote about this a bit in this article:

Specifically, in one section, I mention that one possible alternative is the Result Object pattern, which is basically the pattern used in the link you provided.

So I agree, sometimes it might make more sense to use some custom class or "error" data structure to pass back and forth.

This article is great on the subject. It looks at 3 different ways to do this actually. While my conclusions are the exact same as his, he gives more details for why, whereas that wasn't an issue I specifically was tackling in my article, but just mention it in passing.

It's common in DDD due to the fact of using Value Objects and the "Always Valid" pattern, essentially.

Let me know what you think! 👍

Collapse
 
stemmlerjs profile image
Khalil Stemmler

This is mighty clean, I appreciate how SOLID this is. Good distinction between the Use Case and Command from CQRS as well, that just clicked now.

As for this way of structuring policies, I like it! I think I'll use it myself.

Thanks for this one, James.
Keep it up

Collapse
 
jamesmh profile image
James Hickey

Great! I've been using it with lots of success. Def. makes re-using policies etc. super easy to re-use and test 👍

Collapse
 
lalitkale profile image
Lalit Kale

This is quite similar to what Guard class in many open source projects has been used for. Moreover, fluentvalidations lib provides many other features. You or readers might be interested to take a look.

Collapse
 
jamesmh profile image
James Hickey

Yes. If people are getting into a CQRS or use case style architecture, then using Mediatr is a fantastic tool.

You can register pre-processor handlers that run before each handler. These gate classes I'm discussing can easily be converted as a pre-processor handler (that's essentially the same pattern).

Collapse
 
glenmccallumcan profile image
Glen McCallum

First time I've seen this! Can't wait to try it out.

Collapse
 
jamesmh profile image
James Hickey

Let me know when you do 👍 It's been working well for me!

Collapse
 
glenmccallumcan profile image
Glen McCallum

Where do you put your gate classes in your project package/folder structure?

Thread Thread
 
jamesmh profile image
James Hickey

Usually, I have a project structure like:

web (app layer) -> use cases -> domain project

I tend to put all these kinds of classes in the use cases project. I'll have a structure using feature folders something like:

  • Features
    • Orders
    • Payments
    • Shipping

For cross-cutting stuff like checking a user's role, etc. I would create another folder in the root of the use case projects called "Gates".

If a specific gate class is really tied to a specific feature of the application, which is rare since they are mostly useful for cross-cutting kinds of concerns like checking user permissions etc., then I would just make a "Gates" folder in the features folder:

  • Orders
    • Gates (folder)
    • PlaceStandardOrderCommand.cs (use case)
    • GetActiveOrderForUserQuery.cs (use case)
    • ...and more use cases...