سؤال

كان لدى قسم تكنولوجيا المعلومات في إحدى الشركات التابعة لنا شركة استشارية تكتب لهم تطبيق ASP.NET.يواجه الآن مشكلات متقطعة في الخلط بين هوية المستخدم الحالي ومن المعروف أنه أظهر لجو بعض بيانات بوب عن طريق الخطأ.

تمت إعادة المستشارين لاستكشاف الأخطاء وإصلاحها ودُعينا للاستماع إلى شرحهم.شيئين عالقين.

أولاً، قدم المستشار الاستشاري هذا الرمز الزائف:

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،" أنهم يستخدمون بيانات ثابتة المنشار هذا - مع السلوك تماما كما تصفون على مشروع ورثتها منذ عدة أشهر . وكان مجموع حظة وجها صفعة عندما شاهدنا أخيرا ... ونتمنى أن تحصل على وجها لوجه مع اللاعبين الذين كتبوه ...)

نصائح أخرى

وبحكم التجربة: إذا كنت بحاجة إلى أن نسأل إذا مستشار يعرف ماذا يفعل، وقال انه ربما لا.)

وأنا أميل إلى الاتفاق هنا. من الواضح أنك لم تقدم الكثير، ولكن لا يبدو أنها مختصة بشكل رهيب.

إذا المستشار تمت كتابة أحد التطبيقات التي من المفترض أن تكون قادرة على تتبع المستخدمين وفقط تظهر البيانات الصحيحة للمستخدمين الصحيح وأنها لا تفعل ذلك، فمن الواضح أن شيئا ما خطأ. ومن شأن مستشار جيد العثور على المشكلة وحلها. ومن شأن مستشار سيئة اقول لكم ان كان asynchronicity.

في الجزء غير متزامن، والطريقة الوحيدة التي يمكن أن يكون صحيحا هي إذا كانت المهمة مستمرة هناك في الواقع اضع مفهرس على الدورة التي يختبئ استدعاء غير متزامن مع عدم وجود رد مشيرا إلى نجاح / فشل. ويبدو أن هذا سيكون خيارا تصميم فظيعة، ويبدو أن الطبقة الأساسية في إطار الخاصة بك، لذلك أجد أنه من المستبعد جدا.

والاستدعاءات غير المتزامنة عادة لديهم وسيلة لتحديد رد حتى تتمكن من تحديد ما هي النتيجة، أو إذا كانت العملية ناجحة. وينبغي أن تكون وثائق الدورة واضح جدا على الرغم من إن كانت تخفي في الواقع استدعاء غير متزامن، ولكن نعم ... لا تبدو وكأنها استشاري يعرف ما الذي يتحدث عنه ...


واستدعاء الأسلوب الذي يتم تعيينه إلى مفهرس الدورة لا يمكن أن يكون asynch، لأن الحصول على قيمة بشكل غير متزامن، لديك لاستخدام الاستدعاء ... بأي حال من الأحوال حول ذلك، حتى إذا لم يكن هناك رد واضح، انها بالتأكيد ليست asynch (حسنا، داخليا يمكن أن يكون هناك استدعاء غير متزامن، ولكن المتصل من الأسلوب يرى أنها متزامن، لذلك لا يهم إذا كان الأسلوب داخليا على سبيل المثال استدعاء خدمة ويب بشكل غير متزامن).


لالنقطة الثانية، وأعتقد أن هذا سيكون أفضل بكثير، والحفاظ على الوظيفة نفسها أساسا:

int MyFunction(int x, int y)
{
    if (y == 0)
    {
        // log it
        throw new DivideByZeroException("Divide by zero attempted!");
    }

    return x / y; 
}

لللنقطة الأولى، التي لا يبدو حقا غريب.

في ثانية واحدة، فمن المعقول أن تحاول تجنب القسمة على 0 - انها يمكن تجنبها تماما، وأنه تجنب بسيط. ومع ذلك، باستخدام المعلمة خارج تشير إلى نجاح غير معقول إلا في حالات معينة، مثل int.TryParse وDateTime.TryParseExact - حيث لا يستطيع المتصل بسهولة تحديد وجود أو عدم حججهم معقولة. حتى ذلك الحين، قيمة الإرجاع هي عادة نجاح / فشل والمعلمة خارج هو نتيجة للطريقة.

جلسات Asp.net، إذا كنت تستخدم الموفرين المضمنين، لن تمنحك جلسة شخص آخر عن طريق الخطأ. SomeProprietarySessionManagementLookup() هو السبب المحتمل ويعيد قيمًا سيئة أو لا يعمل.

Session["UserID"] = SomeProprietarySessionManagementLookup();

بادئ ذي بدء، لن يعمل تعيين قيمة الإرجاع من 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);               
}

المستشار ليس ممتلئًا تمامًا بـ BS، لكنهم كتبوا بعض التعليمات البرمجية التي تجرها الدواب.Response.Redirect() يرمي ThreadAbort، وإذا كانت الطريقة الخاصة غير متزامنة، فإن asp.net لا يعرف الانتظار للطريقة غير المتزامنة لإعادة الكتابة إلى الجلسة قبل أن يقوم asp.net نفسه بحفظ الجلسة.ربما هذا هو السبب في أنه يعمل أحيانًا وأحيانًا لا يعمل.

قد تعمل التعليمات البرمجية الخاصة بهم إذا كانت جلسة asp.net قيد المعالجة، لكن خادم الحالة أو خادم قاعدة البيانات لن يعمل.يعتمد الأمر على التوقيت.

لقد اختبرت ما يلي.نحن نستخدم خادم الدولة في التنمية.يعمل هذا الرمز لأنه تتم كتابة الجلسة قبل انتهاء سلسلة الرسائل الرئيسية.

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);

الخطوة الأولى هي أن يقوم المستشار بجعل الكود الخاص به متزامنًا لأنه خدعة الأداء لم يعمل على الإطلاق.إذا أدى ذلك إلى حل المشكلة، فاطلب من الاستشاري التنفيذ بشكل صحيح باستخدام نمط تصميم البرمجة غير المتزامنة

وأنا أتفق معه في جزء - من الأفضل بالتأكيد للتحقق ذ صفر بدلا من اصطياد استثناء (مكلفة). الخروج منطقي isSuccessful يبدو مؤرخة حقا بالنسبة لي، ولكن أيا كان.

وإعادة: جلسة الهوية الغباء غير متزامن - قد يكون أو لا يكون صحيحا، ولكن هذا يبدو وكأنه المستشار تهب الدخان لتغطية

حكم

كودي التجربة هو حق الميت. إذا عليك أن تسأل، وقال انه ربما لا.

ويبدو نقطتين لها غير صحيح واضح. معايير الصافي في شرح أنه إذا فشل الأسلوب ينبغي أن رمي استثناء، وهو ما يبدو أقرب إلى الأصلي؛ لا اقتراح consulstant ل. وإذا افترضنا أن الاستثناء بدقة وعلى وجه التحديد تصف الفشل.

خلقت

والاستشاريين التعليمات البرمجية في المقام الأول أليس كذلك؟ وأنها لا تعمل. اعتقد ان لديك قدرا كبيرا من الأوساخ عليها بالفعل.

والجواب غير متزامن يبدو وكأنه BS، ولكن قد يكون هناك شيء في ذلك. ويفترض انهم عرضوا حلا مناسبا وكذلك الزائفة رمز تصف المشكلة خلقوها هم أنفسهم. وأود أن يكون أكثر إغراء للحكم بها على حلها بدلا من التعبير عنها من المشكلة. إذا معيبة فهمهم والحل الجديد لا يعمل سواء. ثم عليك أن تعلم أنها موجودة في البلهاء. (في الواقع تبدو جولة لمعرفة ما إذا كان لديك دليل مماثل في أي مناطق أخرى من التعليمات البرمجية الخاصة بهم بالفعل)

والآخر هو مسألة أسلوب التعليمات البرمجية. هناك الكثير من الطرق المختلفة للتعامل مع ذلك. أنا شخصيا لا أحب هذا النمط، ولكن سيكون هناك الظروف التي هو مناسب.

وانهم على خطأ على المتزامن.

والتنازل يحدث ومن ثم الموجهات الصفحة. وظيفة يمكن أن تبدأ شيئا غير متزامن والعودة (ويمكن حتى تصور تغير الدورة بطريقتها الخاصة)، ولكن مهما فعلت لابد من تعيين العودة في الكود الذي قدم قبل إعادة التوجيه.

وانهم على خطأ على هذا النمط الترميز دفاعي في أي رمز على مستوى منخفض، وحتى في وظيفة رفيعة المستوى إلا إذا كان حالة عمل محددة أن السلسلة 0 أو فارغة أو فارغة أو أيا كان ينبغي التعامل معها بهذه الطريقة - التي الحالة، وانها دائما ناجحة (هذا العلم الناجح هو رائحة الكود سيئة) وليس استثناء. الاستثناءات هي استثناءات. كنت لا تريد أن تخفي السلوكيات مثل هذا من قبل تدليل المتصلين من وظائف. التقاط الأشياء في وقت مبكر ورمي الاستثناءات. أعتقد ماغواير تغطية هذا في كتابة كود الصلبة أو ماكونيل كود الكامل. وفي كلتا الحالتين، فإنه الروائح.

هذا الرجل لا يعرف ماذا يفعل.الجاني الواضح هنا:

Session["UserID"] = SomeProprietarySessionManagementLookup();

وأنا يجب أن نتفق مع جون رودي. حدسي يقول لي المشكلة هي في SomeProprietarySessionManagementLookup ().

و.. ومستشاريك لا يبدو أن تأكد من أنفسهم.

وتخزين في الدورة في عدم المتزامن. لذلك هذا ليس صحيحا إلا إذا كان هذا هو وظيفة المتزامن. ولكن على الرغم من ذلك، لأنه لا يدعو إلى BeginCall والحصول على شيء للاتصال على الانتهاء، السطر التالي من التعليمات البرمجية لن تعدم حتى خط الدورة كاملة.

لبيان الثاني، في حين يمكن استخدامها، فإنه ليس بالضبط أفضل الممارسات ولديك عدد قليل من الأشياء أن نلاحظ مع ذلك. يمكنك حفظ تكلفة رمي استثناء، ولكن لا تريد أن تعرف أن تحاول القسمة على صفر بدلا من مجرد الانتقال الماضي ذلك؟

وأنا لا أعتقد أن هذا هو اقتراح صلبة على الإطلاق.

وغريب تماما. على البند الثاني فإنه قد أو قد لا يكون أسرع. ومن المؤكد أنه ليس الوظيفة نفسها بالرغم من ذلك.

الكتل "الاستشارية" النموذجية:

  1. تكمن المشكلة في ما يفعله SomeProprietarySessionManagementLookup
  2. الاستثناءات تكون باهظة الثمن فقط إذا تم طرحها.لا تخافوا من try..catch, ، ولكن يجب أن تحدث الرميات فقط استثنائي ظروف.إذا متغير y لا ينبغي يكون صفراً ثم أ ArgumentOutOfRangeException سيكون من المناسب.

وأنا التخمين المستشار الخاص يقترح استخدام متغير الوضع بدلا من استثناء لمعالجة الأخطاء وممارسة أفضل؟ أنا لا أوافق. كم مرة نسيت الناس أو كسول جدا للقيام الخطأ التحقق من القيم العودة؟ أيضا، وتمرير / تفشل متغير ليست غنية بالمعلومات. هناك المزيد من الأشياء يمكن أن يذهب الآخر خاطئ من القسمة على صفر مثل عدد صحيح س / ص كبير جدا أو x هو نان. عندما تسوء الأمور، متغير الوضع لا يمكن أن أقول لكم ما حدث من خطأ، ولكن يمكن استثناء. الاستثناء هو لحالة استثنائية، والقسمة على صفر أو نان هي بالتأكيد حالات استثنائية.

والشيء جلسة ممكن. انها علة، يدع مجالا للشك، ولكن يمكن أن يكون أن الكتابة وصول مهما كان جلسة مخصصة الدولة مزود كنت تستخدم بعد قراءة المقبلة. الدورة دولة مزود API تتكيف مع قفل لمنع هذا النوع من الشيء، ولكن إذا كانت منفذة تجاهلت تماما كل ذلك، مستشار الخاص بك يمكن أن يقول الحقيقة.

والقضية الثانية هي أيضا صالحة كيندا. انها ليست اصطلاحي تماما - انها نسخة عكس قليلا من الأشياء مثل int.TryParse، التي هي هناك لتجنب مشكلات في الأداء الناجم عن رمي الكثير من الاستثناءات. ولكن ما لم كنت تتصل هذا الرمز ضخم، فمن غير المرجح أنها سوف تحدث فرقا ملحوظا (مقارنة مع القول، واحد أقل استعلام قاعدة بيانات في الصفحة الخ). انها بالتأكيد ليست شيئا يجب عليك القيام به بشكل افتراضي.

إذا SomeProprietarySessionManagementLookup ()؛ تقوم مهمة غير متزامن سيكون على الأرجح تبدو مثل هذا:

SomeProprietarySessionManagementLookup(Session["UserID"]);

ووحقيقة أن الكود هو تكليف النتيجة إلى الدورة [ "معرف المستخدم"] أن أقترح أن ليس من المفترض أن تكون متزامنة وينبغي الحصول على نتيجة قبل أن يتم استدعاء Response.Redirect. إذا SomeProprietarySessionManagementLookup يعود قبل نتيجته يحسب لديهم خلل في التصميم على أي حال.

وورمي استثناء أو استخدام معلمة خارج مسألة الرأي والظرف والممارسة الفعلية لن تصل إلى تل الفول الطريقة التي سبق لك أن تفعل ذلك. لضرب أداء استثناءات لتصبح قضية كنت في حاجة إلى أن يكون استدعاء الدالة عدد كبير من المرات التي من المحتمل أن يكون هناك مشكلة في حد ذاته.

إذا الاستشاريين نشر تطبيق ASP.NET على الخادم الخاص بك (ق)، ثم أنها قد انتشرت في شكل uncompiled، وهو ما يعني أنه سيكون هناك مجموعة من الملفات * .cs تطوف التي يمكن أن ننظر.

وإذا كان كل ما يمكن أن تجد يتم تصنيف المجالس NET (دلس ويكسيس) لهما، ثم عليك أن تكون لا تزال قادرة على فك لهم في شفرة مصدر للقراءة إلى حد ما. أراهن إذا نظرتم خلال التعليمات البرمجية ستجد لهم باستخدام المتغيرات ثابتة في التعليمات البرمجية بحث الملكية الخاصة بهم. كنت ثم لدينا شيء ملموس جدا لاظهار أرباب العمل الخاص بك.

وهذا الدفق الجواب كله مليء المواقف مبرمج نموذجية. وهذا يذكرني "الأشياء التي ينبغي القيام به أبدا" جويل المادة (إعادة كتابة من الصفر.) ونحن لا نعرف حقا أي شيء عن النظام، وغيرها من هناك خلل، وبعض الرجل نشر بعض التعليمات البرمجية على الانترنت. هناك الكثير من المجاهيل أنه أمر مثير للسخرية أن تقول "هذا الرجل لا يعرف ماذا يفعل."

بدلاً من تكديس المستشار، يمكنك بسهولة تكديس الشخص الذي قام بشراء خدماته.لا يوجد مستشار مثالي، ولا مدير التوظيف...ولكن في نهاية المطاف فإن الاتجاه الحقيقي الذي يجب أن تسلكه واضح جدًا: بدلاً من محاولة العثور على الخطأ، يجب عليك بذل الطاقة في العمل بشكل تعاوني لإيجاد الحلول.بغض النظر عن مدى مهارة شخص ما في أدواره ومسؤولياته، فمن المؤكد أنه سيكون لديه أوجه قصور.إذا قررت أن هناك نمطًا من عدم الكفاءة، فقد تختار الانتقال إلى مورد آخر للمضي قدمًا، ولكن إلقاء اللوم لم يحل مشكلة واحدة في التاريخ أبدًا.

وفيما يتعلق بالنقطة الثانية، وأنا لن تستخدم استثناءات هنا. محجوزة استثناءات للحالات استثنائية.
ومع ذلك، وتقسيم أي شيء على صفر بالتأكيد لا لا يساوي صفر (في الرياضيات، على الأقل)، ولذلك فإن هذا سيكون لحالة محددة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top