كتب ألن هولب "يجب ألا تستخدم وظائف الحصول على / مجموعة"، هل هو الصحيح؟ [مكرر

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

سؤال

هذا السؤال لديه بالفعل إجابة هنا:

كتب ألين هولب ما يلي،

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

التي تبدو معقولة، لكنه يذهب إلى القول

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

التي، بصراحة، فقط يبدو مجنون لي.

أفهم مبدأ مختبئ المعلومات، ولكن دون مواقف وموتورز لا يمكنك استخدام فاصوليات جافا على الإطلاق. لا أعرف كيف ستتبع تصميم MVC دون مواسفات في النموذج، منذ النموذج لا تستطيع كن مسؤولا عن تقديم الرأي.

ومع ذلك، فأنا مبرمج أصغر وأتعلم المزيد عن التصميم الموجه نحو الكائنات كل يوم. ربما يمكن لأي شخص لديه خبرة أكبر في هذه المشكلة.

مقالات ألين هولوب للرجوع اليها


أسئلة ذات صلة:

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

المحلول

ليس لدي مشكلة مع holub أخبرك أنه يجب عليك عموما تجنب تغيير دولة من كائن ولكن بدلا من ذلك اللجوء إلى الأساليب المتكاملة (تنفيذ السلوكيات) لتحقيق هذه الغاية. كما يشير Corletk، هناك حكمة في التفكير لفترة طويلة وصعبة حول أعلى مستوى من التجريد وليس فقط البرمجة بلا تفكير مع getters / setsters التي تتيح لك فقط القيام بتغليف نهاية.

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

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

نصائح أخرى

قراءة من خلال تلك المادة بعناية. هولوب يدفع النقطة التي تعتبرها getters and setsters هي "antipattern الافتراضية"، عادة سيئة تنزلقها عند تصميم نظام؛ لأننا نستطيع.

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

السيارة مثال جيد. إنه يكشف عن واجهة رفيعة المستوى محددة جيدا. أنا لا أثير نفسي setSpeed(60)... هل هذا ميل في الساعة أو كم / ساعة؟ أنا فقط تسريع، كروز، تباطؤ. ليس لدي التفكير في التفاصيل setSteeringWheelAngle(getSteeringWheelAngle()+Math.rad(-1.5)), ، أنا فقط turn(-1.5), ، والتفاصيل العناية تحت الغطاء.

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

في بعض الأحيان تكون المتطلبات الفعلية للفئة غير معروفة في وقت مبكر. هذا رائع، فقط cop-out واستخدام getter / setter antipattern الآن، ولكن عندما تعرف، من خلال الخبرة، ما يتم استخدام الفئة من أجله، من المحتمل أن ترغب في العودة وتنظيف واجهة المستوى المنخفضة القذرة. إعادة الإنفاق على أساس "الأشياء التي تتمنى أن تعرفها عندما تكتب مصاصة في المقام الأول" هي قدم المساواة في الدورة. لا يتعين عليك معرفة كل شيء من أجل البدء، فهذا ما تعرفه أكثر، من المحتمل أن تكون إعادة صياغة أقل حاجة عند الطريق.

هذه هي العقلية التي يعززها. getters و setters هي فخ سهلة للسقوط فيها.

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

daisy.setColor(Color.PINK) يجعل الشعور بالكمال. ماذا يمكنك أن تفعل أيضا؟ ربما مانع فولكان ميلد، لجعل الزهرة تريد أن تكون وردي؟ أمم؟

getters والعمالين لديهم الشر؟ الشر؟ مكان. إنه فقط، مثل كل الأشياء الجيدة حقا OO، نميل إلى إفراط في استخدامها، لأنها آمنة ومألوفة، ناهيك عن بسيطة، وبالتالي قد يكون من الأفضل أن تكون Noobs لم ير أو نسمع عنها، على الأقل حتى " أتقن D الشيء العقل ميلد.

أعتقد أن ما حاول آلن هولب قوله، وإعادة صياغته هذه المادة، هي ما يلي.

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

كان لدى المبرمجين المتاعب، وكان ألين هولوب في مشيرا إلى ذلك، هو أنهم يستخدمون أحيانا betters / setters لجميع المتغيرات. ويضيع الغرض من التغليف.

(لاحظ أنني قادم في هذا من زاوية "الممتلكات" .NET)

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

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

الملحقات ليس تفاصيل التنفيذ؛ هم API العام / العقد. نعم، إذا كسرت contracft لديك مشكلة. متى أصبح ذلك مفاجأة؟ وبالمثل، ليس من غير المألوف أن يكون الملحقات غير تافهة - أي يفعلون أكثر من مجرد لف الحقول؛ إنهم يؤدون الحسابات، والشيكات المنطقية، والإشعارات، وما إلى ذلك، وهم يسمحون بإجراء تجريدية قائمة على الواجهة. أوه، وأوليمدرومورف - إلخ.

إعادة الطبيعة المطلي للمسافرين (P3؟ 4؟) - في C #: public int Foo {get; private set;} - تم انجاز العمل.

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

يتم استخدام Getters و Setters أقل من قناعا لجعل جمهور متغير خاص.

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

فعلت بعض googling الإضافية على ألن هولب، يبدو أنه لديه حصته من المعارضين هناك في مجتمع Java.

آخر واحد يشير بشكل خاص. نص المعلق في مائل.

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

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

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

ضع في اعتبارك أنني لم أضع أي رمز UI في منطق الأعمال. لقد كتبت طبقة UI من حيث AWT (Toolkit النافذة المجردة) أو الأرجوحة، والتي هي كل من طبقات التجريد.

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

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

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

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

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

لا أعتقد أنه يقول إنه لا يستخدم أبدا الحصول على الحصول على الحصول على / مجموعة، بل أن استخدام الحصول على / تعيين للحقل ليس أفضل من مجرد جعل الحقل العامة (مثل اسم السلسلة العامة مقابل اسم السلسلة العامة {get؛ set؛}).

إذا تم استخدام Get / set، فإنه يحد من المعلومات التي تختبئ OO والتي يمكن أن تقفلك إلى واجهة سيئة.

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

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

هدف OO هو التصميم بمستوى من التجريد؛ لا تعرض المزيد من التفاصيل مما يجب عليك تماما.

هناك احتمالات إذا كنت قد ملفوفت فقط نوعا بدائيا مع الحصول على Get / set لقد كسرت هذا التينيت.

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

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

Getters و Sensters منطقية عندما تعكس نوعا ما من الفكرة المتسق. في فئة المضلع، على سبيل المثال، فإن إحداثيات X و Y من القمم المعنية لها معنى خارج حدود الفصل. من المحتمل أن يكون من المنطقي أن يكون لديك getters، ومن المحتمل أن يكون من المنطقي أن يكون لديك setters. في فئة حساب مصرفي، من المحتمل أن يتم تخزين الرصيد كمتغير خاص، وبالتأكيد يجب أن يكون لديه ماونتر. إذا كان لديه صارما، فسيحتاج إلى تسجيل الدخول في الحفاظ على قابلية مراجعة الحساسية.

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

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

لذلك، أود أن أقول لاستخدام المتغيرات الخاصة تقريبا حصريا، والحيوtters و setters حيث لديهم معنى حقيقي في سلوك الكائن، وليس خلاف ذلك.

لمجرد أن Jetters و Sensers بشكل متكرر كثيرا ما لا يعني أنهم عديمة الفائدة.

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

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

setPositionX("some string");

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

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

public void tryPositionX(int x) throws InvalidParameterException{
    if (x >= 0)
        this.x = x;
    else
        throw new InvalidParameterException("Holy Negatives Batman!");
}

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

tryPositionXAndLog(int x) throws InvalidParameterException{
    tryPositionX(x);
    numChanges++;
}

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

تذكر MVC أيضا ويقول إن النموذج لا يمكن أن يكون مسؤولا عن طريقة العرض، ولهذه الحالة يعطي Allen Holub مثالا على جعل طبقة التجريد من خلال وجود "إعطاء Me-jcomponent-is-is-is-is-is-is-indity" الذي يقول إن "عزل الطريقة التي تمثل بها الهويات من بقية النظام". أنا لا أختبر بما فيه الكفاية للتعليق على ما إذا كان ذلك يعمل أم لا ولكن على السطح يبدو فكرة جيدة.

Getters / Setters العامة سيئة إذا قدموا الوصول إلى تفاصيل التنفيذ. ومع ذلك، من المعقول توفير الوصول إلى خصائص الكائن واستخدام Getters / Setters لهذا الغرض. على سبيل المثال، إذا كانت السيارة تحتوي على خاصية اللون، فمن المقبول أن تدع العملاء "لاحظوا" باستخدام Getter. إذا كان بعض العميل يحتاج إلى القدرة على إعادة استدعاء السيارة، فيمكن للفئة أن توفر قاعدة صارمة ('RECOLOR' هو الاسم الأكثر وضوحا على الرغم من). من المهم عدم إجراء عدم معرفة العملاء كيفية تخزين الخصائص في الكائنات، وكيف يتم الحفاظ عليها وما إلى ذلك.

Ummmm ... لم يسمع أبدا عن مفهوم التغليف. يتم وضع طرق Getter و Setter للسيطرة على الوصول إلى أعضاء الفصل. من خلال صنع جميع المجالات مرئية علانية ... يمكن لأي شخص كتابة أي قيم تريدها وبالتالي إبطال الكائن بأكمله تماما.

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

التغليف (علوم الكمبيوتر)

... وإذا كانوا شريرا حقا، هل يمكن .NET إنشاء مفهوم العقار في اللغة؟ (Getter و STERTER طرق تبدو فقط أجمل قليلا)

تعديل

يذكر المقال التغليف:

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

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

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

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