สถาปัตยกรรมที่สะอาด: โมเดลการดูคืออะไร


13

ในหนังสือของเขาที่ชื่อว่า 'Clean Architecture' ลุงบ๊อบบอกว่าผู้นำเสนอควรใส่ข้อมูลที่ได้รับมาในสิ่งที่เขาเรียกว่า 'ดูแบบจำลอง'

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

นี่เป็นสิ่งเดียวกันกับ 'ViewModel' จากรูปแบบการออกแบบ Model-View-ViewModel (MVVM) หรือเป็น Data Transfer Object (DTO) แบบง่ายหรือไม่?

ถ้าไม่ใช่ DTO แบบง่ายมันเกี่ยวข้องกับมุมมองอย่างไร มุมมองได้รับการปรับปรุงจากความสัมพันธ์ผ่านผู้สังเกตการณ์หรือไม่

ฉันเดาว่ามันเป็นเหมือน ViewModel จาก MVVM เพราะในบทที่ 23 ของหนังสือของเขา Robert Martin กล่าวว่า:

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

นี่ก็หมายความว่ามุมมองนั้นเชื่อมต่อกับ ViewModel แทนการรับฟังก์ชั่นอาร์กิวเมนต์เป็นตัวอย่าง

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

หากไม่ใช่ DTO หรือ ViewModel จาก MVVM โปรดอธิบายอย่างละเอียดว่ามันคืออะไร


ฉันคิดว่าคำตอบคือ "มันขึ้นอยู่กับ" ถ้าเป็นเว็บแอปพลิเคชันโมเดลของมุมมองนั้นจะเป็น DTO เนื่องจากท้ายที่สุดแล้วมันจะได้รับการจัดลำดับเป็นสตริง HTML มิฉะนั้นโมเดลการดูเป็นเพียงวัตถุพิเศษสำหรับการแสดงข้อมูลไปยังมุมมอง
Greg Burghardt

ใน MVVM (WPF, โปรแกรม Winforms) ViewModelเป็นเสื้อคลุมสำหรับController, PresenterและViewModelสถาปัตยกรรมสะอาดลุงบ๊อบ
Fabio

@Greg Burghardt - เมื่อ ViewModel เป็นโครงสร้างข้อมูลเฉพาะมุมมองจะได้รับแจ้งการเปลี่ยนแปลงอย่างไร
Fearnbuster

@Fabio - ถ้าฉันใช้ความหมายของคุณอย่างถูกต้องการพูดของคุณในรูปแบบ MVVM ViewModel นั้นเทียบเท่ากับส่วนประกอบทั้งหมดที่อยู่ในกลุ่มด้านซ้ายสุดของแผนภาพหรือไม่ หากนั่นเป็นความจริงสำหรับสถาปัตยกรรมของลุงบ็อบทำไมเขาถึงแสดงรายการคอนโทรลเลอร์และผู้นำเสนอแยกต่างหาก
Fearnbuster

ฉันคิดว่าเขาแยกอินพุตและเอาท์พุตตัวจัดการกับวัตถุ / คลาสที่แตกต่างกัน ใน MVVM มันอาจจะเป็นController-> ICommandและ->Presenter data-binding mechanism
Fabio

คำตอบ:


17

นี่เป็นสิ่งเดียวกันกับ 'ViewModel' จากรูปแบบการออกแบบ Model-View-ViewModel (MVVM)

Nope

นั่นจะเป็นสิ่งนี้ :

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

ที่มีรอบ ลุงบ๊อบได้รับการอย่างระมัดระวังหลีกเลี่ยงวงจร

แต่คุณมีสิ่งนี้:

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

ซึ่งแน่นอนไม่มีรอบ แต่มันทำให้คุณสงสัยว่ามุมมองรู้เกี่ยวกับการปรับปรุงอย่างไร เราจะไปที่นั้นสักครู่

หรือมันเป็น Data Transfer Object (DTO) ง่าย ๆ ?

วิธีอ้าง Bob จากหน้าก่อนหน้า:

คุณสามารถใช้ structs พื้นฐานหรือวัตถุการถ่ายโอนข้อมูลง่าย ๆ หากคุณต้องการ หรือคุณสามารถบรรจุลงใน hashmap หรือสร้างลงในวัตถุ

สถาปัตยกรรมที่สะอาด p207

ดังนั้นแน่นอนถ้าคุณชอบ

แต่ผมขอสงสัยว่าจริงๆ bugging คุณนี้ :

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

การใช้ UML ในทางที่น่ารักนี้ตรงกันข้ามกับทิศทางของการพึ่งพาซอร์สโค้ดกับทิศทางการไหลของการควบคุม นี่คือคำตอบสำหรับคำถามของคุณ

ในความสัมพันธ์ที่ใช้:

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

การไหลของการควบคุมไปในทิศทางเดียวกันกับการพึ่งพาโค้ดต้นฉบับ

ในความสัมพันธ์ที่นำไปใช้งาน:

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

การไหลของการควบคุมมักจะไปในทิศทางตรงกันข้ามกับการพึ่งพารหัสที่มาไม่

ซึ่งหมายความว่าคุณกำลังดูสิ่งนี้จริงๆ:

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

คุณควรเห็นว่าการควบคุมไม่เคยได้รับจากผู้นำเสนอไปที่มุมมอง

นั่นเป็นอย่างไร มันหมายความว่าอะไร?

หมายความว่ามุมมองมีเธรดของตัวเอง (ซึ่งไม่ใช่สิ่งที่ผิดปกติ) หรือ (ตามที่ @Euphoric points out) การไหลของการควบคุมกำลังเข้ามาในมุมมองจากสิ่งอื่นที่ไม่ใช่ภาพที่นี่

หากเป็นเธรดเดียวกันมุมมองจะรู้ว่าเมื่อใด View-Model พร้อมที่จะอ่าน แต่ถ้าเป็นเช่นนั้นและมุมมองเป็น GUI ก็จะมีเวลาในการทาสีหน้าจอใหม่เมื่อผู้ใช้เลื่อนไปมาระหว่างที่รอ DB

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

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

จากแผนภาพนี้มีเพียงสิ่งเดียวที่ View และ Presenter share คือความรู้เกี่ยวกับ View-Model และมันก็เป็นเพียงโครงสร้างข้อมูล ดังนั้นอย่าคาดหวังว่ามันจะมีพฤติกรรมใด ๆ

อาจดูเป็นไปไม่ได้ แต่สามารถทำงานได้แม้ว่า View-Model นั้นซับซ้อน ฟิลด์ที่อัปเดตเล็ก ๆ น้อย ๆ คือมุมมองทั้งหมดจะต้องสำรวจเพื่อตรวจสอบการเปลี่ยนแปลง

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

นี่เป็นเรื่องสนุกที่ฉันได้อธิบายการควบคุม:

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

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

สิ่งเดียวที่จะเรียนรู้ที่นี่นอกจากนั้นก็คือ Use Case Interactor สามารถเรียกสิ่งต่าง ๆ ตามลำดับที่มันต้องการตราบใดที่มันยังเรียกพรีเซนเตอร์ได้


ขอบคุณมากสำหรับคำตอบฉันได้เห็นคำตอบของคุณสำหรับคำถามอื่น ๆ เกี่ยวกับสถาปัตยกรรมที่สะอาด คุณแนะนำให้มุมมองตรวจสอบการตั้งค่าสถานะอย่างต่อเนื่องตัวอย่างเช่นภายใน View Model เพื่อดูว่ามีการเปลี่ยนแปลงหรือไม่? มุมมองจะต้องแสดงทั้งโมเดลมุมมองใหม่อีกครั้งหรือฉันควรใช้ชุดธงที่ซ้อนกันเพื่อระบุว่าข้อมูลใดมีการเปลี่ยนแปลงหรือไม่
Fearnbuster

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

โอเคขอบคุณมากสำหรับความช่วยเหลือ ถ้า / เมื่อคุณติดตามสถาปัตยกรรมนี้เป็นเทคนิคที่คุณมักจะใช้หรือไม่?
Fearnbuster

1
ฉันคิดว่ามีข้อผิดพลาดใหญ่ที่คำตอบนี้รวมกลุ่มการออกแบบการพึ่งพาและการพึ่งพารันไทม์ ทั้งสองอาจแตกต่างกัน
ร่าเริง

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

2

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

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

รหัสของออเคสตร้าจะง่ายเหมือน

string Request(string request) // returns response
{
    Controller.Run(data);
    Presenter.Run();
    return View.Run();
}

ฉันเชื่อว่าฉันได้ยินมาร์ตินพูดคุยเกี่ยวกับเรื่องนี้ในหนึ่งในการพูดคุยของเขาเกี่ยวกับสถาปัตยกรรมที่สะอาด

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

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

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

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

ในทางตรงกันข้ามViewModelในสถาปัตยกรรมสะอาดเป็นเพียง DTO ธรรมดาโดยไม่มีเหตุผล สิ่งนี้ถูกทำให้ชัดเจนโดย<DS>แท็ก และนี่คือเหตุผลที่orchestratorจำเป็นเพราะViewไม่ทราบว่าเมื่อใดที่จะเรียกใช้มันเป็นตรรกะ

ถ้าฉันจะ "เรียบ" แผนภาพลงในสิ่งที่มันจะมีลักษณะเหมือนในช่วงรันไทม์ก็จะมีลักษณะเช่นนี้:

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

ดังนั้นระหว่างรันไทม์การอ้างอิงอยู่ในทิศทาง "ผิด" แต่ก็ใช้ได้

ฉันแนะนำให้ดูการพูดคุยของเขาเกี่ยวกับ Clean Architectureเพื่อให้เข้าใจเหตุผลของเขาดีขึ้น


"Orchestrator" ของคุณไม่ควรเรียกผู้นำเสนอ ใช้กล่องโต้ตอบการโต้ตอบทำเช่นนั้น
candied_orange

@candied_orange จริงนั่นเป็นข้อผิดพลาด
สุข

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

@Fearnbuster สำหรับคำถามสุดท้ายของคุณใช่ ทิศทางของการพึ่งพามีความสำคัญมากกว่าโครงสร้าง ฉันเชื่อว่า "สถาปัตยกรรมสะอาด", "สถาปัตยกรรมหัวหอม" และ "สถาปัตยกรรมหกเหลี่ยม" เป็นการใช้งานจริงของแนวคิดเดียวกันของ "Keep dependencies in check"
สุข

@Eparhoric สุจริตฉันจะบอกว่านี่เป็นกรณีที่น่าจะเป็นเพราะในภาพที่แตกต่างของหนังสือของเขา (รูปที่ 8.2 บทที่ 8) เขาแสดงให้เห็นถึงสถาปัตยกรรมที่แตกต่างกัน ในแผนภาพนั้นผู้ควบคุมนั้นเป็นคนกลางระหว่างผู้โต้ตอบกับผู้นำเสนอ นอกจากนี้ยังไม่มีขอบเขตผลผลิตสำหรับผู้โต้ตอบ; ดูเหมือนว่าผู้โต้ตอบจะได้รับการร้องขอผ่านทางอินเทอร์เฟซแล้วส่งกลับการตอบสนองผ่านอินเทอร์เฟซเดียวกัน (ฉันคิดว่าสิ่งนี้ทำผ่านฟังก์ชั่นการคืนค่าอย่างง่าย
Fearnbuster
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.