ฉันกำลังฝึกฝน OOP กับสถาปัตยกรรมนี้หรือไม่?


23

ฉันมีเว็บแอพพลิเคชั่น ฉันไม่เชื่อว่าเทคโนโลยีเป็นสิ่งสำคัญ โครงสร้างเป็นแอปพลิเคชันระดับ N ซึ่งแสดงในภาพทางด้านซ้าย มี 3 ชั้น

UI (รูปแบบ MVC), Business Logic Layer (BLL) และ Data Access Layer (DAL)

ปัญหาที่ฉันมีคือ BLL ของฉันมีขนาดใหญ่มากเนื่องจากมีตรรกะและเส้นทางผ่านการเรียกแอปพลิเคชันกิจกรรม

โฟลว์ทั่วไปผ่านแอ็พพลิเคชันอาจเป็น:

มีเหตุการณ์เกิดขึ้นใน UI ข้ามไปที่เมธอดใน BLL ดำเนินการกับลอจิก (อาจอยู่ในหลายส่วนของ BLL) ในที่สุดถึง DAL กลับไปที่ BLL (ซึ่งเป็นไปได้ว่ามีตรรกะมากกว่า) จากนั้นส่งคืนค่าบางค่าไปยัง UI

BLL ในตัวอย่างนี้ยุ่งมากและฉันคิดว่าจะแยกออก ฉันมีตรรกะและวัตถุที่รวมกันซึ่งฉันไม่ชอบ

ป้อนคำอธิบายรูปภาพที่นี่

เวอร์ชั่นด้านขวาคือความพยายามของฉัน

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

การไหลอาจเป็น:

แม้จะถูกกระตุ้นจาก UI และส่งผ่านข้อมูลบางอย่างไปยังตัวควบคุมเลเยอร์ UI (MVC) นี่แปลข้อมูลดิบและแปลงเป็นโมเดล poco จากนั้นโมเดล poco จะถูกส่งผ่านไปยังเลเยอร์ลอจิก (ซึ่งก็คือ BLL) และในที่สุดก็ไปที่เลเยอร์ข้อความค้นหาคำสั่ง ชั้นแบบสอบถามคำสั่งแปลง POCO เป็นวัตถุฐานข้อมูล (ซึ่งเกือบจะเหมือนกัน แต่หนึ่งถูกออกแบบมาสำหรับการติดตาอีกคนสำหรับปลายด้านหน้า) รายการถูกเก็บไว้และวัตถุฐานข้อมูลจะถูกส่งกลับไปยังเลเยอร์คำสั่ง จากนั้นจะถูกแปลงเป็น POCO ซึ่งจะกลับไปที่เลเยอร์ลอจิกซึ่งอาจประมวลผลต่อไปและในที่สุดก็กลับไปที่ UI

ตรรกะและอินเตอร์เฟสที่ใช้ร่วมกันเป็นที่ที่เราอาจมีข้อมูลถาวรเช่น MaxNumberOf_X และ TotalAllowed_X และอินเทอร์เฟซทั้งหมด

ทั้งตรรกะ / อินเตอร์เฟสที่แบ่งใช้และ DAL เป็น "ฐาน" ของสถาปัตยกรรม สิ่งเหล่านี้ไม่รู้อะไรเลยเกี่ยวกับโลกภายนอก

ทุกอย่างรู้เกี่ยวกับ poco นอกเหนือจากตรรกะ / อินเตอร์เฟสและ DAL ที่ใช้ร่วมกัน

การไหลยังคงคล้ายกับตัวอย่างแรก แต่ทำให้แต่ละเลเยอร์รับผิดชอบมากกว่า 1 อย่าง (ไม่ว่าจะเป็นสถานะการไหลหรือสิ่งอื่นใด) ... แต่ฉันจะทำลาย OOP ด้วยวิธีการนี้หรือไม่?

ตัวอย่างการสาธิตลอจิกและ Poco อาจเป็น:

public class LogicClass
{
    private ICommandQueryObject cmdQuery;
    public PocoA Method1(PocoB pocoB) 
    { 
        return cmdQuery.Save(pocoB); 
    }

    /*This has no state objects, only ways to communicate with other 
    layers such as the cmdQuery. Everything else is just function 
    calls to allow flow via the program */
    public PocoA Method2(PocoB pocoB) 
    {         
        pocoB.UpdateState("world"); 
        return Method1(pocoB);
    }

}

public struct PocoX
{
     public string DataA {get;set;}
     public int DataB {get;set;}
     public int DataC {get;set;}

    /*This simply returns something that is part of this class. 
     Everything is self-contained to this class. It doesn't call 
     trying to directly communicate with databases etc*/
     public int GetValue()
     {

         return DataB * DataC; 
     }

     /*This simply sets something that is part of this class. 
     Everything is self-contained to this class. 
     It doesn't call trying to directly communicate with databases etc*/
     public void UpdateState(string input)
     {        
         DataA += input;  
     }
}

ฉันไม่เห็นอะไรผิดปกติกับสถาปัตยกรรมของคุณอย่างที่คุณอธิบายไว้ในขณะนี้
Robert Harvey

19
รายละเอียดการทำงานมีไม่เพียงพอในตัวอย่างโค้ดของคุณเพื่อให้ข้อมูลเชิงลึกเพิ่มเติม ตัวอย่างของ Foobar ไม่ค่อยมีภาพประกอบเพียงพอ
Robert Harvey

1
ส่งไปยังการพิจารณาของคุณ: Baruco 2012: การทำลายโครงสร้างโดย Gary Bernhardt
Theraot

4
เราสามารถหาชื่อที่ดีกว่าสำหรับคำถามนี้เพื่อให้สามารถพบได้ทางออนไลน์ได้ง่ายขึ้น
Soner Gönül

1
เพียงเพื่อจะอวดรู้: ชั้นและชั้นไม่เหมือนกัน "ระดับ" พูดถึงการปรับใช้ซึ่งเป็น "เลเยอร์" เกี่ยวกับตรรกะ ชั้นข้อมูลของคุณจะถูกปรับใช้กับทั้งฝั่งเซิร์ฟเวอร์ - รหัส - และฐานข้อมูล - ระดับ เลเยอร์ UI ของคุณจะถูกนำไปใช้กับทั้งเว็บไคลเอนต์และเซิร์ฟเวอร์ด้านรหัสระดับ สถาปัตยกรรมที่คุณแสดงเป็นสถาปัตยกรรม 3 ชั้น ระดับของคุณคือ "เว็บไคลเอ็นต์", "รหัสฝั่งเซิร์ฟเวอร์" และ "ฐานข้อมูล"
Laurent LA RIZZA

คำตอบ:


54

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

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

แน่นอนว่ามีข้อยกเว้นอยู่เสมอ แต่การออกแบบนี้เป็นการละเมิดกฎเหล่านี้

อีกครั้งฉันต้องการที่จะเน้น "ละเมิด OOP"! = "ผิด" ดังนั้นนี่ไม่จำเป็นต้องเป็นการตัดสินคุณค่า ทุกอย่างขึ้นอยู่กับข้อ จำกัด ด้านสถาปัตยกรรมความสามารถในการบำรุงรักษากรณีความต้องการ ฯลฯ


9
มี upvote นี่เป็นคำตอบที่ดีถ้าฉันเขียนของตัวเองฉันจะคัดลอกและวาง แต่ถ้าคุณพบว่าตัวเองไม่ได้เขียนรหัส OOP บางทีคุณควรพิจารณาภาษาที่ไม่ใช่ OOP มาพร้อมกับค่าใช้จ่ายพิเศษมากมายที่คุณสามารถทำได้โดยไม่ต้องใช้ถ้าคุณไม่ได้ใช้มัน
TheCatWhisperer

2
@TheCatWhisperer: สถาปัตยกรรมองค์กรสมัยใหม่ไม่ได้ทิ้ง OOP ทั้งหมดเพียงแค่เลือกสรร (เช่นสำหรับ DTO)
Robert Harvey

@RobertHarvey เห็นด้วยฉันหมายความว่าถ้าคุณไม่ได้ใช้ OOP แทบจะทุกที่ในการออกแบบของคุณ
TheCatWhisperer

@ TheCatWhisperer ข้อดีหลายประการใน oop เช่น c # ไม่จำเป็นต้องอยู่ในส่วนของภาษา แต่ในการสนับสนุนที่มีให้เช่นห้องสมุด, สตูดิโอภาพ, การจัดการหน่วยความจำเป็นต้น

@ Orangeandlemons ฉันแน่ใจว่ามีภาษาอื่น ๆ อีกมากที่สนับสนุนที่ดีออกมี ...
TheCatWhisperer

31

หนึ่งในหลักการสำคัญของการเขียนโปรแกรมฟังก์ชั่นคือฟังก์ชั่นที่บริสุทธิ์

หนึ่งในหลักการสำคัญของการเขียนโปรแกรมเชิงวัตถุคือการรวมฟังก์ชั่นเข้ากับข้อมูลที่พวกเขาทำ

หลักการสำคัญทั้งสองนี้จะหายไปเมื่อแอปพลิเคชันของคุณต้องสื่อสารกับโลกภายนอก แน่นอนคุณสามารถเป็นจริงได้กับอุดมคติเหล่านี้ในพื้นที่ที่จัดทำขึ้นเป็นพิเศษในระบบของคุณ ไม่ใช่ทุกบรรทัดของรหัสของคุณจะต้องเป็นไปตามอุดมคติเหล่านี้ แต่หากไม่มีบรรทัดของรหัสของคุณตรงตามอุดมคติเหล่านี้คุณจะไม่สามารถเรียกร้องได้ว่าใช้ OOP หรือ FP

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

ไม่ใช่ว่าคุณต้องทำเช่นนั้น OOP ไม่ใช่ทุกสิ่งสำหรับทุกคน มันเป็นสิ่งที่มันเป็น. อย่าอ้างสิทธิ์บางอย่างที่ตามมา OOP เมื่อมันไม่เกิดขึ้นหรือคุณกำลังสับสนคนที่พยายามรักษารหัสของคุณ

POCO ของคุณดูเหมือนจะมีตรรกะทางธุรกิจในพวกเขาได้ดีดังนั้นฉันจะไม่กังวลมากเกินไปเกี่ยวกับการเป็นโรคโลหิตจาง สิ่งที่ทำให้ฉันกังวลคือพวกเขาดูเหมือนจะไม่แน่นอนมาก โปรดจำไว้ว่าผู้ได้รับและผู้ตั้งค่าไม่ได้ให้การห่อหุ้มอย่างแท้จริง ถ้า POCO ของคุณมุ่งหน้าไปยังขอบเขตนั้นก็โอเค เพียงแค่เข้าใจว่าสิ่งนี้ไม่ได้ให้ประโยชน์เต็มที่กับวัตถุ OOP ที่ถูกห่อหุ้มจริงๆ บางคนเรียกสิ่งนี้ว่า Data Transfer Object หรือ DTO

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

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

ในที่สุดบางสิ่งบางอย่างกำลังจะวิ่งเข้าไปในขอบเขตอื่นและทั้งหมดนี้ก็สลายไปอีกครั้ง ไม่เป็นไร. หมุน DTO เพิ่มขึ้นและโยนข้ามกำแพง

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


5
" getters และ setters ไม่มีการห่อหุ้มตัวจริง " - ใช่!
Boris the Spider

3
@BoristheSpider - getters และ setters ให้การห่อหุ้มอย่างแน่นอนพวกเขาเพียงแค่ไม่พอดีกับคำจำกัดความแคบของการห่อหุ้ม
Davor Ždralo

4
@ DavorŽdralo: บางครั้งพวกเขาก็มีประโยชน์ในฐานะที่เป็นวิธีแก้ปัญหา แต่โดยธรรมชาติของพวกเขา getters และ setters ทำลาย encapsulation การหาวิธีในการรับและตั้งค่าตัวแปรภายในคือสิ่งที่ตรงกันข้ามกับการรับผิดชอบต่อสถานะของคุณเองและการกระทำนั้น
cHao

5
@cHao - คุณไม่เข้าใจสิ่งที่ทะเยอทะยาน มันไม่ได้หมายความว่าวิธีการที่ส่งกลับค่าของคุณสมบัติวัตถุ มันเป็นการใช้งานทั่วไป แต่สามารถส่งคืนค่าจากฐานข้อมูลร้องขอผ่าน http คำนวณได้ทันที อย่างที่ฉันพูดไปแล้วผู้ทะเยอทะยานและเซทเทอร์สทำลายการห่อหุ้มเฉพาะเมื่อผู้คนใช้คำจำกัดความของตัวเอง
Davor Ždralo

4
@cHao - การห่อหุ้มหมายความว่าคุณกำลังซ่อนการใช้งาน นั่นคือสิ่งที่ได้รับการห่อหุ้ม หากคุณมี "getSurfaceArea ()" getter ในคลาส Square คุณไม่ทราบว่าพื้นที่พื้นผิวเป็นเขตข้อมูลหรือไม่หากคำนวณจากการบิน (กลับสูง * กว้าง) หรือวิธีที่สามเพื่อให้คุณสามารถเปลี่ยนการใช้งานภายใน เมื่อใดก็ตามที่คุณต้องการเพราะมันถูกห่อหุ้ม
Davor Ždralo

1

ถ้าฉันอ่านคำอธิบายของคุณอย่างถูกต้องวัตถุของคุณมีลักษณะเช่นนี้: (หากินโดยไม่มีบริบท)

public class LogicClass
{
    private ICommandQueryObject cmdQuery;
    public PocoA Method(PocoB pocoB) { ... }
}

public class PocoX
{
     public string DataA {get;set;}
     public int DataB {get;set;}
     ... etc
}

ในคลาส Poco ของคุณมีเพียงข้อมูลและคลาสลอจิกของคุณมีวิธีการที่กระทำกับข้อมูลนั้น ใช่คุณได้ทำลายหลักการของ "Classic OOP"

อีกครั้งมันยากที่จะบอกจากคำอธิบายทั่วไปของคุณ แต่ฉันอยากรู้ว่าสิ่งที่คุณเขียนอาจถูกจัดประเภทเป็น Anemic Domain Model

ฉันไม่คิดว่านี่เป็นวิธีการที่ไม่ดีเป็นพิเศษหรือถ้าคุณพิจารณา Poco ของคุณเนื่องจากโครงสร้างไม่ทำลาย OOP ในแง่ที่เฉพาะเจาะจงมากขึ้น ที่ Objects ของคุณตอนนี้เป็น LogicClasses แน่นอนถ้าคุณทำให้ Pocos ของคุณไม่เปลี่ยนรูปแบบการออกแบบก็ถือว่าใช้งานได้ดี

อย่างไรก็ตามเมื่อคุณอ้างอิงลอจิกที่ใช้ร่วมกัน Pocos ที่แทบจะไม่เหมือนเดิมและสถิตศาสตร์ฉันเริ่มกังวลกับรายละเอียดการออกแบบของคุณ


ฉันได้เพิ่มไว้ในโพสต์ของฉันคัดลอกตัวอย่างของคุณเป็นหลัก ขออภัย ti ยังไม่ชัดเจนที่จะเริ่มต้นด้วย
MyDaftQuestions

1
สิ่งที่ฉันหมายถึงคือถ้าคุณบอกเราว่าแอปพลิเคชันทำอะไรได้ง่ายกว่าที่จะเขียนตัวอย่าง แทนที่จะเป็น LogicClass คุณสามารถมี PaymentProvider หรืออะไรก็ได้
Ewan

1

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

รหัสการเข้าถึง / อัปเดตไม่ได้รับการรวบรวมโดยทั่วไปคุณจึงสามารถใช้งานซ้ำได้ทุกที่

ในทางตรงกันข้ามวัตถุข้อมูลเหล่านั้นมีประโยชน์เช่นการคงอยู่ของฐานข้อมูล ฉันได้ลองวิธีแก้ปัญหาสามข้อแล้ว:

การคัดลอกค่าเข้าและออกไปยังวัตถุ "ของจริง" และการทิ้งวัตถุข้อมูลของคุณนั้นน่าเบื่อ (แต่อาจเป็นทางออกที่ถูกต้องหากคุณต้องการทำเช่นนั้น)

การเพิ่มวิธีการ wrangling ข้อมูลไปยังวัตถุข้อมูลสามารถทำงานได้ แต่มันสามารถทำให้วัตถุข้อมูลยุ่งขนาดใหญ่ที่ทำมากกว่าหนึ่งสิ่ง นอกจากนี้ยังสามารถทำให้การห่อหุ้มยากขึ้นเนื่องจากกลไกการคงอยู่หลายอย่างต้องการผู้เข้าถึงสาธารณะ ... ฉันไม่ได้รักเมื่อฉันทำมัน แต่มันเป็นทางออกที่ถูกต้อง

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

ข้อดีอีกอย่างคือคุณสามารถมั่นใจได้ว่าคลาสข้อมูลของคุณอยู่ในสถานะที่ถูกต้องเสมอ นี่คือตัวอย่าง psuedocode อย่างรวดเร็ว:

// Data Class
Class User {
    String name;
    Date birthday;
}

Class UserHolder {
    final private User myUser // Cannot be null or invalid

    // Quickly wrap an object after getting it from the DB
    public UserHolder(User me)
    {
        if(me == null ||me.name == null || me.age < 0)
            throw Exception
        myUser=me
    }

    // Create a new instance in code
    public UserHolder(String name, Date birthday) {
        User me=new User()
        me.name=name
        me.birthday=birthday        
        this(me)
    }
    // Methods access attributes, they try not to return them directly.
    public boolean canDrink(State state) {
        return myUser.birthday.year < Date.yearsAgo(state.drinkingAge) 
    }
}

โปรดทราบว่าคุณไม่ได้มีการตรวจสอบอายุแพร่กระจายไปทั่วรหัสของคุณในพื้นที่ที่แตกต่างกันและว่าคุณไม่ได้ต้องการที่จะใช้มันเพราะคุณไม่สามารถแม้แต่จะคิดออกว่าวันเกิดคืออะไร (ยกเว้นกรณีที่คุณต้องการสิ่งอื่นใน ในกรณีนี้คุณสามารถเพิ่มได้)

ฉันมักจะไม่เพียงขยายวัตถุข้อมูลเพราะคุณสูญเสียการห่อหุ้มและการรับประกันความปลอดภัย ณ จุดนั้นคุณอาจเพิ่มวิธีการในคลาสข้อมูล

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


1

อย่าเปลี่ยนรหัสของคุณเพราะคุณคิดหรือมีคนบอกคุณว่าไม่ใช่สิ่งนี้หรือไม่ เปลี่ยนรหัสของคุณหากมันทำให้คุณมีปัญหาและคุณสามารถหาวิธีหลีกเลี่ยงปัญหาเหล่านี้ได้โดยไม่ต้องสร้างรหัสอื่น

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


0

หมวดหมู่ "OOP" มีขนาดใหญ่และเป็นนามธรรมมากกว่าสิ่งที่คุณอธิบาย มันไม่สนใจทั้งหมดนี้ มันใส่ใจเกี่ยวกับความรับผิดชอบที่ชัดเจนการเชื่อมโยงการมีเพศสัมพันธ์ ดังนั้นในระดับที่คุณถามมันไม่สมเหตุสมผลเลยที่จะถามเกี่ยวกับ "การฝึกฝน OOPS"

ที่กล่าวถึงตัวอย่างของคุณ:

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

  • รุ่น - มีข้อมูลทางธุรกิจ + ตรรกะ
    • ชั้นข้อมูลเป็นรายละเอียดการใช้งานของโมเดล
  • ดู - รหัส UI, เทมเพลต HTML, CSS ฯลฯ
    • รวมถึงฝั่งไคลเอ็นต์เช่น JavaScript หรือไลบรารี่สำหรับเว็บแอปพลิเคชั่น "one-page" เป็นต้น
  • ควบคุม - กาวด้านเซิร์ฟเวอร์ระหว่างส่วนอื่น ๆ ทั้งหมด
  • (มีส่วนขยายเช่น ViewModel, Batch เป็นต้นซึ่งฉันจะไม่เข้าไปที่นี่)

มีบางคนเหลือเกินที่สำคัญสมมติฐานฐานที่นี่:

  • คลาสโมเดล / วัตถุไม่เคยมีความรู้ใด ๆเลยเกี่ยวกับส่วนอื่น ๆ (มุมมองการควบคุม ... ) มันไม่เคยเรียกพวกเขามันไม่คิดว่าจะถูกเรียกโดยพวกเขามันไม่ได้รับคุณสมบัติ / พารามิเตอร์ sesssion หรือสิ่งอื่นใดในบรรทัดนี้ เป็นคนเดียวอย่างสมบูรณ์ ในภาษาที่รองรับสิ่งนี้ (เช่น Ruby) คุณสามารถใช้บรรทัดคำสั่งด้วยตนเองสร้างอินสแตนซ์ของคลาสโมเดลทำงานกับพวกมันไปยังเนื้อหาในใจของคุณและสามารถทำทุกอย่างที่พวกเขาทำโดยไม่มีอินสแตนซ์ควบคุมหรือมุมมอง ไม่มีความรู้เกี่ยวกับเซสชันผู้ใช้ ฯลฯ ที่สำคัญที่สุด
  • ไม่มีอะไรสัมผัสกับชั้นข้อมูลยกเว้นผ่านแบบจำลอง
  • มุมมองมีเพียงสัมผัสเบา ๆ บนโมเดล (แสดงสิ่งของ ฯลฯ ) และไม่มีอะไรอื่น (โปรดทราบว่าส่วนขยายที่ดีคือ "ViewModel" ซึ่งเป็นคลาสพิเศษที่ทำการประมวลผลจำนวนมากสำหรับการเรนเดอร์ข้อมูลในลักษณะที่ซับซ้อนซึ่งไม่เหมาะกับทั้ง Model หรือ View - นี่เป็นตัวเลือกที่ดีสำหรับการลบ / หลีกเลี่ยงการขยายตัว รุ่นบริสุทธิ์)
  • การควบคุมนั้นมีน้ำหนักเบาที่สุดเท่าที่จะเป็นไปได้ แต่มีหน้าที่รวบรวมผู้เล่นอื่นทั้งหมดเข้าด้วยกันและถ่ายโอนสิ่งต่าง ๆ รอบตัว (เช่นแยกรายการผู้ใช้จากแบบฟอร์มและส่งต่อไปยังแบบจำลองส่งต่อข้อยกเว้นจากตรรกะทางธุรกิจ ข้อความแสดงข้อผิดพลาดสำหรับผู้ใช้ ฯลฯ ) สำหรับ Web / HTTP / REST API เป็นต้นการอนุญาตความปลอดภัยการจัดการเซสชันการจัดการผู้ใช้ ฯลฯ จะเกิดขึ้นที่นี่ (และเฉพาะที่นี่)

สำคัญ: UI เป็นส่วนหนึ่งของ MVC ไม่ใช่รอบอื่น ๆ (เหมือนในแผนภาพของคุณ) หากคุณยอมรับว่ารูปแบบไขมันนั้นดีจริง ๆ - หากว่าพวกเขาไม่มีสิ่งที่ควรทำ

โปรดทราบว่า "รุ่นไขมัน" หมายความว่าตรรกะทางธุรกิจทั้งหมดอยู่ในหมวดหมู่รุ่น (แพคเกจโมดูลสิ่งที่ชื่อในภาษาที่คุณเลือกคือ) แต่ละคลาสควรมีโครงสร้างของ OOP อย่างชัดเจนตามแนวทางการเข้ารหัสที่คุณให้ (เช่นบรรทัดสูงสุดของรหัสต่อคลาสหรือต่อวิธี ฯลฯ )

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

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.