عكس اسم المعلمة: إساءة استخدام تعبيرات C # Lambda أو بناء جملة Billiance؟

StackOverflow https://stackoverflow.com/questions/1718037

سؤال

أنا أبحث في mvccontrib مكون الشبكة وأنا مفتون، ولكن في نفس الوقت صد، من خلال خدعة النحوية المستخدمة في بناء جملة الشبكة:

.Attributes(style => "width:100%")

بناء الجملة أعلاه يعين سمة النمط من HTML الذي تم إنشاؤه width:100%. وبعد الآن إذا كنت تولي اهتماما، فإن "الأسلوب" غير محدد، يتم استنتاج من اسم من المعلمة في التعبير! اضطررت إلى حفر هذا ووجدت أين يحدث "السحر":

Hash(params Func<object, TValue>[] hash)
{
    foreach (var func in hash)
    {
        Add(func.Method.GetParameters()[0].Name, func(null));
    }
}

في الواقع، فإن الرمز يستخدم الوقت الرسمي، والترجمة، واسم المعلمات لإنشاء قاموس أزواج قيمة سمة اسم السمة. بناء الجملة المنتج الناتج معبري للغاية بالفعل، ولكن في نفس الوقت خطير للغاية. يسمح الاستخدام العام لتعبيرات Lambda لاستبدال أسماء تستخدم دون تأثير جانبي. أرى مثالا في كتاب يقول collection.ForEach(book => Fire.Burn(book)) أعلم أنني أستطيع الكتابة في التعليمات البرمجية collection.ForEach(log => Fire.Burn(log)) و انه يعني نفس الشيء. وبعد ولكن مع بناء جملة شبكة MVCContrib هنا فجأة، أجد كود ينظر بنشاط واتخاذ القرارات بناء على الأسماء التي اخترتها لمتغيراتي!

فهل هذه الممارسة المشتركة مع مجتمع C # 3.5 / 4.0 عشاق تعبيرات Lambda؟ أو هي خدعة واحدة مارقة مافريك لا ينبغي أن تقلق بشأن؟

هل كانت مفيدة؟

المحلول

هذا لديه فقير interop. على سبيل المثال، النظر في هذا C # - F #

C #:

public class Class1
{
    public static void Foo(Func<object, string> f)
    {
        Console.WriteLine(f.Method.GetParameters()[0].Name);
    }
}

F#:

Class1.Foo(fun yadda -> "hello")

نتيجة:

"Arg" مطبوعة (وليس "Yadda").

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

نصائح أخرى

أجد أن الغريب ليس كثيرا بسبب اسم, ، ولكن بسبب Lambda غير ضروري; ؛ يمكن استخدام نوع مجهول ويكون أكثر مرونة:

.Attributes(new { style = "width:100%", @class="foo", blip=123 });

هذا هو نمط يستخدم في الكثير من ASP.NET MVC (على سبيل المثال)، و استخدامات اخرىمذكرة قانونية, ، لاحظ ايضا أفكار عيسين إذا كان الاسم قيمة سحرية بدلا من المتصل الخاص)

أردت فقط أن رمي في رأيي (أنا مؤلف مكون شبكة MVCContrib).

هذا هو بالتأكيد إساءة استخدام اللغة - لا شك في ذلك. ومع ذلك، لن أعتبر أنه عكس ذلك بديهية - عندما تنظر إلى مكالمة Attributes(style => "width:100%", @class => "foo")
أعتقد أنه من الواضح أن ما يحدث (بالتأكيد ليس أسوأ من نهج النوع المجهول). من منظور IntelliSense، أوافق على أنه رائع.

بالنسبة للمهتمين، بعض المعلومات الأساسية في استخدامها في MVCContrib ...

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

إذا كان C # كان لديه بناء جملة أقل حرفا للحرفية القاموس، فلن أزعجني بما في ذلك بناء الجملة في مكون الشبكة :)

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

أيضا، ذكر شخص ما "الانعكاس النفقات العامة" وأردت فقط أن أشير إلى أنه ليس هناك الكثير من النفقات العامة مع هذا النهج - لا يوجد تعكس وقت التشغيل أو تجميع التعبير المعني (انظر http://blog.bittercoder.com/permalink gguid، 206e64d1-29ae-4362-874B-83F5B103727F.ASPX.).

انا افضل

Attributes.Add(string name, string value);

إنه أكثر صراحة ومعيار ولا شيء يتم اكتسابه باستخدام Lambdas.

مرحبا بكم في القضبان الأرض :)

لا يوجد شيء خاطئ حقا طالما تعرف ما الذي يحدث. (عندما لا يتم توثيق هذا النوع من الأشياء جيدا أن هناك مشكلة).

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

مكان آخر حيث رأيت خدعة مثل هذا في تأكيدات استدعاء الأسلوب في موك. تمر في Lambda، ولكن لم يتم تنفيذ Lambda أبدا. إنهم يستخدمون التعبير فقط للتأكد من حدوث استدعاء الأسلوب ورمي استثناء إن لم يكن كذلك.

هذا هو رهيب على أكثر من مستوى واحد. ولا، هذا لا شيء مثل روبي. إنه إساءة استخدام C # و .NET.

كان هناك العديد من الاقتراحات حول كيفية القيام بذلك بطريقة أكثر تباين إلى الأمام: Tuples، وأنواع مجهولة، وواجهة بطلاقة وهلم جرا.

ما الذي يجعله سيئا للغاية هو أن طريقتها فقط لتوضيح من أجلها جيدة:

  • ماذا يحدث عندما تحتاج إلى الاتصال بهذا من VB؟

    .Attributes(Function(style) "width:100%")

  • لها مواجهة تماما بديهية، سيوفر Intellisense مساعدة قليلة في معرفة كيفية تمرير الأشياء في.

  • لها غير فعالة دون داع.

  • لن يكون لأحد أي فكرة عن كيفية الحفاظ عليه.

  • ما هو نوع الحجة التي تسير في السمات، هل Func<object,string> ب كيف تكشف هذه النية. ما هي وثائقك الاحتياجات الخاصة بك، "يرجى تجاهل جميع قيم الكائن"

أعتقد أنك مبرر تماما وجود مشاعر الاشمئزاز.

أنا في مخيم "بناء جملة Brilliance"، إذا وثابته بوضوح، ويبدو هذا رائعا، فلا توجد مشكلة تقريبا في IMO!

كلاهما. إنه مسؤولية تعبيرات لامدا و بناء بناء جملة.

بالكاد جاءت عبر هذا النوع من الاستخدام. أعتقد أنه "غير مناسب" :)

هذه ليست طريقة شائعة للاستخدام، فمن غير المتناقضة مع الاتفاقيات العامة. هذا النوع من بناء الجملة لديه إيجابيات وسلبيات بالطبع:

سلبيات

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

إياب

  • إنه أكثر قابلية للقراءة بعد المطور المعدل على بناء الجملة هذا.

الحد الأدنى - في تصميم API العام، كنت قد اخترت طريقة أكثر صراحة.

لا، إنها بالتأكيد ليست ممارسة شائعة. إنها مضادة بديهية، لا توجد وسيلة للنظر في التعليمات البرمجية لمعرفة ما يفعله. عليك أن تعرف كيف يتم استخدامها لفهم كيف يتم استخدامها.

بدلا من توفير سمات باستخدام مجموعة من المندوبين، ستكون أساليب المدارس أكثر وضوحا وأداء أفضل:

.Attribute("style", "width:100%;").Attribute("class", "test")

على الرغم من أن هذا أكثر قليلا للكتابة، إلا أنه واضح وبديهيا.

هل يمكنني استخدام هذا لعملية عملة عبارة؟

Magic Lambda (n): وظيفة Lambda المستخدمة فقط لغرض استبدال سلسلة سحرية.

ما هو الخطأ في ما يلي:

html.Attributes["style"] = "width:100%";

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

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

الاقتراب من التعبير عن إرشاداتنا لأجهزة الكمبيوتر بنفس الطريقة التي نعتقد أنها داخليا هي مفتاح جعل البرامج أكثر دقة وأكثر دقة.

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

هذه واحدة من فوائد أشجار التعبير - يمكن للمرء فحص الكود نفسه للحصول على معلومات إضافية. هذه هي الطريقة التي .Where(e => e.Name == "Jamie") يمكن تحويلها إلى SQL المكافئ حيث جملة. هذا هو استخدام ذكي لأشجار التعبير، على الرغم من أنني آمل أن لا تذهب إلى أبعد من ذلك. من المرجح أن يكون أي شيء أكثر تعقيدا أكثر صعوبة من التعليمات البرمجية التي تأمل في استبدالها، لذلك أظن أنه سيكون الحد من النفس.

إنه نهج مثير للاهتمام. إذا كنت تقيد الجانب الأيمن من التعبير ليكون ثوابت فقط، فيمكنك تنفيذ استخدام

Expression<Func<object, string>>

ما أعتقد أنه ما تريده حقا بدلا من المندوب (أنت تستخدم Lambda للحصول على أسماء كلا الجانبين)، انظر التنفيذ الساذج أدناه:

public static IDictionary<string, string> Hash(params Expression<Func<object, string>>[] hash) {
    Dictionary<string, string> values = new Dictionary<string,string>();
    foreach (var func in hash) {
        values[func.Parameters[0].Name] = ((ConstantExpression)func.Body).Value.ToString();
    }
    return values;
}

قد يؤدي ذلك إلى معالجة اهتمام اللغة عبر الإنترنت التي تم ذكرها في وقت سابق في الخيط.

الرمز ذكي للغاية، ولكن يحتمل أن يسبب المزيد من المشاكل التي يحلها.

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

سيكون الحل الأفضل هو الحصول على عضو بيانات يمكن التحقق منه في وقت الترجمة. لذلك بدلا من هذا:

.Attributes(style => "width:100%");

يمكن التحقق من رمز مع خاصية نمط من قبل المحول البرمجي:

.Attributes.Style = "width:100%";

او حتى:

.Attributes.Style.Width.Percent = 100;

هذا أكثر عمل لمؤلفي الكود، ولكن هذا النهج يستفيد من قدرة التحقق من النوع القوي C #، مما يساعد على منع الحشرات من الدخول إلى التعليمات البرمجية في المقام الأول.

في الواقع يبدو مثل Ruby =)، على الأقل بالنسبة لي استخدام مورد ثابت لإجراء "بحث ديناميكي" لاحق لا يناسب اعتبارات تصميم API، نأمل أن تكون هذه الخدعة الذكية اختيارية في واجهة برمجة تطبيقات.

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

أتمنى أن يساعدك هذا

IMHO، إنها طريقة رائعة للقيام بذلك. نحب جميعا حقيقة أن تسمية وحدة تحكم فئة ستجعلها وحدة تحكم في MVC أليس كذلك؟ لذلك هناك حالات تهم فيه التسمية.

أيضا النية واضحة جدا هنا. من السهل جدا فهم ذلك .Attribute( book => "something") سوف يؤدي إلى book="something" و .Attribute( log => "something") سوف يؤدي إلى log="something"

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

في رأيي، إنها إساءة معاملة Lambdas.

بالنسبة إلى بناء جملة BRILNIANCE style=>"width:100%" مربكة عادية. خاصة بسبب => بدلا من =

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

أعتقد أن هذا ليس أفضل من "السلاسل السحرية". أنا لست كثيرا من أنواع الأنواع المجهولة إما لهذا. يحتاج إلى نهج أفضل وثوبيا بقوة.

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