هي القيم المنطقية طريقة الحجج غير مقبول ؟ [مغلقة]

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

سؤال

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

ما أسهل أن نفهم ؟

file.writeData( data, true );

أو

enum WriteMode {
  Append,
  Overwrite
};

file.writeData( data, Append );

الآن فهمت!;-)
هذا هو بالتأكيد مثال حيث التعداد الثاني المعلمة يجعل رمز أكثر قابلية للقراءة.

إذن ما رأيك في هذا الموضوع ؟

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

المحلول

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

ولكن إذا كان الاختيار بين خيارين لا بنعم أو لا, ثم التعداد في بعض الأحيان يمكن أن يكون أكثر قابلية للقراءة.

نصائح أخرى

Enums تسمح أيضا تعديلات مستقبلية ، حيث تريد الآن خيار ثالث (أو أكثر).

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

lock.setIsLocked(True);

أو

enum LockState { Locked, Unlocked };
lock.setLockState(Locked);

في هذه الحالة, قد تختار منطقية الخيار منذ اعتقد انها واضحة جدا ولا لبس فيها ، و أنا متأكد من بلدي قفل لن يكون أكثر من دولتين.لا يزال الخيار الثاني ساري المفعول ، ولكن معقدة دون داع ، IMHO.

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

تذكر السؤال أدلاي ستيفنسون الذي يشكله السفير زورين في الامم المتحدةخلال أزمة الصواريخ الكوبية?

"كنت في قاعة المحكمة من العالم الرأي الآن يمكنك الإجابة نعم أو لا.كنت قد نفى أن [الصواريخ] الوجود ، و أريد أن أعرف ما إذا كان قد فهمت بشكل صحيح....أنا مستعدة أن تنتظر جوابي حتى تتجمد الجحيم ، إذا كان هذا هو الخاص بك القرار".

إذا كان العلم في الأسلوب هو من النوع الذي يمكنك إضافته إلى ثنائي القرار, و هذا القرار سوف أبدا تتحول إلى ثلاثية أو n-الطريقة قرار الذهاب منطقية.مؤشرات:العلم الخاص بك يسمى isXXX.

لا تجعل منطقية في حالة ما مفتاح الوضع.هناك دائما أكثر واحد الوضعية ، مما كنت اعتقد من عند كتابة الطريقة في المقام الأول.

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

بالنسبة لي, لا تستخدم منطقية ولا التعداد هو نهج جيد.روبرت C.مارتن يلتقط هذا واضح جدا في رمز نظيفة نصيحة رقم 12:القضاء على حجج منطقية:

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

إذا كان الأسلوب يفعل أكثر من شيء واحد ، يجب أن تكتب بدلا اثنين من أساليب مختلفة ، على سبيل المثال في حالة: file.append(data) و file.overwrite(data).

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

هناك نوعان من الأسباب لقد واجهت هذا شيء سيء:

  1. لأن بعض الناس سوف أكتب أساليب مثل:

    ProcessBatch(true, false, false, true, false, false, true);
    

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

  2. لأن التحكم في تدفق البرنامج بسيطة نعم/لا فرع قد يعني أن لديك اثنين مختلفة تماما الوظائف التي هي ملفوفة في واحد في awkard الطريق.على سبيل المثال:

    public void Write(bool toOptical);
    

    حقا يجب أن يكون هذا طريقتين

    public void WriteOptical();
    public void WriteMagnetic();
    

    لأن التعليمات البرمجية في هذه قد تكون مختلفة تماما;أنها قد تضطر إلى القيام بكل أنواع مختلفة معالجة الأخطاء والتحقق من صحتها أو ربما حتى تنسيق البيانات الصادرة بشكل مختلف.لا يمكنك أن تقول ذلك فقط باستخدام Write() أو حتى Write(Enum.Optical) (على الرغم من وبطبيعة الحال يمكن أن يكون أي من تلك الأساليب فقط اتصل الطرق الداخلية WriteOptical/ماج إذا كنت تريد).

اعتقد ان ذلك يعتمد فقط.لا تجعل كبيرة جدا من الموضوع باستثناء #1.

Enums أفضل لكن لا أقول منطقية params بأنه "غير مقبول".في بعض الأحيان انها مجرد أسهل رمي شيء منطقية في والانتقال (اعتقد أساليب خاصة.... الخ)

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

file.writeData(data, overwrite=true)

أو:

[file writeData:data overwrite:YES]

أنا لا أوافق على أن القاعدة.ومن الواضح أن التعداد يجعل أفضل صريحة أو مطول في بعض الحالات, ولكن كقاعدة عامة يبدو الطريق على الوصول.

أولا اسمحوا لي أن تأخذ الخاص بك على سبيل المثال:المبرمجين المسؤولية (وقدرة) لكتابة كود جيدة ليست حقا للخطر من خلال وجود المعلمة المنطقية.في المثال الخاص بك مبرمج يمكن أن يكتب كما مطول كود عن طريق كتابة:

dim append as boolean = true
file.writeData( data, append );

أو كنت تفضل أكثر العامة

dim shouldAppend as boolean = true
file.writeData( data, shouldAppend );

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

Enums لها فائدة واضحة ، ولكن يجب أن لا تذهب فقط استبدال كل ما تبذلونه من القيم المنطقية مع enums.هناك العديد من الأماكن حيث true/false هو في الواقع أفضل طريقة لتمثيل ما يجري.

ومع ذلك ، واستخدامها كطريقة الحجج هو المشتبه به قليلا, ببساطة لأنك لا يمكن أن ترى من دون حفر في أشياء ما يفترض القيام به ، كما أنها تتيح لك رؤية ما true/false يعني في الواقع

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

C# على سبيل المثال:

var worker = new BackgroundWorker { WorkerReportsProgress = true };

روبي سبيل المثال

validates_presence_of :name, :allow_nil => true

بيثون سبيل المثال

connect_to_database( persistent=true )

الشيء الوحيد الذي يمكنني التفكير فيه منطقية الأسلوب الحجة هو الشيء الصحيح القيام به هو في جاوة ، حيث لم يكن لديك أي خصائص أو الكلمة الحجج.هذا هو واحد من الأسباب أكره java :-(

ولئن كان صحيحا أنه في كثير من الحالات enums أكثر للقراءة أكثر الموسعة من القيم المنطقية, قاعدة مطلقة أن "القيم المنطقية غير مقبولة" هو المعتوه.فمن غير مرنة وذات نتائج عكسية - لا تترك مجالا الإنسان الحكم.إنهم الأساسية التي بنيت في نوع في معظم اللغات لأنها مفيدة - النظر في تطبيقه على الأخرى المدمج في-أنواع:تقول على سبيل المثال "لم استخدم الباحث كمعلمة" أن يكون مجرد مجنون.

هذه القاعدة هي مجرد مسألة أسلوب ، وليس من احتمال الخلل أو وقت الأداء.أفضل القاعدة "تفضل enums إلى القيم المنطقية لأسباب القراءة".

نظرة على .Net framework.القيم المنطقية تستخدم المعلمات على عدد غير قليل من الطرق.على .Net API ليست مثالية, ولكن لا أعتقد أن استخدام منطقية كما المعلمات مشكلة كبيرة.تلميح الأدوات دائما يعطيك اسم المعلمة و يمكنك بناء هذا النوع من التوجيه أيضا - في ملء الخاص بك XML تعليقات على طريقة المعلمات ، سوف يأتي في تلميح الأدوات.

وأود أن أضيف أيضا أن هناك حالة عند بوضوح ريفاكتور القيم المنطقية تعداد - عندما يكون لديك اثنين أو أكثر من القيم المنطقية في صفك أو في طريقة params, و ليس كل الدول صالحة (على سبيل المثالإنه لا يصح أن يكون لهم تعيين كلا صحيح).

فعلى سبيل المثال ، إذا كان لديك فئة لديها خصائص مثل

public bool IsFoo
public bool IsBar

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

enum FooBarType { IsFoo, IsBar, IsNeither };

بعض القواعد التي زميلك قد يكون من الأفضل التمسك هي:

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

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

ميزة أخرى من التعداد هو أسهل للقراءة.

إذا كان الأسلوب يسأل سؤال مثل:

KeepWritingData (DataAvailable());

حيث

bool DataAvailable()
{
    return true; //data is ALWAYS available!
}

void KeepWritingData (bool keepGoing)
{
   if (keepGoing)
   {
       ...
   }
}

منطقية طريقة الحجج تبدو مثالية تماما معنى.

ذلك يعتمد على الأسلوب.إذا كان الأسلوب لا شيء من الواضح جدا أ true/false شيء ثم فإنه على ما يرام, على سبيل المثالأدناه [ولو لا أنا لا أقول هذا هو أفضل تصميم هذا الأسلوب هو مجرد مثال من حيث الاستخدام هو واضح].

CommentService.SetApprovalStatus(commentId, false);

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

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

Enums بالتأكيد يمكن أن تجعل القانون أكثر قابلية للقراءة.لا يزال هناك عدد قليل من الأشياء لمشاهدة (في .صافي على الأقل)

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

إذا كان الخاص بك enum هي خاصة إلى التعليمات البرمجية الخاصة بك (لم يتعرض علنا) ثم يمكنك التوقف عن القراءة هنا.

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

لا يمكن قانونا كتابة

WriteMode illegalButWorks = (WriteMode)1000000;
file.Write( data, illegalButWorks );

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

if (!Enum.IsDefined(typeof(WriteMode), userValue))
    throw new ArgumentException("userValue");

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

public static bool CheckWriteModeEnumValue(WriteMode writeMode)
{
  switch( writeMode )
  {
    case WriteMode.Append:
    case WriteMode.OverWrite:
      break;
    default:
      Debug.Assert(false, "The WriteMode '" + writeMode + "' is not valid.");
      return false;
  }
  return true;
}

في الإصدارات المسألة هو أن القانون القديم قد لا يعرفون سوى كيفية التعامل مع 2 enums لديك.إذا قمت بإضافة ثلث القيمة ، Enum.IsDefined سوف يكون هذا صحيحا ، ولكن القانون القديم لا يمكن بالضرورة التعامل معها.يصيح.

هناك حتى أكثر متعة يمكنك القيام به مع [Flags] enums و رمز التحقق هذا هو مختلفة قليلا.

سوف نلاحظ أيضا أن لقابلية, يجب عليك استخدام الاتصال ToString() على التعداد ، واستخدام Enum.Parse() عند القراءة لهم مرة أخرى.سواء ToString() و Enum.Parse() يمكن التعامل مع [Flags] التعداد هو كذلك, لذلك ليس هناك سبب عدم استخدامها.فتذكروا انه بعد شرك آخر ، لأنه الآن لا يمكنك حتى تغيير اسم التعداد بدون وربما كسر رمز.

لذا في بعض الأحيان تحتاج إلى وزن كل ما سبق في عندما تسأل نفسك هل يمكنني الحصول على بعيدا مع مجرد منطقي?

IMHO يبدو أن التعداد سيكون الخيار الواضح عن أي الحالة التي يكون فيها أكثر من اثنين من الخيارات الممكنة.ولكن بالتأكيد هناك حالات حيث منطقية هو كل ما تحتاج.في هذه الحالة أود أن أقول أن استخدام التعداد حيث منطقي ويكون العمل مثال على استخدام 7 الكلمات عند 4 سوف تفعل.

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

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

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

file.appendData( data );  
file.overwriteData( data );

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

Enums يمكن في بعض الحالات تجعل رمز أكثر قابلية للقراءة ، على الرغم من أن التحقق من الدقيق التعداد قيمة في بعض اللغات (C# على سبيل المثال) يمكن أن يكون صعبا.

في كثير من الأحيان منطقية المعلمة إلحاق قائمة المعالم الجديدة الزائد.مثال واحد في .صافي هي:

Enum.Parse(str);  
Enum.Parse(str, true); // ignore case

هذا الأخير الزائد أصبح متاحا في إصدار أحدث من .NET framework من الأولى.

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


تحرير

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

Enum.Parse(str, ignoreCase: true);

حيث أنا أوافق على أن Enums هي وسيلة جيدة للذهاب في الطرق حيث لديك 2 الخيارات (و اثنين فقط من الخيارات يمكنك القراءة دون enum.)

على سبيل المثال

public void writeData(Stream data, boolean is_overwrite)

أحب Enums ، ولكن منطقية مفيدة جدا.

هذا هو تأخر في الدخول على البريد القديم, و هو حتى الآن إلى أسفل الصفحة أن لا أحد سوف تقرأ من أي وقت مضى ، ولكن لأن لا أحد قد قال ذلك بالفعل....

مضمنة التعليق يقطع شوطا طويلا في حل غير متوقعة bool المشكلة.المثال الأصلي شنيعة لا سيما:تخيل تحاول اسم المتغير في الدالة declearation!سيكون شيئا مثل

void writeData( DataObject data, bool use_append_mode );

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

file.writeData( data, true );

مع

file.writeData( data, true /* use_append_mode */);

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

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

var v = CallMethod(pData = data, pFileMode = WriteMode, pIsDirty = true);

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

C# 3.0 يسمح اسمه الحجج في المنشئات.أنا لا أعرف لماذا لا يمكن أن تفعل هذا مع أساليب كذلك.

القيم المنطقية القيم true/false فقط.لذلك فإنه ليس من الواضح ما تمثل. Enum يمكن أن يكون معنى الاسم هـ.ز OVERWRITE, APPEND, ، وما إلى ذلك.حتى enums أفضل.

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