รูปแบบการต่อต้านการตั้งชื่ออะไรอยู่? [ปิด]


35

มีบางชื่อที่ถ้าคุณพบว่าตัวเองชื่อคุณรู้ว่าคุณได้ทำบางสิ่งบางอย่างสับสน

ตัวอย่างเช่น:

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

มีรูปแบบการต่อต้านการตั้งชื่ออื่น ๆ อีกบ้าง?

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


1
วิธีการเกี่ยวกับSmurf ตั้งชื่อการประชุม ?
back2dos

4
สำหรับผู้ลงคะแนนให้ปิดในฐานะ "ไม่สร้างสรรค์" - คุณยินดีที่จะอธิบายเหตุผลว่าทำไม เพียงคนเดียวที่นี้ไม่ได้ทำดีเกินไปกับการเป็นว่าคำตอบอาจจะสั้น แต่แน่นอนมีคุณสมบัติตรงตามหลักเกณฑ์อีกห้า ...
บิลลี่ ONeal


2
@Aaraught: คำแนะนำใด ๆ ฉันได้พูดคุยเกี่ยวกับเรื่องนี้เช่นเดียวกับที่ฉันสามารถในการแก้ไข ....
Billy ONeal

1
@ jhocking - ฉันเห็นด้วยกับลิงค์นั้น - โดยเฉพาะอย่างยิ่งเรื่อง "Manager" และ "Handler" นั้นมีค่าเกินกว่าที่จะปล่อยได้ และฉันก็ไม่ได้ขายในรูปแบบการออกแบบและทางเลือกอื่น ๆ ซึ่งอย่างน้อยก็คลุมเครือในหลายกรณี บางครั้ง "คิว" หรืออะไรก็ตามที่อาจเหมาะสม แต่บ่อยครั้งที่ข้อเท็จจริงที่ผู้จัดการเก็บไอเท็ม (หรือการอ้างอิง) ในคิวนั้นเป็นเพียงแง่มุมหนึ่งของการจัดการไอเท็มเหล่านั้น เช่นเดียวกับสิ่งที่มีประโยชน์จะถูกแสดงโดย "ผู้จัดการ" เป็นชื่องาน IMO เดียวกันจะใช้ใน OOP
Steve314

คำตอบ:


22

รูปแบบการต่อต้านการตั้งชื่อต่อไปนี้เกี่ยวข้องกับ. NET และโดยเฉพาะ C #:

  • ไม่สอดคล้องกัน ถ้าคุณตัดสินใจที่จะเริ่มต้นชื่อทุกสาขาที่มีขีดชั้นนำติดมัน
  • ตัวย่อ Ambiguos กับสระหายไป cxtCtrlMngrฉันได้เห็นอย่างจริงจังชื่อฟิลด์เช่น คุณแทบจะไม่สามารถเดาได้ว่าสิ่งที่ควรจะเป็น
  • ยาวเกินไปและ verbose ชื่อตัวแปร ILoginAttemptRepositoryดีและเป็นคำอธิบาย - ILoginAttemptRepositoryUsingEntityFrameworkForObjectRelationalMappingเป็นคำอธิบาย แต่ไม่แน่นอน

7
เป็นIความหมายที่จะหมายถึงinterfaceที่นี่implementerหรือเอกพจน์คนแรก? เนื่องจากคลาสส่วนใหญ่ใช้อินเทอร์เฟซการมีคลาส / อินเตอร์คาเฟ่มากเกินไปเริ่มต้นด้วยตัวเมืองหลวงIนั้นน่ารำคาญและขัดขวางการอ่านได้และมีกลิ่นรหัสของมัน
ผู้ใช้ที่ไม่รู้จัก

3
+1 สำหรับ "ตัวย่อ Ambiguos ที่มีสระหายไป" พวกนั้นทำให้ฉันบ้า!
FrustratedWithFormsDesigner

6
@Billy ONeal: C ++ มีอินเตอร์เฟส พวกเขาไม่ได้แยกออกจากชั้นเรียนโดยไม่ตั้งใจ ;)
Jon Purdy

4
@Billy ONeal: นั่นคือจุดของฉัน
Jon Purdy

2
@MariusSchulz: โอ้ใช่ฉันเห็นด้วยกับคุณ :) แค่คิดว่ามันไม่ใช่ตัวย่อที่ทึบแสงมาก
amara

9

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

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


7

คำตอบง่ายๆก่อนอื่นให้พิมพ์ภาษาฮังการี ( http://mindprod.com/jgloss/unmainnaming.htmlยังมีความคิดอื่น ๆ อีกมาก) มุมมองที่สมดุลมากขึ้นเมื่อชาวฮังการีไม่ใช่คนชั่วร้าย http://www.joelonsoftware.com /articles/Wrong.html )


7
สัญกรณ์ฮังการีเป็นสิ่งที่เลวร้ายเสมอ :)
Wayne Molina

12
@ Wayne: จริงๆแล้วมันไม่ได้เลวร้ายเสมอไป ฉันทำงานให้กับชาร์ลส์ที่ซีร็อกซ์ในช่วงปลายยุค 70 และระบบการตั้งชื่อดั้งเดิมเป็นผู้ช่วยชีวิต เราทำงานใน BCPL ซึ่งมี 1 ประเภท: จำนวนเต็ม ทุกอย่างอื่นเกี่ยวกับประเภทถูกถ่ายทอดโดยใช้และการตั้งชื่อการประชุม เรามีโปรแกรมเมอร์ 7 คน + ชาร์ลส์และเราคนใดคนหนึ่งสามารถเดินเข้าไปในรหัสของคนอื่นและทำงานได้ทันที นี่ไม่ใช่การบอกว่ามันไม่สามารถบิด / ใช้ผิดอย่างน่ากลัว (แม้กระทั่งโดยชาร์ลส์) เพียงแค่ว่าในบริบทที่ถูกต้องมันเป็นทางออกที่ถูกต้อง
Peter Rowell

3
@Marius: อ่านบทความของ Joel ระบบประเภทไม่สามารถบังคับใช้ความแตกต่างทางความหมายระหว่างตัวแปรได้เสมอ Intellisense ไม่ได้ช่วยในกรณีเช่นนี้
Billy ONeal

4
ประเภทง่ายกว่าการอนุมานโดยใช้ กับบรรณาธิการที่ทันสมัย อย่างไรก็ตามมันต้องมีวินัย คุณไม่ได้มีคำนำหน้าทุกอย่าง ฉันทำงานใน Java และส่วนใหญ่แอพฮังการีไม่จำเป็น แต่เมื่อฉันทำอะไรที่ต้องใช้ตัวแปรประเภทเดียวกันหลายประเภท (เช่น fromX และ toX) ในระบบพิกัดมันเป็นเครื่องช่วยชีวิต
Michael K

3
สิ่งที่จะดีคือความสามารถทั่วไปในการสร้างรูปแบบใหม่ได้อย่างง่ายดาย "อันนี้เหมือน int ยกเว้นจะใช้กับหมายเลขแถว"
David Thornley

6

คำนำหน้า 'I' เป็นชื่อของอินเทอร์เฟซหรือ 'Abstract' เป็นชื่อของคลาสนามธรรม สิ่งนี้อาจนำมาใช้ซ้ำได้ในภาษาที่ไม่มีแนวคิดของคลาสนามธรรมหรือที่ไม่แยกความแตกต่างระหว่างอินเทอร์เฟซและคลาสนามธรรม - แต่ใน Java ตัวอย่างเช่นมันเป็นความคิดที่ไม่ดีเสมอ

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


@ ไมค์: ฉันไม่เห็นด้วยกับคำสั่งของคุณอย่างเต็มที่ขอโทษ ในความคิดของฉันXxxxManagerมันเป็นชื่อที่แย่ที่สุดที่เป็นไปได้ในชั้นเรียน แน่นอนมันจัดการอะไรบางอย่าง! นั่นคือเหตุผลที่เขียนขึ้นสำหรับ Managerเป็นคำเติมเต็มความหมายที่เพิ่มคุณค่าให้กับความเข้าใจ - โดยชื่อของมัน - สิ่งที่ชั้นเรียนมีความรับผิดชอบ
Marius Schulz

1
แล้วพูดTabManagerอะไร มีชื่อที่ดีกว่าสำหรับคลาสที่ควบคุมกลไกแท็บ JSP หรือไม่ หรืออ้าปากค้าง TabController ... เท่าที่คำนำหน้าด้วยAbstractฉันรู้สึกว่ามันมากเกินไป แต่มักจะใช้ได้ (ดูตัวอย่างไลบรารีของ Java) ฉันคิดว่าฉันสามารถพูดได้อย่างปลอดภัยว่าฉันไม่เคยเห็นIอินเทอร์เฟซในสถานที่ใด ๆ ที่ใครบางคนไม่ได้พยายามตั้งโปรแกรมกับอินเทอร์เฟซที่ไม่ควรอยู่ที่นั่น เช่นเดียวคลาสเดียวที่ใช้อินเทอร์เฟซ
Michael K

1
@Darien (และอื่น ๆ ): ไม่ว่าจะด้วยวิธีใด - มันไม่สำคัญ ไม่มีชื่อเหล่านี้เป็นรูปแบบการต่อต้าน (และพวกเขาอยู่นอกหัวข้อสำหรับคำถามนี้) ฉันไม่คิดว่าคุณสามารถพูดอะไรเกี่ยวกับการออกแบบระบบได้ไม่ว่าพวกเขาจะใช้IXxxหรือXxxImplไม่ก็ตาม
Billy ONeal

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

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

6

Speeling:

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


2
ฉันใช้ปลั๊กอิน jQuery สั้น ๆ ว่าพารามิเตอร์ตัวใดตัวหนึ่งเป็นaffect(แทนเอฟเฟกต์) มันทำให้ฉันเป็นบ้าและฉันก็พบปลั๊กอินที่แตกต่างเพื่อทำสิ่งเดียวกัน
zzzzBov

4
ปัญหาที่แย่ที่สุดที่ฉันมีคือเมื่อฉันเห็นชื่อที่สะกดผิดมันทำให้ฉันเจ็บปวดอย่างมากที่จะจำชื่อนั้นได้
David Thornley

1
มันเลวร้ายลงเมื่อสิ่งเดียวกันสะกดแตกต่างกันในส่วนต่าง ๆ ของรหัส เช่นเมื่อคุณมีฟิลด์ strenght ของคลาส Srtength เข้าถึงได้โดยเมธอด getStrenth ()
Eva

5

ฉันเกรงว่าความคิดเห็นของฉันจะขัดแย้งกันเล็กน้อย แต่ลอง ...

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

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

สิ่งที่ฉันไม่ชอบคือเมื่อเมธอดที่เรียกว่า get ... หรือ set ... เป็นมากกว่า accessor ธรรมดา ๆ ฉันชอบเดช ... เพื่อพิจารณา

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

ฉันเองก็เป็นแฟนตัวยงของสัญกรณ์ระบบฮังการี - ส่วนใหญ่คุณกำลังติดต่อกับซอร์สโค้ดใน IDE ตกลง แต่บ่อยครั้งที่คุณใช้โปรแกรมแก้ไขหรือคุณเรียกดู repo ในเบราว์เซอร์ ข้อเสียอย่างหนึ่งอาจเป็นเครื่องมือสนับสนุนเนื่องจากคำนำหน้าประเภท ...

ฉันคิดว่าสิ่งที่สำคัญที่สุดคือ beeing consitent - อนุสัญญาไม่ดี - สำหรับฉัน - ดีกว่าที่ไม่มีการประชุม ...


1
"คอนโทรลเลอร์" มีความหมายที่แตกต่างจาก "ผู้จัดการ" โดยส่วนตัวแล้วฉันไม่ชอบ แต่อย่างใด "คอนโทรลเลอร์" เข้าถึงได้เพราะเป็นองค์ประกอบทั่วไปของรูปแบบมากมายโดยเฉพาะ MVC XxxHandler แย่มาก หากคลาสเพียง "จัดการ" บางอย่าง - คลาสนั้นใหญ่เกินไปหรือควรเรียกว่าส่วน "Xxx"
Billy ONeal

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

5

บางทีรูปแบบการตั้งชื่อที่แย่ที่สุดก็คือ

create table stuff(..., foo1 string, bar1 string,
                        foo2 string, bar2 string, 
                        foo3 string, bar3 string, ...)

เรามีรายการสามองค์ประกอบของคู่ [foo, bar] ถ้าเราต้องการหนึ่งในสี่เราจะต้องเพิ่มคอลัมน์ใหม่ลงในตาราง

นำไปสู่รหัสเช่นนี้:

'SELECT foo' + i + ', bar' + i + ' FROM stuff'

ควรสร้างตารางแยกต่างหากด้วยคอลัมน์ foo และ bar และเชื่อมโยงกับตารางรายการ:

create table fubar(foo string, bar string, stuff_id long)

สิ่งที่เลวร้ายที่สุดอันดับสองคือ:

class Student {
  ...
  String homeStreet;
  String homeCity;
  String homeState;
  String permStreet;
  String permCity;    
  String permState;
  ...
}

ที่นี่เรามีหกฟิลด์แทนสองอินสแตนซ์ของคลาสที่อยู่

รูปแบบการต่อต้านนี้ถูกทำเครื่องหมายด้วยชุดชื่อสองส่วนที่แสดงรายการทุกชุดของสองชุดเช่น [foo, bar] x [1,2,3] หรือ [home, Perm] x [ถนน, เมือง, state]


-1 - นี่ไม่ได้กล่าวถึงการตั้งชื่อเลย
Billy ONeal

รูปแบบการตั้งชื่อไม่สามารถมีชื่อมากกว่าหนึ่งชื่อได้หรือไม่
วินไคลน์

การ==ตั้งชื่อ antipattern มีการโต้แย้งกันมากเกินไปอย่างไร? ฉันสับสน
Billy ONeal

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

3
@Billy ONeal: ใช่พวกเขาทำ ปัญหาการออกแบบคือการขาดการทำให้ปกติและส่วนต่อท้ายของตัวเลขเป็นรูปแบบการตั้งชื่อที่ชี้ไป
reinierpost

3

การตั้งชื่อคลาสหรืออินเทอร์เฟซใด ๆ ที่เป็นเรื่องที่ซ้ำซากนั้นเป็นสิ่งที่ไม่ดีไม่ใช่แค่ใน Java ที่ลิงก์พูดถึง แต่เป็นภาษาใด ๆ

Tautology (วาทศาสตร์) ใช้คำที่แตกต่างกันในการพูดในสิ่งเดียวกันแม้ว่าการทำซ้ำไม่ได้ให้ความชัดเจน


2
น่าสนใจ ตัวอย่างใด ๆ ?
Mike Baranczak

2
ฉันอ่านลิงค์มันก็บอกว่า "ซ้ำซาก" ... ;)
46411

10
กฎข้อแรกของสโมสร tautology คือกฎข้อแรกของชมรม tautology
Cercerilla

ฉันอ่านลิงค์ (โอเคเนื้อหาของลิงค์) และไม่พบตัวอย่าง
barjak

ตกลงตามลิงค์นั้นเราควรหยุดใช้ฉัน <InterfaceName> ... ถูกต้อง
Dal

3

ฉันมักพบห้องสมุดซอฟแวร์ที่มีชื่อทั่วไปเช่นหรือLibrary Commonพวกเขาบ่งบอกถึงการออกแบบที่ไม่ดี: นักพัฒนาพยายามที่จะหลีกเลี่ยงการทำสำเนารหัส แต่ไม่มีความพยายามใด ๆ ที่จะสร้างการออกแบบที่สลายตัวบนพื้นฐานของการทำงาน


+1 - ฉันเห็นคำว่า "ธรรมดา" ตลอดเวลา
Morgan Herlocker

1

จากMicrosoftในการตั้งชื่อฉันสามารถให้รายการนี้สำหรับชื่อที่ไม่ดี:

  1. พวกเขาจะไม่ความหมายซึ่งหมายความว่าพวกเขามีชื่อซึ่งแทนที่จะเน้นสิ่งที่มันไม่ให้ความสำคัญกับเทคโนโลยีที่ใช้หรือรูปแบบก็ขึ้นอยู่กับ
  2. พวกเขาไม่ปฏิบัติตามความสอดคล้องด้านไวยากรณ์ ตัวอย่างเช่นส่วนหนึ่งของชื่อจะถูกใส่อูฐในขณะที่ส่วนอื่น ๆ จะเป็นปาสคาล
  3. มันเป็นตัวย่อซึ่งยากที่จะเข้าใจเช่นScrollableXแทนที่จะเป็นCanScrollH แนวนอน
  4. พวกเขาเลือกเช่นที่พวกเขายุ่งกับคำหลักของสภาพแวดล้อมที่

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