ใช้คลาสเพื่อนเพื่อแค็ปซูลฟังก์ชั่นสมาชิกส่วนตัวใน C ++ - การปฏิบัติที่ดีหรือการละเมิด?


12

ดังนั้นฉันสังเกตเห็นว่าเป็นไปได้ที่จะหลีกเลี่ยงการใส่ฟังก์ชั่นส่วนตัวไว้ในส่วนหัวโดยทำสิ่งนี้:

// In file pred_list.h:
    class PredicateList
    {
        int somePrivateField;
        friend class PredicateList_HelperFunctions;
    public:
        bool match();
    } 

// In file pred_list.cpp:
    class PredicateList_HelperFunctions
    {
        static bool fullMatch(PredicateList& p)
        {
            return p.somePrivateField == 5; // or whatever
        }
    }

    bool PredicateList::match()
    {
        return PredicateList_HelperFunctions::fullMatch(*this);
    }

ฟังก์ชั่นส่วนตัวไม่เคยประกาศในส่วนหัวและผู้บริโภคของชั้นเรียนที่นำเข้าส่วนหัวไม่จำเป็นต้องรู้ว่ามันมีอยู่ นี่เป็นสิ่งจำเป็นหากฟังก์ชันตัวช่วยเป็นเทมเพลต (ทางเลือกคือใส่รหัสเต็มในส่วนหัว) ซึ่งเป็นวิธีที่ฉัน "ค้นพบ" สิ่งนี้ ข้อดีอีกอย่างที่ไม่จำเป็นต้องคอมไพล์ใหม่ทุกไฟล์ที่มีส่วนหัวหากคุณเพิ่ม / ลบ / แก้ไขฟังก์ชั่นสมาชิกส่วนตัว ฟังก์ชั่นส่วนตัวทั้งหมดอยู่ในไฟล์. cpp

ดังนั้น...

  1. นี่เป็นรูปแบบการออกแบบที่รู้จักกันดีว่ามีชื่อหรือไม่
  2. สำหรับฉัน (มาจากพื้นหลัง Java / C # และเรียนรู้ C ++ ในเวลาของฉันเอง) สิ่งนี้ดูเหมือนจะเป็นสิ่งที่ดีมากเนื่องจากส่วนหัวคือการกำหนดอินเทอร์เฟซในขณะที่. cpp กำลังกำหนดการใช้งาน โบนัสที่ดี) อย่างไรก็ตามมันก็มีกลิ่นเหมือนว่ามันเป็นการใช้ภาษาในทางที่ผิดซึ่งไม่ได้ตั้งใจจะนำมาใช้ แล้วมันคืออะไร? นี่เป็นสิ่งที่คุณอยากเห็นในโครงการ C ++ มืออาชีพหรือไม่?
  3. ข้อผิดพลาดใด ๆ ที่ฉันไม่ได้คิด

ฉันตระหนักถึง Pimpl ซึ่งเป็นวิธีที่แข็งแกร่งกว่าในการซ่อนการใช้งานที่ขอบห้องสมุด สิ่งนี้มีไว้สำหรับใช้กับคลาสภายในซึ่ง Pimpl อาจทำให้เกิดปัญหาด้านประสิทธิภาพหรือไม่ทำงานเนื่องจากคลาสนั้นต้องได้รับการปฏิบัติเสมือนเป็นค่า


แก้ไข 2: คำตอบที่ดีเยี่ยมของ Dragon Energy ด้านล่างแนะนำวิธีแก้ไขปัญหาต่อไปนี้ซึ่งไม่ได้ใช้friendคำหลักเลย:

// In file pred_list.h:
    class PredicateList
    {
        int somePrivateField;
        class Private;
    public:
        bool match();
    } 

// In file pred_list.cpp:
    class PredicateList::Private
    {
    public:
        static bool fullMatch(PredicateList& p)
        {
            return p.somePrivateField == 5; // or whatever
        }
    }

    bool PredicateList::match()
    {
        return PredicateList::Private::fullMatch(*this);
    }

สิ่งนี้หลีกเลี่ยงปัจจัยช็อตของfriend(ซึ่งดูเหมือนจะถูกปิศาจเหมือนgoto) ในขณะที่ยังคงหลักการเดิมของการแยก


2
" ผู้บริโภคสามารถกำหนด PredicateList_HelperFunctions คลาสของตัวเองและให้พวกเขาเข้าถึงเขตข้อมูลส่วนตัว " นั่นจะเป็นการละเมิด ODRหรือไม่? ทั้งคุณและผู้บริโภคจะต้องมีการกำหนดระดับเดียวกัน หากคำจำกัดความเหล่านั้นไม่เท่ากันรหัสนั้นจะเกิดขึ้นไม่ดี
Nicol Bolas

คำตอบ:


13

มันเป็นเรื่องลึกลับเล็กน้อยที่จะพูดให้น้อยที่สุดเท่าที่คุณจำได้ซึ่งอาจทำให้ฉันเกาหัวสักครู่เมื่อฉันเริ่มพบรหัสของคุณก่อนที่สงสัยว่าคุณกำลังทำอะไรอยู่ / อุปนิสัย (ณ จุดที่ฉันอาจคุ้นเคยกับมันทั้งหมด)

ฉันชอบที่คุณลดปริมาณข้อมูลในส่วนหัว โดยเฉพาะอย่างยิ่งในฐานรหัสขนาดใหญ่มากที่สามารถมีผลในทางปฏิบัติเพื่อลดการพึ่งพาเวลารวบรวมและในที่สุดก็สร้างครั้ง

ปฏิกิริยาทางเดินอาหารของฉันคือว่าถ้าคุณรู้สึกว่าจำเป็นต้องซ่อนรายละเอียดการใช้งานด้วยวิธีนี้เพื่อให้การสนับสนุนพารามิเตอร์ที่ส่งผ่านไปยังฟังก์ชั่นว่างด้วยการเชื่อมโยงภายในในไฟล์ต้นฉบับ โดยปกติแล้วคุณสามารถใช้ฟังก์ชั่นยูทิลิตี้ (หรือคลาสทั้งหมด) มีประโยชน์สำหรับการใช้คลาสเฉพาะโดยไม่ต้องเข้าถึง internals ทั้งหมดของคลาสและเพียงแค่ส่งผ่านสิ่งที่เกี่ยวข้องจากการใช้เมธอดไปยังฟังก์ชัน (หรือคอนสตรัคเตอร์) และเป็นธรรมชาติที่มีโบนัสในการลดการมีเพศสัมพันธ์ระหว่างชั้นเรียนของคุณและ "ผู้ช่วยเหลือ" นอกจากนี้ยังมีแนวโน้มที่จะสรุปสิ่งที่อาจเป็น "ผู้ช่วยเหลือ" เพิ่มเติมหากคุณพบว่าพวกเขาเริ่มให้บริการวัตถุประสงค์ทั่วไปที่ใช้กับการใช้งานมากกว่าหนึ่งชั้น

บางครั้งฉันก็ประจบประแจงเล็กน้อยเมื่อฉันเห็น "ผู้ช่วยเหลือ" จำนวนมากในรหัส มันไม่ได้เป็นความจริงเสมอไป แต่บางครั้งพวกเขาก็สามารถแสดงอาการของนักพัฒนาที่เพิ่งสลายฟังก์ชั่นโดยจำใจเพื่อกำจัดการทำซ้ำโค้ดด้วยการหยดข้อมูลขนาดใหญ่ที่ถูกส่งผ่านไปยังฟังก์ชันที่มีชื่อ / วัตถุประสงค์ที่เข้าใจยาก รหัสที่จำเป็นสำหรับการใช้งานฟังก์ชั่นอื่น ๆ เพียงเล็กน้อยคิดล่วงหน้าเล็ก ๆ น้อย ๆ บางครั้งอาจนำไปสู่ความชัดเจนมากขึ้นในแง่ของวิธีการใช้งานของชั้นเรียนถูกแบ่งออกเป็นฟังก์ชั่นเพิ่มเติมและการสนับสนุนผ่านพารามิเตอร์ที่เฉพาะเจาะจงเพื่อส่งผ่านกรณีทั้งหมดของวัตถุของคุณ ส่งเสริมแนวคิดการออกแบบ ฉันไม่แนะนำให้คุณทำอย่างนั้นแน่นอน (ฉันไม่รู้)

หากสิ่งนั้นกลายเป็นเรื่องไม่แน่นอนฉันจะพิจารณาวิธีแก้ปัญหาที่สองซึ่งเป็นสำนวนมากกว่าซึ่งเป็น pimpl (ฉันรู้ว่าคุณพูดถึงปัญหาด้วย แต่ฉันคิดว่าคุณสามารถสรุปวิธีแก้ปัญหาเพื่อหลีกเลี่ยงปัญหาเหล่านั้นด้วยความพยายามน้อยที่สุด) ที่สามารถย้ายข้อมูลจำนวนมากทั้งหมดที่คลาสของคุณต้องการนำไปใช้รวมถึงข้อมูลส่วนตัวของมันอยู่ห่างจากส่วนหัวขายส่ง ปัญหาด้านประสิทธิภาพของ pimpl สามารถลดลงได้อย่างมากด้วยตัวจัดสรรเวลาคงที่ราคาถูกสกปรก * เหมือนรายการฟรีในขณะที่รักษาความหมายของค่าโดยไม่ต้องใช้ ctor สำเนาที่ผู้ใช้กำหนดเองเต็มรูปแบบ

  • สำหรับด้านประสิทธิภาพ pimpl แนะนำค่าใช้จ่ายตัวชี้อย่างน้อยที่สุด แต่ฉันคิดว่าคดีต้องร้ายแรงมากที่ต้องคำนึงถึงเรื่องจริง หากตำแหน่งเชิงพื้นที่ไม่ได้ลดลงอย่างมีนัยสำคัญผ่านตัวจัดสรรดังนั้นลูปที่วนซ้ำของคุณจะวนซ้ำกับวัตถุ (ซึ่งโดยทั่วไปควรเป็นเนื้อเดียวกันหากประสิทธิภาพนั้นเป็นเรื่องที่น่ากังวลมาก) จะยังคงมีแนวโน้มที่จะลดการพลาดแคชในทางปฏิบัติ รายการอิสระในการจัดสรร pimpl ทำให้ฟิลด์ของคลาสเป็นบล็อกหน่วยความจำที่ต่อเนื่องกันเป็นส่วนใหญ่

โดยส่วนตัวหลังจากหมดความเป็นไปได้เหล่านั้นฉันจะพิจารณาบางอย่างเช่นนี้ ฉันคิดว่ามันเป็นความคิดที่ดีถ้าทางเลือกเป็นเหมือนวิธีการส่วนตัวที่เปิดเผยกับส่วนหัวซึ่งอาจมีเพียงความลึกลับที่เป็นความลับในทางปฏิบัติ

ทางเลือก

ทางเลือกหนึ่งที่โผล่เข้ามาในหัวของฉันในตอนนี้ที่ทำให้เป้าหมายเดียวกันกับเพื่อนที่ขาดไปของคุณส่วนใหญ่เป็นเช่นนี้:

struct PredicateListData
{
     int somePrivateField;
};

class PredicateList
{
    PredicateListData data;
public:
    bool match() const;
};

// In source file:
static bool fullMatch(const PredicateListData& p)
{
     // Can access p.somePrivateField here.
}

bool PredicateList::match() const
{
     return fullMatch(data);
}

ตอนนี้อาจดูเหมือนว่าจะแตกต่างกันมากและฉันก็ยังเรียกมันว่า "ผู้ช่วยเหลือ" (ในความรู้สึกเสื่อมเสียเนื่องจากเรายังคงส่งผ่านสถานะภายในทั้งหมดของคลาสไปยังฟังก์ชันไม่ว่าจะต้องการทั้งหมดหรือไม่ก็ตาม) ยกเว้นว่ามันจะไม่หลีกเลี่ยง "ช็อต" friendปัจจัยที่จะเผชิญหน้า โดยทั่วไปแล้วfriendดูน่ากลัวนิดหน่อยที่จะเห็นการขาดการตรวจสอบเพิ่มเติมบ่อยครั้งเนื่องจากมันบอกว่า internals ในชั้นเรียนของคุณสามารถเข้าถึงได้จากที่อื่น (ซึ่งมีความหมายว่า ด้วยวิธีที่คุณใช้friendมันจะกลายเป็นข้อสงสัยหากผู้คนตระหนักถึงการปฏิบัติตั้งแต่friendเป็นเพียงการอยู่ในไฟล์ต้นฉบับเดียวกันเพื่อช่วยในการใช้งานฟังก์ชั่นส่วนตัวของชั้นเรียน แต่สิ่งที่กล่าวมาข้างต้นนั้นประสบความสำเร็จอย่างมากในเรื่องเดียวกันอย่างน้อยก็มีข้อดีที่พิสูจน์ได้ว่ามันไม่เกี่ยวข้องกับเพื่อน ๆ shoot คลาสนี้มีเพื่อนคนอื่น ๆ จะเข้าถึงหรือกลายพันธุ์ได้ที่ไหน ") ในขณะที่รุ่นเหนือทันทีสื่อสารว่ามีวิธีไม่มีไพร่พลที่จะเข้าถึง / PredicateListนอกกลายพันธุ์ของสิ่งที่ทำในการดำเนินงานของ

นั่นอาจจะเคลื่อนไปสู่ดินแดนดื้อดึงที่มีระดับความแตกต่างกันเล็กน้อยเนื่องจากใคร ๆ ก็สามารถรู้ได้อย่างรวดเร็วว่าคุณมีชื่อที่เหมือนกัน*Helper*และทำให้พวกเขาทั้งหมดอยู่ในไฟล์ต้นฉบับเดียวกันซึ่งมันรวมกันเป็นส่วนหนึ่งของการนำคลาสส่วนตัว แต่ถ้าเราได้รับจู้จี้จุกจิกบางทีสไตล์ข้างต้นในทันทีจะไม่ทำให้เกิดปฏิกิริยากระตุกเข่ามากนักโดยไม่รวมfriendคำสำคัญที่มีแนวโน้มจะดูน่ากลัวเล็กน้อย

สำหรับคำถามอื่น ๆ :

ผู้บริโภคสามารถกำหนด PredicateList_HelperFunctions คลาสของตัวเองและให้พวกเขาเข้าถึงฟิลด์ส่วนตัว ในขณะที่ฉันไม่เห็นว่านี่เป็นปัญหาใหญ่ (ถ้าคุณต้องการที่เขตข้อมูลส่วนตัวเหล่านั้นคุณสามารถทำการคัดเลือกนักแสดงได้) บางทีมันอาจกระตุ้นให้ผู้บริโภคใช้มันอย่างนั้น?

นั่นอาจเป็นไปได้ที่จะข้ามขอบเขตของ API ซึ่งไคลเอนต์สามารถกำหนดคลาสที่สองด้วยชื่อเดียวกันและเข้าใช้งาน internals ในลักษณะที่ไม่มีข้อผิดพลาดในการเชื่อมโยง จากนั้นอีกครั้งฉันส่วนใหญ่ C coder ทำงานในกราฟิกที่ความกังวลด้านความปลอดภัยในระดับนี้ "เกิดอะไรขึ้น" ต่ำมากในรายการลำดับความสำคัญดังนั้นความกังวลเช่นนี้เป็นเพียงคนที่ฉันมักจะโบกมือและเต้นรำ พยายามแสร้งทำเหมือนไม่มีอยู่จริง :-D หากคุณกำลังทำงานในโดเมนที่มีความกังวลเช่นนี้ค่อนข้างร้ายแรง แต่ฉันคิดว่านั่นเป็นสิ่งที่ควรพิจารณา

ข้อเสนอทางเลือกข้างต้นยังหลีกเลี่ยงปัญหานี้ หากคุณยังต้องการใช้งานต่อไปfriendคุณสามารถหลีกเลี่ยงปัญหานั้นได้ด้วยการทำให้ผู้ช่วยเป็นคลาสที่ซ้อนกันแบบไพรเวต

class PredicateList
{
    ...

    // Declare nested class.
    class Helper;

    // Make it a friend.
    friend class Helper;

public:
    ...
};

// In source file:
class PredicateList::Helper
{
    ...
};

นี่เป็นรูปแบบการออกแบบที่รู้จักกันดีว่ามีชื่อหรือไม่

ไม่มีความรู้ของฉัน ฉันสงสัยว่าจะมีอย่างใดอย่างหนึ่งเนื่องจากเป็นการเข้าถึงข้อมูลและรูปแบบการใช้งานจริง ๆ

"ผู้ช่วยนรก"

ฉันได้รับการร้องขอให้ชี้แจงเพิ่มเติมเกี่ยวกับจุดที่ว่าฉันประจบประแจงบางครั้งเมื่อฉันเห็นการใช้งานด้วยรหัส "ตัวช่วย" มากมายและนั่นอาจขัดแย้งกับบางอย่างเล็กน้อย จากการใช้ชั้นเรียนของเพื่อนร่วมงานเพื่อค้นหา "ผู้ช่วยเหลือ" จำนวนมาก :-D และฉันไม่ได้เป็นคนเดียวในทีมที่เกาหัวของฉันพยายามที่จะคิดออกว่าผู้ช่วยเหลือเหล่านี้ควรทำอะไรกันแน่ ฉันไม่ต้องการหลุดพ้นจากความดันทุรังเช่น"คุณไม่ควรใช้ผู้ช่วย"แต่ฉันจะแนะนำเล็กน้อยว่ามันอาจช่วยคิดเกี่ยวกับวิธีการใช้สิ่งต่าง ๆ ที่ขาดหายไปเมื่อใช้งานจริง

ไม่ได้เป็นสมาชิกฟังก์ชั่นส่วนตัวของผู้ช่วยฟังก์ชั่นตามคำนิยาม?

และใช่ฉันรวมถึงวิธีการส่วนตัว ถ้าฉันเห็นชั้นเรียนที่มีอินเทอร์เฟซสาธารณะตรงไปตรงมา แต่ชอบวิธีการส่วนตัวแบบไม่มีที่สิ้นสุดซึ่งค่อนข้างชัดเจนในวัตถุประสงค์เช่นfind_implหรือfind_detailหรือfind_helperจากนั้นฉันก็ประจบประแจงในลักษณะที่คล้ายกัน

สิ่งที่ฉันแนะนำว่าเป็นอีกทางเลือกหนึ่งคือฟังก์ชั่นที่ไม่เป็นสมาชิกที่ไม่ใช่สมาชิกที่มีการเชื่อมโยงภายใน (ประกาศstaticหรือภายในเนมสเปซที่ไม่ระบุชื่อ) เพื่อช่วยให้ชั้นเรียนของคุณมีจุดประสงค์ทั่วไป และฉันสามารถอ้างอิง Herb Sutter จาก C ++ 'มาตรฐานการเข้ารหัส' ได้ที่นี่เพราะเหตุใดจึงเป็นที่นิยมในมุมมอง SE ทั่วไป:

หลีกเลี่ยงค่าธรรมเนียมการเป็นสมาชิก: หากเป็นไปได้ควรทำฟังก์ชั่นที่ไม่ใช่สมาชิก nonfriends [... ] ฟังก์ชั่นที่ไม่ใช่สมาชิกที่ไม่เป็นเพื่อนปรับปรุงการห่อหุ้มโดยลดการพึ่งพา: ร่างกายของฟังก์ชั่นไม่สามารถขึ้นอยู่กับสมาชิกที่ไม่เปิดเผยต่อสาธารณะของชั้นเรียน (ดูหัวข้อ 11) พวกมันยังแยกชั้นหินใหญ่ออกเป็นชั้น ๆ เพื่อปลดปล่อยการทำงานที่แยกกันได้ช่วยลดการมีเพศสัมพันธ์ (ดูข้อ 33)

คุณยังสามารถเข้าใจ "ค่าธรรมเนียมสมาชิก" ที่เขาพูดถึงในระดับหนึ่งในแง่ของหลักการพื้นฐานของการ จำกัด ขอบเขตตัวแปรให้แคบลง ถ้าคุณจินตนาการว่าเป็นตัวอย่างที่ดีที่สุดเป็นวัตถุพระเจ้าที่มีรหัสทั้งหมดที่จำเป็นสำหรับโปรแกรมทั้งหมดของคุณเพื่อเรียกใช้แล้วโปรดปราน "ผู้ช่วยเหลือ" ของการจัดเรียงนี้ (ฟังก์ชั่นไม่ว่าจะเป็นฟังก์ชั่นสมาชิกหรือเพื่อน) ซึ่งสามารถเข้าถึงภายในทั้งหมด ไพร่พล) ของคลาสทำให้ตัวแปรเหล่านั้นมีปัญหาไม่น้อยไปกว่าตัวแปรทั่วโลก คุณมีปัญหาทั้งหมดในการจัดการสถานะอย่างถูกต้องและจัดการเรื่องความปลอดภัยและรักษาค่าคงที่ที่คุณจะได้รับจากตัวแปรทั่วโลกในตัวอย่างสุดขีดนี้ และแน่นอนว่าตัวอย่างจริงส่วนใหญ่ไม่ได้หวังว่าจะอยู่ใกล้กับจุดสุดยอดนี้ แต่การซ่อนข้อมูลมีประโยชน์เพียงเพราะมัน จำกัด ขอบเขตของข้อมูลที่ถูกเข้าถึง

ตอนนี้ซัทเทอร์ให้คำอธิบายที่ดีอยู่แล้วที่นี่ แต่ฉันยังจะเพิ่มเติมต่อไปว่า decoupling มีแนวโน้มที่จะส่งเสริมเช่นการปรับปรุงทางจิตวิทยา (อย่างน้อยถ้าสมองของคุณทำงานเหมือนของฉัน) ในแง่ของวิธีการออกแบบฟังก์ชั่น เมื่อคุณเริ่มออกแบบฟังก์ชั่นที่ไม่สามารถเข้าถึงทุกสิ่งในชั้นเรียนยกเว้นเฉพาะพารามิเตอร์ที่เกี่ยวข้องที่คุณส่งผ่านหรือถ้าคุณส่งตัวอย่างของคลาสเป็นพารามิเตอร์สมาชิกสาธารณะเท่านั้นก็มีแนวโน้มที่จะส่งเสริมแนวคิดการออกแบบที่โปรดปราน ฟังก์ชั่นที่มีจุดประสงค์ที่ชัดเจนกว่า decoupling และส่งเสริมการห่อหุ้มที่ดีขึ้นกว่าสิ่งที่คุณอาจถูกล่อลวงให้ออกแบบถ้าคุณเข้าถึงทุกอย่างได้

ถ้าเรากลับไปที่สุดขั้วแล้วโค้ดเบสที่เต็มไปด้วยตัวแปรทั่วโลกไม่ได้ดึงดูดนักพัฒนาให้ออกแบบฟังก์ชั่นในลักษณะที่ชัดเจนและมีจุดประสงค์ทั่วไป ยิ่งคุณเข้าถึงข้อมูลในฟังก์ชันได้เร็วเท่าไรมนุษย์ของเราจำนวนมากต้องเผชิญกับการล่อลวงเพื่อทำให้เสื่อมและลดความชัดเจนในการเข้าถึงข้อมูลพิเศษทั้งหมดที่เรามีแทนที่จะยอมรับพารามิเตอร์ที่เฉพาะเจาะจงและเกี่ยวข้องกับฟังก์ชันนั้นมากขึ้น เพื่อ จำกัด การเข้าถึงของรัฐและขยายการบังคับใช้และปรับปรุงความชัดเจนของความตั้งใจ ที่ใช้ (แม้ว่าโดยทั่วไปจะมีระดับที่น้อยกว่า) กับฟังก์ชั่นสมาชิกหรือเพื่อน


1
ขอบคุณสำหรับการเข้า! ฉันไม่เข้าใจว่าคุณมาจากส่วนนี้อย่างไร: "บางครั้งฉันก็ประจบประแจงเล็กน้อยเมื่อฉันเห็น" ผู้ช่วยเหลือ "ในรหัส" - ไม่ได้เป็นสมาชิกฟังก์ชั่นส่วนตัวของผู้ช่วยฟังก์ชั่นตามนิยาม? ดูเหมือนว่าจะมีปัญหากับฟังก์ชั่นสมาชิกส่วนตัวโดยทั่วไป
Robert Fraser

1
อาชั้นเรียนไม่จำเป็นต้องมี "เพื่อน" เลยทำอย่างนั้นเพื่อหลีกเลี่ยงคำหลัก "เพื่อน" โดยสิ้นเชิง
Robert Fraser

"ไม่ใช่สมาชิกฟังก์ชั่นส่วนตัวของผู้ช่วยฟังก์ชั่นตามคำจำกัดความดูเหมือนจะมีปัญหากับฟังก์ชั่นสมาชิกส่วนตัวโดยทั่วไป" มันไม่ใช่สิ่งที่ยิ่งใหญ่ที่สุด ฉันเคยคิดว่ามันเป็นความจำเป็นในทางปฏิบัติที่สำหรับการดำเนินการในชั้นเรียนที่ไม่สำคัญคุณอาจมีฟังก์ชั่นส่วนตัวจำนวนมากหรือผู้ช่วยเหลือที่สามารถเข้าถึงสมาชิกชั้นเรียนทั้งหมดได้ในครั้งเดียว แต่ฉันดูที่สไตล์ของผู้ยิ่งใหญ่บางคนเช่น Linus Torvalds, John Carmack และแม้ว่ารหัสก่อนหน้าใน C เมื่อเขาใช้รหัสเทียบเท่าวัตถุของแบบอะนาล็อกเขาก็จัดการโดยไม่ใช้รหัสร่วมกับ Carmack
Dragon Energy

และโดยธรรมชาติฉันคิดว่าผู้ช่วยในไฟล์ต้นฉบับนั้นดีกว่าส่วนหัวขนาดใหญ่ที่มีส่วนหัวภายนอกมากกว่าที่จำเป็นเพราะใช้ฟังก์ชันส่วนตัวจำนวนมากเพื่อช่วยในการปรับใช้คลาส แต่หลังจากเรียนรู้สไตล์ของคนข้างบนและคนอื่น ๆ ฉันก็รู้ว่ามันมักจะเป็นไปได้ที่จะเขียนฟังก์ชั่นที่ค่อนข้างกว้างกว่าประเภทที่ต้องการการเข้าถึงสมาชิกภายในของชั้นเรียนทั้งหมดเพียงแค่ใช้คลาสเดียวและคิดล่วงหน้า เพื่อตั้งชื่อฟังก์ชั่นให้ดีและส่งต่อให้สมาชิกที่ต้องการทำงานบ่อยครั้งจะทำให้ประหยัดเวลามากขึ้น [... ]
Dragon Energy

[... ] มากกว่าที่เป็นไปได้ทำให้การใช้งานโดยรวมชัดเจนขึ้นซึ่งง่ายต่อการจัดการในภายหลัง มันเหมือนกับว่าแทนที่จะเขียน "ผู้ช่วยกริยา" สำหรับ "การจับคู่แบบเต็ม" ซึ่งเข้าถึงทุกอย่างในตัวคุณPredicateListบ่อยครั้งที่มันอาจเป็นไปได้เพียงแค่ส่งสมาชิกหรือสองคนจากรายการกริยาไปยังฟังก์ชันทั่วไปที่ไม่ต้องการ สมาชิกส่วนบุคคลทุกคนPredicateListและมักจะมีแนวโน้มที่จะให้ชื่อที่ชัดเจนและมีความชัดเจนมากขึ้นรวมถึงวัตถุประสงค์ในการทำงานภายในเช่นเดียวกับโอกาสที่มากขึ้นสำหรับ "การใช้รหัสเข้าใจย้อนกลับ"
Dragon Energy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.