views:

144

answers:

5

I have a large list of error messages that my biz code can return based on what's entered. The list may end up with more than a thousand.

I'd like to just enum these all out, using the [Description("")] attribute to record the friendly message.

Something like:

public enum ErrorMessage
{
     [Description("A first name is required for users.")]
     User_FirstName_Required = 1,
     [Description("The first name is too long.  It cannot exceed 32 characters.")]
     User_FirstName_Length = 2,
     ...
}

I know enums are primitive types, integers specifically. There shouldn't be any problem with that many integers, right?

Is there something I'm not thinking of? It seems like this should be okay, but I figured I should ask the community before spending the time to do it this way.

Does .Net care about enum types differently when they have lots of values?

Update

The reason I didn't want to use Resources is because

a) I need to be able to reference each unique error message with an integer value. The biz layer services an API, in addition to other things, and a list of integer values has to be returned denoting the errors. I don't believe Resources allows you to address a resource value with an integer. Am I wrong?

b) There are no localization requirements.

+2  A: 

1000 is not many, you should just make sure that the underlying integer type is big enough (don't use a char for your enum.

On second thought 1000 is tons if you're manually entering them, if they are generated from some data set it could make sense kinda...

Motti
+8  A: 

I think a design that has 1,000+ values in an enum needs some more thought. Sounds like a "God Enum" anti-pattern will have to be invented for this case.

duffymo
I thought about using generic ErrorMessage types against the model, but it seems like the only point of that would be to have less vertical code and more horizontal code. My plan is to iterate to something better as future requirements become more clear.
sohtimsso1970
While in a general case I would say that it's a sign of bad design I think he has about the only legit case for it--a result code that must be passed as an integer.
Loren Pechtel
+4  A: 

The main downside I'd point out with having the friendly description in an Attribute is that this will cause challenges if you ever need to localize your app for another language. If this is a consideration, it would be a good idea to put the strings in a resource file.

The enum itself should not be a problem, though having all of your error codes in one master list can be confusing. You may consider creating seperate enums for seperate categories of return codes, as this will make it easier for developers to understand the possible return values for a particular function. You can still give them distinct numeric values (by specifying the numeric values explicitly) if it's important that the codes be unique.

On a side note, the .NET BCL does not make much use of return codes and return codes are somewhat discouraged in modern .NET development. They create maintainability issues (you can almost never remove old return codes or risk breaking backwards compatibility) and they require special validation logic to handle the returns for every call. Stateful validation can be accomplished with IDataErrorInfo, where you use an intermediate class that can represent invalid states, but that only allows a Commit of changes that are validated. This allows you to manipulate the object freely, but also provide feedback to the user as to the validity of its state. The equivalent logic with error codes often requires a switch statement for each use.

Dan Bryant
Yeah, I thought about localization but that isn't required, and it is extremely unlikely ever to be. I figure if that requirement ever surfaces, I'll have the team iterate to something else.
sohtimsso1970
You make a good point about using valid/invalid state with an interface, but I have to disagree that using return types are discouraged. This ErrorMessage enum is not the only thing being returned. It's part of a Result<Model> pattern that allows the biz layer to return a lot of information that isn't possible any other way. (At least not that I can comprehend). Keep in mind, this biz layer is surfacing a variety of controller types, including a REST and SOAP API.
sohtimsso1970
@sohtimsso1970, it sounds like your use case is an exception, as you need to package more information than just a return code. I was referring more to the old-school approach of having every method call return an integer, with some master set of constants for interpreting the result of each method. In your case, you need to support multiple service fronts, so an error code to communicate validation may make the best sense. Even still, it will be helpful to split up the codes/results; I think having one central `Result<Model>` is going to cause headaches later.
Dan Bryant
+1  A: 

I fully agree with duffymo. An enum with 1000+ values smells bad from y design point of view. Not to mention that it would be quite nasty for the developer to use intelligence on such a GOD ENUM:-) I would better go for using resources.

bakopanos costas
The reason I don't want to go with resources is because I need to hand back a unique integer value for each error. The biz code is being used in different places, including an API, so there are times when I can't pass the Resource Name but would need to pass an int. I'll edit the question to include this.
sohtimsso1970
By the way, do you read out the [Description("A first name is required for users.")] at runtime? That could affect performance.
bakopanos costas
@bakopanos costas - Yes, there's a point where reflection is used to get the Description, but that's only happening once per application instance, right? As soon as that hit is taken, it shouldn't be happening again unless the application resets.
sohtimsso1970
Coming back to your concern about being able to hand back a unique integer value... consider your requirements again. If you use resources it will be much easier for you to deal with localization issues. The industry standard practice is to use resources for error codes. There is a big ecosystem of tools to help you with that.
bakopanos costas
One way to make sure that your codes are the same across releases if you use resources is to write tests that compare the resources files across releases.
bakopanos costas
+1  A: 

I think it's very bad, for error handling you can simply use resource, as i see you want to do reflection and fetch the description its bad too. If you don't want to use resources, you can define different enum for each of your business rules, Also your different business doesn't need others error message (and shouldn't be like this).

SaeedAlg