คลาสที่ไม่ได้เป็นตัวแทนอะไร - ถูกต้องหรือไม่?


42

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

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

  1. FeatureExtractor
  2. ชุดข้อมูล
  3. วิเคราะห์

แต่คลาส FeatureExtractor ไม่ได้แสดงอะไรเลยมันทำสิ่งที่ทำให้มันเป็นกิจวัตรมากกว่าคลาส มันจะมีเพียงหนึ่งฟังก์ชั่นที่จะใช้: extract_features ()

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

แก้ไข: ไม่แน่ใจว่ามันสำคัญ แต่ฉันใช้ Python

และถ้า extract_features () จะมีลักษณะเช่นนั้น: มันคุ้มค่าไหมที่จะสร้างคลาสพิเศษเพื่อเก็บเมธอดนั้น

def extract_features(df):
    extr = PhrasesExtractor()
    extr.build_vocabulary(df["Text"].tolist())

    sent = SentimentAnalyser()
    sent.load()

    df = add_features(df, extr.features)
    df = mark_features(df, extr.extract_features)
    df = drop_infrequent_features(df)
    df = another_processing1(df)
    df = another_processing2(df)
    df = another_processing3(df)
    df = set_sentiment(df, sent.get_sentiment)
    return df

13
ฟังก์ชั่นนี้ดูดีมาก พิจารณาสามสิ่งที่คุณระบุไว้เป็นโมดูลก็โอเคและคุณอาจต้องการวางไว้ในไฟล์ที่แตกต่างกัน แต่นั่นไม่ได้หมายความว่าพวกเขาจะต้องเรียน
Bergi

31
โปรดทราบว่ามันค่อนข้างทั่วไปและยอมรับได้ในการใช้วิธีการที่ไม่ใช่ OO ใน Python
jpmc26

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

1
เมื่อคุณคุ้นเคยกับ OOP มากขึ้นฉันคิดว่าคุณจะพบว่าคลาสนั้นไม่ค่อยตรงกับแบบตัวต่อตัวกับเอนทิตีโลกแห่งความจริง ตัวอย่างเช่นต่อไปนี้เป็นบทความที่ระบุว่าพยายามยัดเยียดการทำงานทั้งหมดที่เกี่ยวข้องกับเอนทิตีโลกแห่งความจริงในคลาสเดียวมักจะเป็นรูปแบบต่อต้าน: programmer.97things.oreilly.com/wiki/index.php/ ......
Kevin - Reinstate Monica

1
"พวกเขาควรเป็นตัวแทนวัตถุจริงที่เราทำงานด้วย" ไม่จำเป็น. ภาษาจำนวนมากมีคลาสสตรีมที่แสดงถึงสตรีมของไบต์ซึ่งเป็นแนวคิดที่เป็นนามธรรมแทนที่จะเป็น 'วัตถุจริง' ในทางเทคนิคแล้วระบบไฟล์ไม่ใช่วัตถุจริง แต่เป็นเพียงแนวคิด แต่บางครั้งก็มีคลาสที่แสดงถึงระบบไฟล์หรือบางส่วน
Pharap

คำตอบ:


96

คลาสควรทำ 1 สิ่งและทำได้ดี

ใช่ว่าโดยทั่วไปเป็นวิธีการที่ดี

แต่ในทางกลับกันพวกเขาควรเป็นตัวแทนของจริงที่เราทำงานด้วย

ไม่นั่นเป็นความเข้าใจผิดที่เกิดขึ้นทั่วไปของ IMHO การเข้าถึง OOP เริ่มต้นที่ดีมักจะ"เริ่มต้นด้วยวัตถุที่เป็นตัวแทนของสิ่งต่าง ๆ จากโลกแห่งความเป็นจริง"ซึ่งเป็นเรื่องจริง

อย่างไรก็ตามคุณไม่ควรหยุดกับสิ่งนี้ !

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

หมายเหตุด้านข้าง: ในภาษาอย่าง Python ที่สนับสนุนแนวคิดของโมดูลที่แยกจากกันเราสามารถใช้โมดูลFeatureExtractorสำหรับสิ่งนี้ได้ แต่ในบริบทของคำถามนี้ IMHO แตกต่างกันเล็กน้อย

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


33
โดยเฉพาะอย่างยิ่งฉันชอบที่คุณพูดถึงปัญหาของรัฐภายใน ฉันมักจะพบว่ามันเป็นปัจจัยในการตัดสินใจว่าฉันจะทำบางสิ่งบางอย่างในชั้นเรียนหรือฟังก์ชั่นในงูใหญ่
David Z

17
คุณดูเหมือนจะแนะนำ“ classitis” อย่าสร้างคลาสสำหรับสิ่งนี้เพราะเป็นสเปรย์สไตล์ Java หากเป็นฟังก์ชันให้ใช้เป็นฟังก์ชัน สถานะภายในไม่เกี่ยวข้อง: ฟังก์ชันสามารถมีได้ (ผ่านการปิด)
Konrad Rudolph

25
@KonradRudolph: คุณดูเหมือนจะไม่ได้รับว่าเรื่องนี้ไม่เกี่ยวกับการทำอย่างใดอย่างหนึ่งฟังก์ชั่น นี่เป็นโค้ดส่วนหนึ่งที่ต้องการฟังก์ชั่นหลายอย่างชื่อสามัญและอาจจะเป็นบางสถานะที่ใช้ร่วมกัน การใช้โมดูลสำหรับสิ่งนี้อาจสมเหตุสมผลในภาษาที่มีแนวคิดโมดูลแตกต่างจากคลาส
Doc Brown

8
@DocBrown ฉันจะต้องไม่เห็นด้วย มันเป็นคลาสที่มีวิธีการสาธารณะหนึ่งวิธี API ฉลาดที่แยกไม่ออกจากฟังก์ชั่น ดูคำตอบของฉันสำหรับรายละเอียด การใช้คลาสเดียวสามารถทำได้หากคุณต้องการสร้างประเภทเฉพาะเพื่อเป็นตัวแทนของรัฐ แต่นี่ไม่ใช่กรณีที่นี่ (และแม้กระทั่งบางครั้งก็สามารถใช้ฟังก์ชันได้)
Konrad Rudolph

6
@DocBrown ฉันเริ่มที่จะเห็นว่าคุณหมายถึงอะไร: คุณกำลังพูดถึงฟังก์ชั่นที่เรียกจากภายในextract_features? ฉันแค่คิดว่าพวกเขาเป็นงานสาธารณะจากที่อื่น พอธรรมผมยอมรับว่าถ้าเหล่านี้เป็นส่วนตัวแล้วพวกเขาก็อาจจะไปลงในโมดูล ( แต่ยังคง: ไม่ได้เรียนจนกว่าพวกเขาจะแบ่งปันรัฐ) extract_featuresร่วมกับ (ที่กล่าวว่าแน่นอนคุณสามารถประกาศพวกเขาในท้องถิ่นในฟังก์ชั่นนั้น.)
Konrad Rudolph

44

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

ที่กล่าวว่ากรณีของคุณเป็นพิเศษ ตามคำอธิบายของคุณ:

และถ้า extract_features () จะมีลักษณะเช่นนั้น: มันคุ้มค่าไหมที่จะสร้างคลาสพิเศษเพื่อเก็บเมธอดนั้น

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

การใช้งานมากเกินไปนั้นเกิดจากความจริงที่ว่า OOP กลายเป็นกระแสหลักกับ Java ในปี 1990 น่าเสียดายที่ Java ในขณะนั้นขาดคุณสมบัติภาษาที่ทันสมัยหลายอย่าง (เช่นการปิด) ซึ่งหมายความว่าแนวคิดหลายอย่างนั้นยากหรือเป็นไปไม่ได้ที่จะแสดงออกโดยไม่ต้องใช้คลาส ตัวอย่างเช่นมันเป็นไปไม่ได้ใน Java จนกระทั่งเมื่อเร็ว ๆ นี้จะมีวิธีการที่ดำเนินการรัฐ (เช่นการปิด) แต่คุณต้องเขียนชั้นเรียนเพื่อพกพารัฐและสัมผัสวิธีการเดียว (เรียกว่าคล้ายinvoke)

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

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


มันจะมีประโยชน์ที่จะเพิ่มว่าถ้าฟังก์ชั่นที่เรียกว่าในตัวอย่างเป็นฟังก์ชั่นส่วนตัวจริงการห่อหุ้มพวกเขาในโมดูลหรือคลาสจะเหมาะสมทั้งหมด มิฉะนั้นฉันเห็นด้วยอย่างสิ้นเชิง
Leliel

11
นอกจากนี้ยังมีประโยชน์ที่ต้องจำไว้ว่า "OOP" ไม่ได้หมายความว่า "เขียนกลุ่มเรียน" ฟังก์ชั่นเป็นวัตถุใน Python ดังนั้นจึงไม่จำเป็นต้องพิจารณาสิ่งนี้ว่า "ไม่ใช่ OOP" แต่เป็นเพียงการนำชนิด / คลาสในตัวมาใช้ใหม่และ "นำกลับมาใช้ใหม่" เป็นหนึ่งใน grails ศักดิ์สิทธิ์ในการเขียนโปรแกรม การห่อสิ่งนี้ในคลาสจะป้องกันการนำกลับมาใช้ใหม่เนื่องจากไม่มีสิ่งใดที่เข้ากันได้กับ API ใหม่นี้ (เว้นแต่__call__จะมีการกำหนดไว้ซึ่งในกรณีนี้ให้ใช้ฟังก์ชัน!)
Warbo

3
นอกจากนี้ในเรื่องของ "คลาสเทียบกับฟังก์ชั่นยืนฟรี": eev.ee/blog/2013/03/03/ …
Joker_vD

1
ไม่ใช่เป็นเช่นนั้นแม้ว่าใน Python "ฟังก์ชั่นฟรี" ก็เป็นวัตถุที่มีประเภทที่เปิดเผยวิธีการ__call__()หรือไม่ นั่นแตกต่างจากอินสแตนซ์ของคลาสภายในที่ไม่ระบุชื่อจริงๆหรือ แน่นอนว่าจากการออกแบบทางภาษาดูเหมือนว่าจะมีความแตกต่างอย่างมีนัยสำคัญน้อยกว่าที่คุณนำเสนอที่นี่
JimmyJames

1
@JimmyJames ถูกต้อง จุดรวมคือพวกเขามีฟังก์ชั่นเดียวกันสำหรับวัตถุประสงค์เฉพาะ แต่ใช้งานง่ายขึ้น
Konrad Rudolph

36

ฉันเพิ่งออกแบบแอปพลิเคชันของฉันและฉันไม่แน่ใจว่าฉันเข้าใจ SOLID และ OOP ถูกต้องหรือไม่

มาที่นี่มากกว่า 20 ปีแล้วและฉันก็ไม่แน่ใจเหมือนกัน

คลาสควรทำ 1 สิ่งและทำได้ดี

ยากที่จะไปผิดที่นี่

ควรเป็นตัวแทนวัตถุจริงที่เราทำงานด้วย

โอ้จริงเหรอ? ผมขอแนะนำให้คุณรู้จักกับคลาสที่โด่งดังที่สุดและประสบความสำเร็จตลอดกาล: String. เราใช้มันเป็นข้อความ และวัตถุในโลกแห่งความเป็นจริงก็คือ:

ฟิชเชอร์แมนถือ 10 ปลาที่ถูกระงับจากสายเชือก

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

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

ตอนนี้แน่นอนคุณสามารถคิดแบบนี้:

ตัวอักษรเทศกาลหยุดจากสตริงอ่าน "ให้ทำสิ่ง!

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


1
รูปสวย ๆ ...
Zev Spitz

ณ จุดนี้ฉันไม่แน่ใจว่า "สตริง" เป็นอุปมา มันก็มีความหมายเฉพาะประสิทธิภาพการเขียนโปรแกรมเช่นเดียวกับคำเช่นclassและtableและcolumn...
Kyralessa

@Kyralessa คุณอีเธอร์สอนอุปมาอุปมัยมือใหม่หรือคุณปล่อยให้มันเป็นเวทมนตร์สำหรับพวกเขา โปรดช่วยฉันจากผู้เขียนที่เชื่อในเวทย์มนตร์
candied_orange

6

ระวัง! ไม่มีที่ใดที่โซลิดบอกว่าชั้นเรียนควร "ทำสิ่งใดสิ่งหนึ่งเท่านั้น" หากเป็นเช่นนั้นคลาสจะมีวิธีการเดียวเท่านั้นและจะไม่มีความแตกต่างระหว่างคลาสและฟังก์ชัน

SOLID กล่าวว่าชั้นเรียนควรแสดงความรับผิดชอบที่เดียว สิ่งเหล่านี้เป็นเหมือนหน้าที่รับผิดชอบของบุคคลในทีม: คนขับทนายนักล้วงกระเป๋านักออกแบบกราฟิก ฯลฯ บุคคลเหล่านี้สามารถทำงานหลายอย่าง (เกี่ยวข้อง) แต่ทั้งหมดเกี่ยวข้องกับความรับผิดชอบเดียว

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

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

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


+1 สำหรับ "ไม่จำเป็นต้องสร้างชั้นเรียนหากคุณสามารถแก้ไขได้ด้วยฟังก์ชั่น" บางครั้งบางคนต้องการพูดความจริง
tchrist

5

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

โดยทั่วไปนั่นก็โอเค

หากไม่มีคำอธิบายที่เฉพาะเจาะจงเพิ่มเติมเล็กน้อยสิ่งที่FeatureExtractorชั้นเรียนควรทำอย่างแน่นอนเป็นการยากที่จะบอก

อย่างไรก็ตามถึงแม้ว่าการFeatureExtractorเปิดเผยเพียงextract_features()ฟังก์ชั่นที่สาธารณะฉันสามารถคิดว่าการกำหนดค่าด้วยStrategyชั้นเรียนซึ่งเป็นตัวกำหนดว่าการสกัดควรจะทำอย่างไร

อีกตัวอย่างหนึ่งคือเรียนกับที่ฟังก์ชั่นแม่แบบ

และยังมีรูปแบบการออกแบบเชิงพฤติกรรมอีกมากซึ่งขึ้นอยู่กับแบบจำลองของชั้นเรียน


ในขณะที่คุณเพิ่มรหัสเพื่อชี้แจง

และถ้า extract_features () จะมีลักษณะเช่นนั้น: มันคุ้มค่าไหมที่จะสร้างคลาสพิเศษเพื่อเก็บเมธอดนั้น

เส้น

 sent = SentimentAnalyser()

ประกอบด้วยสิ่งที่ฉันหมายถึงว่าคุณสามารถกำหนดค่าคลาสด้วยกลยุทธ์ได้

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


2
ฉันไม่เห็นเหตุผลที่จะเพิ่มความซับซ้อน ( FeatureExtractorคลาส) เพียงเพื่อแนะนำความซับซ้อนมากยิ่งขึ้น (อินเทอร์เฟซสำหรับSentimentAnalyserชั้นเรียน) ถ้าเป็นที่น่าพอใจ decoupling แล้วextract_featuresสามารถใช้get_sentimentฟังก์ชั่นเป็นอาร์กิวเมนต์ (การloadโทรดูเหมือนจะเป็นอิสระจากฟังก์ชั่นและเรียกเฉพาะสำหรับผลกระทบของมัน) นอกจากนี้โปรดทราบว่า Python ไม่มี / กระตุ้นการเชื่อมต่อ
Warbo

1
@warbo - แม้ว่าคุณจะให้ฟังก์ชันเป็นอาร์กิวเมนต์โดยการทำให้มันเป็นฟังก์ชันคุณจะ จำกัด การใช้งานที่เป็นไปได้ซึ่งจะเหมาะกับรูปแบบของฟังก์ชั่น แต่ถ้ามีความจำเป็นในการจัดการสถานะถาวรระหว่างการร้องขอและ ถัดไป (เช่น a CacheingFeatureExtractorหรือ a TimeSeriesDependentFeatureExtractor) จากนั้นวัตถุจะมีขนาดพอดีดีกว่ามาก เพียงเพราะไม่จำเป็นต้องมีวัตถุในปัจจุบันไม่ได้หมายความว่าจะไม่มี
จูลส์

3
@Jules ประการแรกคุณไม่ต้องการมัน (YAGNI), ประการที่สองฟังก์ชั่น Python สามารถอ้างอิงสถานะถาวร (ปิด) ถ้าคุณต้องการ (คุณไม่ได้), ประการที่สามการใช้ฟังก์ชั่นไม่ได้ จำกัด อะไรตั้งแต่วัตถุใด ๆ ที่มี__call__วิธีการจะเข้ากันได้ถ้าคุณต้องการ (คุณไม่ได้), ประการที่สี่โดยการเพิ่มเสื้อคลุมเหมือนที่FeatureExtractorคุณกำลังทำรหัสที่เข้ากันไม่ได้กับรหัสอื่น ๆ ทั้งหมดที่เคยเขียน (เว้นแต่คุณจะให้__call__วิธีการในกรณีที่ฟังก์ชั่น )
Warbo

0

รูปแบบและทุกภาษาแฟนซี / แนวคิดกัน: สิ่งที่คุณได้เจอเป็นงานหรือกระบวนการผลิตเป็นชุด

ในตอนท้ายของวันแม้แต่โปรแกรม OOP ที่บริสุทธิ์ก็จำเป็นต้องได้รับแรงผลักดันจากบางสิ่งเพื่อทำงานจริงๆ จะต้องมีจุดเข้าใช้อย่างใด ในรูปแบบ MVC ตัวอย่างเช่น "C" ontroller ได้รับเหตุการณ์การคลิก ฯลฯ จาก GUI จากนั้นทำการวางองค์ประกอบอื่น ๆ ในเครื่องมือบรรทัดคำสั่งแบบคลาสสิกฟังก์ชัน "main" จะทำเช่นเดียวกัน

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

คลาสของคุณแสดงถึงเอนทิตีที่ทำบางสิ่งบางอย่างและจัดการทุกอย่างอื่น คุณสามารถตั้งชื่อมันว่าController , Job , Mainหรืออะไรก็ตามที่อยู่ในใจ

และถ้า extract_features () จะมีลักษณะเช่นนั้น: มันคุ้มค่าไหมที่จะสร้างคลาสพิเศษเพื่อเก็บเมธอดนั้น

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


3
โปรดทราบว่าในสถานการณ์เช่นนี้การเรียก "วิธีการ" แบบสแตนด์อโลนอาจทำให้เกิดความสับสน ภาษาส่วนใหญ่รวมถึง Python เรียกว่า "ฟังก์ชั่น" "วิธีการ" ที่มีฟังก์ชั่น / วิธีการที่ถูกผูกไว้กับอินสแตนซ์โดยเฉพาะอย่างยิ่งของชั้นซึ่งอยู่ตรงข้ามกับการใช้งานของคุณในระยะ :)
Warbo

จริงพอ @Warbo หรือเราสามารถเรียกมันว่ากระบวนงานหรือ defun หรือ sub หรือ ... ; และพวกเขาอาจเป็นวิธีการเรียน (sic) ไม่เกี่ยวข้องกับอินสแตนซ์ ฉันหวังว่าผู้อ่านที่อ่อนโยนจะสามารถขจัดความหมายที่ตั้งใจไว้ได้ :)
AnoE

@Warbo มันดีที่รู้! สื่อการเรียนรู้ส่วนใหญ่ฉันเจอรัฐระบุว่าฟังก์ชั่นคำศัพท์และวิธีการนั้นใช้แทนกันได้และเป็นเพียงการตั้งค่าภาษา
Dom

@Dom โดยทั่วไป a ("pure") "function" คือการแม็พจากค่าอินพุตไปยังค่าเอาต์พุต "โพรซีเดอร์" เป็นฟังก์ชันที่อาจทำให้เกิดเอฟเฟกต์ (เช่นการลบไฟล์); ทั้งสองถูกส่งแบบสแตติก (เช่นค้นหาในขอบเขตคำศัพท์) "วิธีการ" เป็นฟังก์ชั่นหรือ (ปกติ) ขั้นตอนซึ่งส่งแบบไดนามิก (ค้นหา) จากค่า (เรียกว่า "วัตถุ") ซึ่งถูกผูกไว้โดยอัตโนมัติเพื่อโต้แย้ง(โดยนัยthisหรือชัดเจนself) ของวิธีการ วิธีการของวัตถุเป็นแบบ "เปิด" ซ้ำกันดังนั้นการแทนที่จะfooทำให้เกิดการself.fooเรียกทั้งหมดเพื่อใช้การแทนที่นี้
Warbo

0

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

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

เมื่อเรามีชิ้นส่วนง่าย ๆ เหล่านั้นเราสามารถรวมเข้าด้วยกันเพื่ออธิบายพฤติกรรมของชิ้นส่วนที่ใหญ่กว่าซึ่งเราสามารถรวมเข้าด้วยกันเป็นชิ้น ๆ ที่มีขนาดใหญ่ขึ้นเรื่อย ๆ จนกว่าเราจะสามารถอธิบายส่วนประกอบทั้งหมดของโดเมนที่จำเป็นสำหรับทั้ง ระบบ.

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

โปรดทราบว่าเราสามารถเขียนคลาสใหม่สำหรับส่วนประกอบเหล่านั้น (foos, bar and bazs) แต่เราไม่จำเป็นต้องทำถ้ามีบางอย่างที่มีพฤติกรรมที่ถูกต้องอยู่แล้ว โดยเฉพาะอย่างยิ่งสำหรับคลาสที่มีประโยชน์จะต้อง 'ให้' บางสิ่ง (ข้อมูลวิธีการค่าคงที่คลาสย่อย ฯลฯ ) ดังนั้นแม้ว่าเราจะมีคลาสแบบกำหนดเองหลายเลเยอร์เราต้องใช้คุณลักษณะในตัวบางอย่างในที่สุด ตัวอย่างเช่นถ้าเราเขียนคลาสใหม่สำหรับ foos มันก็อาจจะมีเพียงสตริงดังนั้นทำไมไม่ลืมคลาส foo และให้บาร์คลาสมีสตริงเหล่านั้นแทน โปรดทราบว่าคลาสนั้นเป็นวัตถุในตัวด้วยเช่นกันพวกมันเป็นเพียงวัตถุที่ยืดหยุ่นเป็นพิเศษ

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

เมื่อเรามีการจำลองนี้เราสามารถเรียกใช้และเฮ้โอมเพี้ยงเรามีระบบการเรียนรู้เครื่องจักร (จำลอง) สำหรับ ... (หรืออะไรก็ตามที่เรากำลังสร้างแบบจำลอง)


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


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

ในอดีตวรรณกรรม OOP จำนวนมาก (โดยเฉพาะ "รูปแบบการออกแบบ") ได้มุ่งเน้นไปที่ Java ซึ่งค่อนข้างแตกต่างจาก Python ตัวอย่างเช่นคลาส Java ไม่ใช่วัตถุ Java ไม่ได้มีฟังก์ชั่นวัตถุจนกระทั่งเมื่อเร็ว ๆ นี้ Java มีการตรวจสอบประเภทที่เข้มงวด (ซึ่งสนับสนุนการเชื่อมต่อและคลาสย่อย) ในขณะที่ Python สนับสนุนการพิมพ์ด้วยเป็ด Java ไม่มีวัตถุโมดูล ลอย / ฯลฯ ไม่ใช่วัตถุการเขียนโปรแกรมเมตา / การวิปัสสนาใน Java ต้องใช้ "การสะท้อน" และอื่น ๆ

ฉันไม่ได้พยายามเลือกบน Java (เป็นอีกตัวอย่างหนึ่งทฤษฎี OOP มากมายหมุนรอบ Smalltalk ซึ่งแตกต่างจาก Python อีกครั้ง) ฉันแค่พยายามชี้ให้เห็นว่าเราต้องคิดอย่างรอบคอบเกี่ยวกับบริบทและ ข้อ จำกัด ในการแก้ปัญหาที่ได้รับการพัฒนาและไม่ว่าจะตรงกับสถานการณ์ที่เรากำลัง

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


0

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

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

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