1
\$\begingroup\$

In my project I used N Layer Architecture.

In the service layer I return an enum for each action, for example for Add action I have an enum like this :

  public enum AddStatus
{
    AddSuccessful,
    Faild,
    Exists
}

And for Edit I have this :

    public enum EditStatus
{
    Successful,
    Faild,
    NotFound,
    Exists
}

But sometimes I need a custom enum like this one :

    public enum AddAssetFunctionStatus
{
    AddSuccessful,
    Faild,
    Exists,
    ValueIsLess,
    ItIsNotStatistical
}

and with custom enum I can show the appropriate message to the end user.

Another way I use, which I think is good, is to pass an out string param to each action, like :

   AddStatus Add(AddAccessDeviceViewModel accessDeviceViewModel,out string message);

And in the controller I have :

 switch (result)
        {
            case AddStatus.AddSuccessful:
                _uow.SaveChanges();
                this.AddNotification(Messages.SaveSuccessfull, NotificationType.Success);
                return RedirectToAction(MVC.Admin.AccessDevice.Index());
            case AddStatus.Faild:
                this.AddNotification(Messages.SaveFailed, NotificationType.Warning);
                break;
            case AddStatus.Exists:
                this.AddNotification(Messages.DataExists, NotificationType.Info);
                break;

        }

Which one is better?

  1. Use custom enum for each action that I need.

  2. pass an out param to the action that I need.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Does the code you presented actually work? \$\endgroup\$
    – Phrancis
    Mar 11, 2017 at 8:00
  • \$\begingroup\$ yes , of course . but I want the best way to return message . because Addstatus always does not support things that I want \$\endgroup\$ Mar 11, 2017 at 8:02
  • 2
    \$\begingroup\$ Not working code in my opinion. Some code fragments. \$\endgroup\$
    – paparazzo
    Mar 11, 2017 at 15:30
  • 1
    \$\begingroup\$ Some disadvantages of using strings: they don't tell you or other programmers what errors can be expected, and they need to be parsed to determine the error. Parsing requires their format to be known, all implementations to stick to that format, they'd better not be localized, and so on... \$\endgroup\$ Mar 13, 2017 at 8:23
  • \$\begingroup\$ a disadvantage of enum is I have to create new Enum for New Situation . For eaxample I cant always use AddStatus because some times It does not enough for all Methods . some methods need to return a custome error ex. (your ReputationIsNotEnough for Add Vote). \$\endgroup\$ Mar 13, 2017 at 12:01

1 Answer 1

1
\$\begingroup\$

I would not recommend using this pattern, personally. What you're effectively trying to do is signal error state, where 0 is null state and therefore success, similar to the way that you might do it with the Win32 API. The designers of c# and the .NET framework explicitly sought to avoid this pattern (and deem it to be an anti pattern). I think it works great for OS level work, and clearly does for both Windows and Linux, but it can be very cumbersome.

The "c#" method of doing this is by using exceptions. For a method called SaveChanges, the return type is usually either void or bool. I personally recommend void, because bool doesn't give any context for what caused the operation to fail, and is really just a slim version using an enumeration.

For the remainder of cases, there is USUALLY a built in exception type that is appropriate. InvalidOperationException can be used to state that you can't save the changes because the entity already exists, for instance. In a Web API, you can return something in one of the error ranges for this case.

If you really look at the exception model, I believe you'll find that it does provide a decent solution to this problem for you. It liberates you from having to build complex enumerations, and mapping them across layers. Your application is then free to focus on interactions with the layer it communicates with, and you don't need to build extra services across each tier to describe what happened. Ideally, this means easier long term maintenance as well, because changing any part of the implementation does not result in needing to update the ENTIRE implementation.

\$\endgroup\$
2
  • \$\begingroup\$ I'm not really convinced. An enum will tell you what kind of errors you can expect. They're self-documenting. With exceptions you usually can't easily tell which ones a method might throw, unless the developer explicitly documented it (and the docs are still in sync with the code). I'm also not sure about repurposing system exceptions. The type of an exception is often used to filter on. Using your own (layer-specific) types will make it easier for the caller to determine which exceptions they should be taking care of. \$\endgroup\$ Mar 13, 2017 at 8:38
  • \$\begingroup\$ I agree, enums are self-documenting. They are extremely helpful in that regard, but they also raise a lot of design discussions thereafter as well. With the system exceptions, there are only a handful that really shouldn't ever be thrown by user code; many of the others are designed to provide common semantics across implementations, such as the ArgumentException exceptions. They are also not that to document if you use XML commenting, which you should do anyway if other people are using your code directly, and not through some abstraction layer (such as HTTP). \$\endgroup\$
    – PSGuy
    Mar 13, 2017 at 22:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.