ในช่วงหลายเดือนที่ผ่านมาฉันขอคนที่นี่ทางทิศตะวันออกเฉียงใต้และในเว็บไซต์อื่น ๆ เสนอคำวิจารณ์ที่สร้างสรรค์เกี่ยวกับรหัสของฉัน มีสิ่งหนึ่งที่โผล่ออกมาเกือบทุกครั้งและฉันก็ยังไม่เห็นด้วยกับคำแนะนำนั้น : P ฉันต้องการที่จะพูดคุยที่นี่และบางทีสิ่งต่าง ๆ จะชัดเจนสำหรับฉัน
มันเกี่ยวกับหลักการความรับผิดชอบเดี่ยว (SRP) โดยทั่วไปฉันมีคลาสข้อมูลFont
ที่ไม่เพียง แต่มีฟังก์ชั่นสำหรับจัดการข้อมูล แต่ยังสำหรับการโหลด ฉันบอกว่าทั้งสองควรแยกจากกันฟังก์ชั่นการโหลดควรอยู่ในคลาสของโรงงาน ฉันคิดว่านี่เป็นความผิดพลาดของ SRP ...
ชิ้นส่วนจากคลาสแบบอักษรของฉัน
class Font
{
public:
bool isLoaded() const;
void loadFromFile(const std::string& file);
void loadFromMemory(const void* buffer, std::size_t size);
void free();
void some();
void another();
};
การออกแบบที่แนะนำ
class Font
{
public:
void some();
void another();
};
class FontFactory
{
public:
virtual std::unique_ptr<Font> createFromFile(...) = 0;
virtual std::unique_ptr<Font> createFromMemory(...) = 0;
};
การออกแบบที่แนะนำควรจะเป็นไปตาม SRP แต่ฉันไม่เห็นด้วย - ฉันคิดว่ามันไปไกลเกินไป Font
ชั้นไม่ได้อีกต่อไปแบบพอเพียง (มันจะไร้ประโยชน์โดยไม่ต้องโรงงาน) และFontFactory
ความต้องการที่จะทราบรายละเอียดเกี่ยวกับการดำเนินงานของทรัพยากรที่จะทำอาจจะเป็นเพื่อนหรือ getters Font
สาธารณะซึ่งต่อไปจะเปิดเผยการดำเนินงานของ ผมคิดว่านี่ค่อนข้างกรณีที่มีความรับผิดชอบในการแยกส่วน
นี่คือเหตุผลที่ฉันคิดว่าวิธีการของฉันดีกว่า:
Font
เป็นแบบพอเพียง - การแบบพอเพียงง่ายต่อการเข้าใจและบำรุงรักษา นอกจากนี้คุณสามารถใช้คลาสได้โดยไม่ต้องรวมอะไรไว้ อย่างไรก็ตามหากคุณพบว่าคุณต้องการการจัดการทรัพยากรที่ซับซ้อนมากขึ้น (โรงงาน) คุณสามารถทำสิ่งนั้นได้ง่ายเช่นกัน (ภายหลังฉันจะพูดถึงโรงงานของตัวเองResourceManager<Font>
)เป็นไปตามไลบรารี่มาตรฐาน - ฉันเชื่อว่าประเภทที่ผู้ใช้กำหนดควรพยายามคัดลอกพฤติกรรมของประเภทมาตรฐานในภาษานั้น ๆ ให้มากที่สุด
std::fstream
เป็นตัวเองเพียงพอและจะให้ทำงานที่ชอบและopen
close
การติดตามห้องสมุดมาตรฐานหมายความว่าไม่จำเป็นต้องใช้ความพยายามในการเรียนรู้อีกวิธีหนึ่งในการทำสิ่งต่าง ๆ นอกจากนี้โดยทั่วไปแล้วคณะกรรมการมาตรฐาน C ++ อาจรู้เรื่องการออกแบบมากกว่าใครที่นี่ดังนั้นหากมีข้อสงสัยให้คัดลอกสิ่งที่พวกเขาทำความสามารถในการทดสอบ - มีบางอย่างผิดปกติปัญหานี้จะเกิดขึ้นที่ไหน - เป็นวิธี
Font
จัดการกับข้อมูลหรือวิธีFontFactory
โหลดข้อมูลหรือไม่ คุณไม่รู้หรอก การมีชั้นเรียนแบบพอเพียงช่วยลดปัญหานี้ได้: คุณสามารถทดสอบFont
แยกได้ หากคุณต้องทดสอบโรงงานและคุณรู้ว่าFont
ทำงานได้ดีคุณจะรู้ว่าเมื่อเกิดปัญหาขึ้นต้องอยู่ภายในโรงงานมันเป็นบริบทที่ไม่เชื่อเรื่องพระเจ้า - (นี่จะตัดกับจุดแรกของฉัน)
Font
ทำสิ่งนั้นและไม่ตั้งสมมติฐานว่าคุณจะใช้มันอย่างไร: คุณสามารถใช้มันในแบบที่คุณชอบ การบังคับให้ผู้ใช้ใช้โรงงานเพิ่มการเชื่อมต่อระหว่างคลาส
ฉันก็มีโรงงานเช่นกัน
(เพราะการออกแบบของFont
ช่วยให้ฉันไป.)
หรือมากกว่าผู้จัดการไม่ใช่เพียงแค่โรงงาน ... Font
มีความพอเพียงดังนั้นผู้จัดการไม่จำเป็นต้องรู้วิธีการสร้าง ผู้จัดการแทนทำให้แน่ใจว่าไฟล์หรือบัฟเฟอร์เดียวกันไม่ได้โหลดลงในหน่วยความจำมากกว่าหนึ่งครั้ง คุณสามารถพูดได้ว่าโรงงานสามารถทำเช่นเดียวกัน แต่นั่นจะไม่ทำลาย SRP หรือไม่ โรงงานจะไม่เพียง แต่ต้องสร้างวัตถุ แต่ยังจัดการพวกมันด้วย
template<class T>
class ResourceManager
{
public:
ResourcePtr<T> acquire(const std::string& file);
ResourcePtr<T> acquire(const void* buffer, std::size_t size);
};
นี่คือตัวอย่างของวิธีการใช้งานผู้จัดการ โปรดสังเกตว่ามันถูกใช้โดยทั่วไปเหมือนกับโรงงาน
void test(ResourceManager<Font>* rm)
{
// The same file isn't loaded twice into memory.
// I can still have as many Fonts using that file as I want, though.
ResourcePtr<Font> font1 = rm->acquire("fonts/arial.ttf");
ResourcePtr<Font> font2 = rm->acquire("fonts/arial.ttf");
// Print something with the two fonts...
}
บรรทัดล่าง ...
(มันอยากจะใส่ tl; dr ที่นี่ แต่ฉันคิดไม่ออกเลย: \) เอา
ล่ะคุณมีแล้วฉันทำดีที่สุดเท่าที่จะทำได้ กรุณาโพสต์ข้อโต้แย้งใด ๆ ที่คุณมีและข้อดีที่คุณคิดว่าการออกแบบที่แนะนำมีมากกว่าการออกแบบของฉันเอง โดยพื้นฐานแล้วพยายามแสดงให้ฉันเห็นว่าฉันผิด :)