Rake36
Rake36

Reputation: 1022

enums across tiers

I'd like to use the same enum across three tiers of my application (presentation -> bal -> dal). I defined the enum in the data layer and I want to use the same enum in the presentation layer (the presentation layer does not have a reference to the data layer). Using someone else's answer to what I think is a similar question, I've built the following enum in the business layer:

namespace bal
{
    public enum TransactionCode
    {
        Accepted = dal.TransactionCode.Accepted,
        AcceptedWithErrors = dal.TransactionCode.AcceptedWithErrors,
        InvalidVendorCredentials = dal.TransactionCode.InvalidVendorCredentials,
        BrokerOffline = dal.TransactionCode.BrokerOffline
    }
}

Is this an appropriate way to construct enums between the tiers?

Upvotes: 5

Views: 3304

Answers (6)

jeancallisti
jeancallisti

Reputation: 1673

My answer is slightly more "elaborate" than the other ones because I have two extra criteria :

  1. We use versioned APIs. It means there are several potential versions of each presentation class.

The enums don't fit well in there, because if we wanted to make it consistent (references-wise) we would need to create "versioned" enums too. But then if they're shared with the data layer then that versioning starts invading it (imagine a bad "int" value reaching a column in the Db because the DTO class have rearranged their enums in a new version. Not good).

  1. we want to publish the DTO classes to their own project, in order to make it a nugget package that we then share with any potential client.

Problem: If we put our enums in a "shared" project that already contains other shared stuff (some constants, some utility extension classes, etc.) then we share that with the clients!

The solution I'm about to choose is to have a project only for Enums . Not just Shared stuff in general, but strictly Enums. I think I've seen that in the past in other projects and it seems right.

Upvotes: 0

jrista
jrista

Reputation: 32960

Your enum is actually part of an API. When you think about layered software, its often hard to think about shared types, but most of the time, a set of types is always shared accross layers. Instead of just thinking about the standard layering:

Presentation -> Business -> Data

Try thinking about it like this:

Presentation -> API
|-> Business ----^
    |-> Data ----^

Where API is a shared aspect of your system. The API contains any shared data types, entities, enumerations, service interfaces, etc. The API can be isolated into its own library, and reused in your presentation, while also being the gateway to your domain (which is business and data logic.)

Upvotes: 3

Jeremy
Jeremy

Reputation: 46360

In these cases, I usually seperate out my "data types" into its own small assembly. Then reference that assembly everywhere you need it.

Upvotes: 2

Spencer Ruport
Spencer Ruport

Reputation: 35117

If it were me I would create another project with this kind of stuff in it and have all the projects reference that.

Upvotes: 2

Mitchel Sellers
Mitchel Sellers

Reputation: 63126

This really depends on how your interactions are going on. The translation of a dal.TransactionCode to bal.TransactionCode will most likely not work in any operation where you are trying to set equality.

If you are truly passing it all the way around and NEED to across all layers, I would either define it at the bal layer, or reference the dal from the UI.

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500873

One approach is to have one "layer" (well, not really a layer as such) which is shared across all layers.

I blogged about this a while ago (in a blog/project which is now dormant, unfortunately). It may seem "impure" but it makes life a lot easier in many ways and reduces duplication. Of course, it does then reduce flexibility too - if you ever want the presentation enum to be different from the data layer enum, you'd have to refactor...

Upvotes: 7

Related Questions