我们子公司的IT部门有一家咨询公司为他们编写了一个ASP.NET应用程序.现在它已经出现间歇性问题,混淆了当前用户是谁,并且已经知道他错误地向Joe展示了一些Bob的数据.
顾问们被带回来进行故障排除,我们被邀请听取他们的解释.突然发生了两件事.
首先,顾问主管提供了这个伪代码:
void MyFunction() { Session["UserID"] = SomeProprietarySessionManagementLookup(); Response.Redirect("SomeOtherPage.aspx"); }
他继续说会话变量的赋值是异步的,这似乎是不真实的.对查询函数的调用可以异步执行某些操作,但这似乎是不明智的.
鉴于所谓的异步性,他的理论是在重定向不可避免的ThreadAbort异常被引发之前没有分配会话变量.然后,此故障阻止SomeOtherPage显示正确的用户数据.
其次,他举了一个他推荐的编码最佳实践的例子.而不是写:
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; }
这肯定会起作用,并且在某些情况下从性能角度来看可能更好.
但是,从这些和其他讨论点来看,我们认为这个团队在技术上并不精通.
意见?
经验法则:如果您需要询问顾问是否知道他在做什么,他可能不会;)
我倾向于同意这里.显然你没有提供太多,但他们似乎并不是非常称职.
我同意.这些家伙似乎很无能.
(顺便说一句,我要查看是否在"SomeProprietarySessionManagementLookup"中,他们正在使用静态数据.看到这一点 - 行为与你在几个月前我继承的项目中所描述的完全相同.这是一个完全头脑发热的时刻.我们终于看到了......并且希望我们能够与写下它的人面对面...)
如果顾问编写了一个应该能够跟踪用户的应用程序并且只向正确的用户显示正确的数据并且它没有这样做,那么显然有些错误.一个好的顾问会发现问题并解决它.一个糟糕的顾问会告诉你这是异步性的.
在异步部分,唯一可行的方法是,如果正在进行的赋值实际上是Session上的索引器设置器,它隐藏了一个没有回调的异步调用,表明成功/失败.这似乎是一个可怕的设计选择,它看起来像你的框架中的核心类,所以我发现它不太可能.
通常,异步调用可以指定回调,以便您可以确定结果是什么,或者操作是否成功.Session的文档应该非常清楚,如果它实际上是隐藏异步调用,但是......看起来不像顾问知道他在说什么......
分配给Session索引器的方法调用不能是异步的,因为要异步获取一个值,你必须使用回调......没办法,所以如果没有显式的回调,它肯定不是异步的(好吧) ,内部可能存在异步调用,但该方法的调用者会将其视为同步,因此如果内部方法例如异步调用Web服务则无关紧要.
对于第二点,我认为这会好得多,并且基本保持相同的功能:
int MyFunction(int x, int y) { if (y == 0) { // log it throw new DivideByZeroException("Divide by zero attempted!"); } return x / y; }
对于第一点,这确实看起来很奇怪.
在第二个方面,尝试避免除以0是合理的 - 它完全可以避免并且避免很简单.但是,在某些情况下使用out参数来指示成功是合理的,例如int.TryParse和DateTime.TryParseExact - 调用者无法轻易确定其参数是否合理.即便如此,返回值通常是成功/失败,out参数是方法的结果.