C# 这位ASP.NET顾问是否知道他';他在干什么?

C# 这位ASP.NET顾问是否知道他';他在干什么?,c#,asp.net,exception,session-variables,C#,Asp.net,Exception,Session Variables,我们子公司的IT部门让一家咨询公司为他们编写了一个ASP.NET应用程序。现在,它在混淆当前用户方面存在间歇性问题,并且已知它错误地向Joe显示了Bob的一些数据 顾问们被带回来进行故障排除,我们被邀请听取他们的解释。有两件事很突出 首先,顾问负责人提供了以下伪代码: void MyFunction() { Session["UserID"] = SomeProprietarySessionManagementLookup(); Response.Redirect("SomeOt

我们子公司的IT部门让一家咨询公司为他们编写了一个ASP.NET应用程序。现在,它在混淆当前用户方面存在间歇性问题,并且已知它错误地向Joe显示了Bob的一些数据

顾问们被带回来进行故障排除,我们被邀请听取他们的解释。有两件事很突出

首先,顾问负责人提供了以下伪代码:

void MyFunction()
{
    Session["UserID"] = SomeProprietarySessionManagementLookup();
    Response.Redirect("SomeOtherPage.aspx");
}
他接着说session变量的赋值是异步的,这似乎是不真实的。允许调用lookup函数可以异步执行某些操作,但这似乎不明智

鉴于这种所谓的异步性,他的理论是,在引发重定向不可避免的ThreadAbort异常之前,会话变量没有被赋值。然后,此错误阻止其他页面显示正确的用户数据

其次,他给出了一个他推荐的编码最佳实践的示例。而不是写:

int MyFunction(int x, int x)
{
    try 
    {
        return x / y; 
    }
    catch(Exception ex)
    {
        // log it
        throw;
    }
}
他推荐的技术是:

  int MyFunction(int x, int y, out bool isSuccessful)
  {
    isSuccessful = false;

    if (y == 0)
        return 0;

    isSuccessful = true;

    return x / y;
  }
这肯定会起作用,在某些情况下,从性能角度来看可能会更好

然而,从这些和其他讨论点来看,我们似乎觉得这个团队在技术上并不精通


意见?

经验法则:如果你需要询问顾问是否知道他在做什么,他可能不知道;)


我倾向于同意这一点。很明显,你没有提供太多,但他们似乎不是非常胜任。

第一点,这确实看起来很奇怪


在第二个问题上,避免被0除法是合理的——这是完全可以避免的,而且避免很简单。但是,只有在某些情况下,使用out参数表示成功才是合理的,例如int.TryParse和DateTime.TryParseExact-调用方无法轻松确定其参数是否合理。即使如此,返回值通常是成功/失败,out参数是该方法的结果。

如果顾问编写了一个应用程序,该应用程序应该能够跟踪用户,并且只向正确的用户显示正确的数据,而它没有这样做,那么显然出了问题。一个好的顾问会发现问题并解决它。一个差劲的顾问会告诉你这是异步的。

我同意。这些人看起来很无能

(顺便说一句,我想看看在“SomepropertySessionManagementLookup”中,他们是否使用了静态数据。看到了这一点——行为与你几个月前在我继承的一个项目中描述的一模一样。当我们最终看到它时,真是一个令人震惊的时刻……希望我们能与编写它的人面对面地交流……)我部分同意他的观点——检查y是否为零肯定比捕捉(昂贵的)异常要好。对我来说,出局成功似乎真的过时了,但不管怎样

re:asynchronous sessionid的滑稽表演——可能是真的,也可能不是真的,但听起来顾问好像是在吹毛求疵。

如果你不得不问,他可能没有


看起来第二点显然是不正确的。NET的标准解释说,如果一个方法失败,它应该抛出一个异常,这似乎更接近原始的异常;不是领事的建议。假设异常准确且具体地描述了故障。

顾问首先创建了代码,对吗?但它不起作用。我想你已经有不少污点了

异步答案听起来像BS,但其中可能有一些东西。他们可能已经提供了一个合适的解决方案以及描述他们自己创建的问题的伪代码。我更倾向于根据他们的解决方案而不是他们对问题的表达来评判他们。如果他们的理解有缺陷,他们的新解决方案也不会起作用。那你就知道他们是白痴了。(事实上,环顾四周,看看你是否已经在他们代码的任何其他方面有类似的证据)


另一个是代码风格问题。有很多不同的方法来解决这个问题。我个人不喜欢这种风格,但在某些情况下它是合适的。

关于第二点,我不会在这里使用例外。例外情况是为例外情况保留的。
然而,任何东西除以零肯定不等于零(至少在数学上是这样),所以这是具体情况。

典型的“顾问”胡说八道:

  • 问题在于某个专业人员正在做的任何事情
  • 异常只有在抛出时才会很昂贵。不要害怕
    try..catch
    ,但抛出应该只在异常情况下发生。如果变量
    y
    不应为零,则
    ArgumentOutOfRangeException
    将是合适的

  • 我不得不同意约翰·鲁迪的观点。我的直觉告诉我问题出在某个特定的会话管理查找()中


    。。而且你的顾问听起来也不太确定。

    他们在异步方面错了

    分配发生,然后页面重定向。函数可以异步启动并返回(甚至可以想象以自己的方式更改会话),但无论返回什么,都必须在重定向之前的代码中指定

    在任何低级代码中,甚至在高级函数中,他们的防御性编码风格都是错误的,除非是一个特定的业务案例,0、NULL或空字符串或其他任何东西应该以这种方式处理——在这种情况下,它总是成功的(成功标志是一种讨厌的代码味道),而不是异常。例外是指例外。您不希望通过溺爱函数的调用者来掩盖这样的行为。尽早捕获事物并抛出异常。我认为马奎尔在编写可靠的代码或者麦康奈尔在Code Com中都提到了这一点
    int MyFunction(int x, int y)
    {
        if (y == 0)
        {
            // log it
            throw new DivideByZeroException("Divide by zero attempted!");
        }
    
        return x / y; 
    }
    
    Session["UserID"] = SomeProprietarySessionManagementLookup();
    
    Session["UserID"] = SomeProprietarySessionManagementLookup();
    
    public void SomeProprietarySessionManagementLookup()
    {
        // do some async lookup
        Action<object> d = delegate(object val)
        {
            LookupSession(); // long running thing that looks up the user.
            Session["UserID"] = 1234; // Setting session manually
        };
    
        d.BeginInvoke(null,null,null);               
    }
    
    Action<object> d = delegate(object val)
    {
        System.Threading.Thread.Sleep(1000);  // waits a little
        Session["rubbish"] = DateTime.Now;
    };
    
    d.BeginInvoke(null, null, null);
    System.Threading.Thread.Sleep(5000);      // waits a lot
    
    object stuff = Session["rubbish"];
    if( stuff == null ) stuff = "not there";
    divStuff.InnerHtml = Convert.ToString(stuff);
    
    Action<object> d = delegate(object val)
    {
        System.Threading.Thread.Sleep(5000);  // waits a lot
        Session["rubbish"] = DateTime.Now;
    };
    
    d.BeginInvoke(null, null, null);
    
    // wait removed - ends immediately.
    object stuff = Session["rubbish"];
    if( stuff == null ) stuff = "not there";
    divStuff.InnerHtml = Convert.ToString(stuff);
    
    SomeProprietarySessionManagementLookup(Session["UserID"]);