如何编写优雅的验证方法

时间:2015-12-15 11:02:03

标签: c# asp.net-mvc

Notifications可以被标记为Employee读取 其工作原理如下:

  1. 用户/员工打开通知(网页)
  2. 用户点击"标记为已读"
  3. 用户必须插入他的EmployeeNumber并单击"确认"
  4. 如果出现错误,用户会收到反馈
  5. 在我的示例中,我必须验证我的数据库中是否存在带有输入的EmployeeNumber的Employee,如果是,则加载该条目。

    我需要在多个地方进行此验证,所以我认为我可以将其提取到D.R.Y的方法中。

    的EmployeeService:

    public class EmployeeService : BaseService
    {
        public static Employee VerifyEmployeeNumber(ISession session, string employeeNumber)
        {
            if (employeeNumber.IsNullOrWhitespace())
                throw new ArgumentNullException();
    
            Employee employee = session.Query<Employee>().FirstOrDefault(x => x.Number == employeeNumber);
            if (employee == null)
                throw new ArgumentException();
    
            return employee;
        }
    
    }
    

    NotificationService

    public class NotificationService : BaseService
    {
        public string SetNotificationAsRead(long notificationId, string employeeNumber)
        {
            Employee employee;
            try
            {
                employee = EmployeeService.VerifyEmployeeNumber(Session, employeeNumber);
            }
            catch (ArgumentNullException)
            {
                return "No Employeenumber was entered";
            }
            catch (ArgumentException)
            {
                return "No Employee exists with this number";
            }
    
            //Update my notification as read
            return null;
        }
    }   
    

    NotificationController:

     public JsonResult MarkAsRead(long notificationId, string employeeNumber)
     {
         string errormessage = NotificationService.SetNotificationAsRead(notificationId, employeeNumber);
    
         if (errormessage.IsNotNullOrWhitespace())
             return Error(errormessage);
    
         return Success();
     }
    

    JSON在前端解析。

    问题:
    我还需要在我的BarcodeService等其他服务中验证我的EmployeeNumber。我也必须表现出同样的错误 所以我再次编写try-catch并对错误消息进行硬编码。

    这看起来很笨拙。

    如何以更好的方式实现这一点 似乎我需要一种可以返回错误员工的方法,这在c#中是不可能的

    提前致谢。

    有条件的信息:

    • 不需要通用验证
    • @I Stanley - 我可以将这些消息放入Employeeclass,但如果我只在一个地方需要它们,我就不会认为它太糟糕了将它们硬编码到验证方法中
    • 我认为最大的问题是如何从Businesslogic(服务)向用户(控制器 - &gt; JSON - &gt;网页)获取错误消息

    可能的改进1:
    我想到验证员工是否存在我的VerifyEmployeeNumber,如果没有返回错误,则员工从数据库加载。这有2个DB访问的缺点。

2 个答案:

答案 0 :(得分:3)

这里的问题是优雅是一个很大的主观特征。我可以建议一些可能有助于您更好地封装代码并防止重复行的事情,但我建议对下一个人可能是令人憎恶的。

您似乎在询问两个不同的问题,或者至少是一个可以分为两个部分的问题:

  1. 如何处理错误消息,以免每次都对其进行硬编码
  2. 如何处理您的验证方法,以便您不会每次都复制try / catch块。
  3. 为了它而忽略了对整体设计方法的任何疑问......

    错误消息位很容易至少清理 - 使错误字符串成为错误类的一部分或类本身的一部分。例如,你可以这样做:

    public class Employee : BaseClass
    { 
      ...
    
      //Error Messages for Employee checks
      public static string ErrorNotFound = "No Employee exists with this number";
      public static string ErrorInvalid = "Invalid Employee Number";
    
      ...
    }
    

    然后你可以通过Employee.ErrorNotFound来调用该字符串,而不是每次都写出来。

    或者,您创建一个类/结构,其中包含名为ErrorMsg或其他内容的所有错误消息,然后调用ErrorMsg.EmployeeNotFound。这本身比硬编码的字符串更整洁,但在第二部分中将进一步明显的优势。

    现在,try / catch的东西。如果您打算坚持使用异常(请参阅下面的注释),那么根据您想要的通用程度,只需重复您对EmployeeService所做的操作,并创建一个封装try / catch的方法。没有理由认为这不应该是EmployeeService中的一项功能,因为这项服务将始终提供什么,对吧?该员工是否存在或输入是否有效。

    如果您想让它变得有趣,并且有一个处理所有验证的功能,无论它是员工还是其他形式的验证,您都可以尝试使用Delegates,并创建一个函数,它将调用正确的验证函数,然后输出相关的错误消息。我没有详细介绍,因为有数百种方法可以正确地完成这项工作,而且我不知道你的系统有多复杂。如果您需要验证的唯一内容是EmployeeNumber,则可能没有理由创建通用验证处理函数。

    有几点需要注意:

    1)您对例外的使用充其量是有争议的。您将看到的大多数指南(例如MSDN)强烈建议使用异常来捕获意外行为,而不是作为标准形式的流控制。在这些函数中,您将它们有效地用作返回值 - 很可能在正常使用期间会反复命中这些异常。最好返回NULL,或者某些&#34;没有员工找到&#34;然后可以通过标准流量控制处理的对象。

    这样做的好处在于:a)您不必拥有如此多的尝试/捕获声明; b)它标准化您必须检查的内容,以确定您是否找到了一名员工 - 如果它是&#39;不是NULL,很棒,你找到了一个。我不需要去看看抛出了什么样的异常。

    2)是否有必要区分&#34;没有员工与此号码&#34;和&#34;没有输入员工编号&#34;?两者都相同。如果你只是使用一个包含&#34的单个错误消息,那么找不到这个号码的员工&#34;或类似的。如果您设置了不同的错误消息,请通过引用将字符串传递给函数并在出错时填充它,如果函数返回NULL,则打印字符串的内容以获取错误消息。

    每个回答这个问题的人都有机会根据他们的深度以及他们关注的重点来看待不同的事情(我可能错过的设计方面很可能会产生任何我想要做的事情。建议无效!)。您可以考虑要采取哪些建议。

    我不知道你将如何选择&#34;对&#34;回答......

答案 1 :(得分:0)

我认为您的Employee VerifyEmployeeNumber(ISession session, string employeeNumber)方法设计存在问题。通过验证实体并返回它来混合命令和查询。这就是你遇到分离问题的原因。

我宁愿查询员工,然后以单独的方法验证他。请注意,您正在尝试SetNotificationAsRead,但您还要查询员工并验证值。这是设计糟糕的证据。

不仅仅是:

 public JsonResult MarkAsRead(long notificationId, string employeeNumber)
 {
     var employee = _session.Query<Employee>().FirstOrDefault(x => x.Number == employeeNumber);
     var error = EmployeeService.VerifyEmployee(_session, employee);
     if (errormessage.IsNotNullOrWhitespace())
         return Error(errormessage);

     NotificationService.SetNotificationAsRead(notificationId, employee);   
     return Success();
 }

这只是一个概念,但你应该有个主意。