ข้อเสียของเรื่องราวของผู้ใช้แนวตั้ง


9

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

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

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

อะไรคือข้อเสียเพิ่มเติมของการแบ่งเรื่องราวของผู้ใช้ในแนวตั้ง?

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


ฉันไม่เข้าใจว่าจุดสองจุดที่คุณอยู่ในรายการนั้นเป็นข้อเสียอย่างไร คุณบอกว่าอาจจะช้า แต่ก็ไม่เท่ากัน คุณหมายถึงอะไรโดยสถาปัตยกรรมโดยรวมไม่เหมาะ อีกครั้งมันอาจจะพอดีดีกว่า
Dave Hillier

@DaveHillier: มันเป็นประโยคในลักษณะที่มันเป็นข้อเสีย ตัวอย่างเช่นธุรกิจอาจคิดว่าเวลาดำเนินการ "ช้า" เป็นข้อเสีย
c_maker

คุณพยายามที่จะบอกว่าธุรกิจรับรู้ว่าช้าลงหรือไม่?
Dave Hillier

เป็น "ชิ้นส่วนแนวตั้ง" เป็นหลักเหมือนกับสิ่งที่เป็น
Robert Harvey

1
มีบทความที่ดีมากเกี่ยวกับเรื่องราวของผู้ใช้ในแนวนอนและแนวตั้งซึ่งมีรายละเอียดที่ดีเกี่ยวกับข้อดีและข้อเสียของแต่ละเรื่องที่นี่: deltamatrix.com/…
Robert Harvey

คำตอบ:


7

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

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

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

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

ฉันไม่เห็นด้วยกับคำตอบอื่น ๆ ที่วิธีนี้นำมาซึ่งหนี้ทางเทคนิค มันสามารถทำได้ แต่ก็มีวิธีอื่นใด


ฉันจะลองจับคู่เขียนโปรแกรม สิ่งนี้จะช่วยให้ผู้คนได้รับความรู้เกี่ยวกับโดเมนอื่น ๆ ที่พวกเขาต้องการและช่วยในการหลีกเลี่ยงการวางท่อ
user99561

7

ฉันกำลังคิดถึงคำถามที่แน่นอนนี้มาก

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

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

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

ฉันจะสรุปความคิดเห็นของฉันจนถึงการเปรียบเทียบสรุปต่อไปนี้:

ทีมแนวนอน

ข้อดี:

  • ส่งเสริมการแบ่งแยกที่ดีของความกังวลและชั้นที่สองอย่างหลวม ๆ
  • การจัดการการกระจายภาระงานง่ายขึ้นมาก
  • ง่ายสำหรับผู้เชี่ยวชาญด้านเทคนิคในการจัดการ
  • ส่งเสริมการทำงานร่วมกันภายในชั้นเรียนแนวปฏิบัติที่ดีที่สุดความภาคภูมิใจและวัฒนธรรมแห่งความเป็นเลิศ
  • สอดคล้องกับรูปแบบการสื่อสารตามธรรมชาติ / ฉุกเฉิน

ข้อเสีย:

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

ทีมแนวตั้ง / แนวทแยง

ข้อดี:

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

ข้อเสีย:

  • การจัดการการกระจายเวิร์กโหลดที่ยากมากขึ้น
  • เปิดใช้งานการแยกความกังวลที่ไม่ดีและเทียร์คู่แน่น
  • เป็นอุปสรรคต่อความเชี่ยวชาญโดยการลดการสื่อสารภายในองค์กร เป็นการยากที่จะเห็นว่าวัฒนธรรมแห่งความเป็นเลิศสามารถเกิดขึ้นได้จากโครงสร้างนี้โดยไม่ต้องเพิ่มพฤติกรรมแนวนอน / ผู้เชี่ยวชาญ

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

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

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

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


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

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

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

6

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

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

สิ่งนี้เป็นสิ่งที่หลีกเลี่ยงไม่ได้ แต่ไม่ใช่ตัวบล็อก ฉันพยายามต่อสู้ในสองวิธี:

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

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


2
จากการทำงานอย่างอิสระคุณสร้างหนี้ทางเทคนิคได้อย่างไร ดูเหมือนจะไม่จำเป็นเสมอไป
Sklivvz

มันไม่จำเป็นต้องเป็นอย่างนั้น แต่มันจะเพิ่มความน่าจะเป็น ทำซ้ำรหัสเช่น หากบางคำศัพท์ด้านเทคนิคของโดเมนไม่ได้รับการทำให้แข็ง แต่สอง devs อาจเขียนฟังก์ชันการทำงานเดียวกันในสองคลาสแยกกัน เฉพาะที่แตกต่างเป็นที่หนึ่ง dev เรียกมันและอื่นWobbleAdapterWibbleConverter
MetaFight

3
คุณไม่ได้อธิบายว่าทำไมปัญหาเหล่านี้มีแนวโน้มที่จะเกิดขึ้นเมื่อแบ่งงานเป็นเลเยอร์หรือแนวตั้ง และทำไมคุณต้องเขียนแผ่นความร้อนจำนวนมากในการทำซ้ำครั้งแรก เสียงเหมือน YAGNI
Dave Hillier

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

1
และการแบ่งงานเป็นชิ้นตามแนวตั้งหมายความว่าแต่ละเรื่องราวมีจำนวนเลเยอร์มากกว่า นี่เป็นการเพิ่มโอกาสของนักพัฒนาสองคนในการเขียนส่วนของเลเยอร์เดียวกันในการแยกแบบสัมพัทธ์ ซึ่งสามารถนำไปสู่แนวทางการดำเนินการที่ไม่ตรงกัน ... นี่ให้ความรู้สึกที่เป็นนามธรรมมาก ... ฉันยินดีที่จะเห็นด้วยกับสิ่งที่ฉันแนะนำอาจไม่น่าเป็นไปได้!
MetaFight

4

ฉันไม่ทราบข้อเสียใด ๆ เช่นกัน แต่เรื่องราวแนวดิ่งสามารถนำไปใช้ได้ไม่ดี

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

หนึ่งในปัญหาที่เราพบเมื่อทำงานในแนวนอนคือคุณสมบัติไม่ได้รวมเข้ากับเลเยอร์ได้ดี API มักไม่ตรงกับข้อกำหนดคุณลักษณะที่หายไปและปัญหาอื่น ๆ อีกมากมาย บ่อยครั้งเนื่องจากผู้พัฒนาของได้ย้ายไปยังสิ่งอื่นคุณจะต้องรอหรือทำด้วยตัวเอง

การเปลี่ยนไปทำเรื่องราวแนวดิ่งแก้ปัญหาเหล่านี้และลด / กำจัดของเสียจากการทำงานซ้ำเพื่อรวมเข้าด้วยกัน

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

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

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

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

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