เคยมีเหตุผลในการทำงานของวัตถุทั้งหมดในนวกรรมิกหรือไม่?


49

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

ในขณะที่ บริษัท ของเราเติบโตขึ้นเราได้พยายามพัฒนาบ้านให้มากขึ้น โปรเจ็กต์นี้ลงบนตักของฉันดังนั้นฉันได้ไปทำความสะอาดเพิ่มการทดสอบ ฯลฯ ฯลฯ

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

ตัวอย่างเช่น (รหัสอยู่ใน Java หากมีความสำคัญ แต่ฉันหวังว่านี่จะเป็นคำถามทั่วไปมากขึ้น):

public class Foo {
  private int bar;
  private String baz;

  public Foo(File f) {
    execute(f);
  }

  private void execute(File f) {
     // FTP the file to some hardcoded location, 
     // or parse the file and commit to the database, or whatever
  }
}

หากคุณสงสัยรหัสประเภทนี้มักจะถูกเรียกในลักษณะดังต่อไปนี้:

for(File f : someListOfFiles) {
   new Foo(f);
}

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

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

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


18
ดูเหมือนว่าฉันจะถูกเขียนขึ้นโดยนักพัฒนาที่รู้เกี่ยวกับpublic static void main(string[] args)และผู้ที่เคยได้ยินของวัตถุแล้วพยายามที่จะบดเข้าด้วยกัน
Andy Hunt

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

4
คำถามที่เกี่ยวข้อง: มีปัญหาอะไรกับการทำงานหลักของคลาสในคอนสตรัคเตอร์หรือไม่? . แม้ว่าคนนี้จะแตกต่างกันเล็กน้อยเนื่องจากอินสแตนซ์ที่สร้างขึ้นจะถูกใช้ในภายหลัง
sleske


ฉันไม่ต้องการขยายคำตอบนี้ให้เต็ม แต่ขอให้ฉันบอกว่า: มีหลายสถานการณ์ที่ยอมรับได้ อันนี้อยู่ไกลจากมันมาก ที่นี่วัตถุนั้นถูกสร้างขึ้นโดยไม่จำเป็นต้องมีวัตถุจริงๆ ในทางตรงกันข้ามถ้าคุณกำลังสร้างโครงสร้างข้อมูลบางอย่างจากไฟล์ XML การเริ่มต้นการแยกวิเคราะห์จากตัวสร้างไม่น่ากลัวเลย ในความเป็นจริงในภาษาที่อนุญาตให้มีการสร้างมากเกินไปมันไม่มีอะไรที่ฉันจะฆ่าคุณในฐานะผู้ดูแล;)
back2dos

คำตอบ:


60

ตกลงลงรายการ:

ฉันถูกสอนมานานแล้วว่าวัตถุที่สร้างอินสแตนซ์ในลูปโดยทั่วไปเป็นความคิดที่ไม่ดี

ไม่ได้อยู่ในภาษาใด ๆ ที่ฉันเคยใช้

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

โดยทั่วไปหากคุณต้องการวัตถุภายในลูปให้สร้างขึ้นใหม่

ตัวสร้างควรทำขั้นต่ำของงาน

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

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

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

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

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

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

3
เวอร์ชั่นสั้น: อย่าใช้อินสแตนซ์ของวัตถุเช่นเดียวกับฟังก์ชั่น
Erik Reppen

27

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

ตัวอย่างที่ดี :

ฉันไม่แน่ใจว่าการใช้งานนี้เป็นรูปแบบต่อต้านหรือไม่ แต่ใน C # ฉันเคยเห็นโค้ดที่เรียงตามบรรทัดของ (ตัวอย่างที่ทำขึ้นมาบ้าง):

using (ImpersonationContext administrativeContext = new ImpersonationContext(ADMIN_USER))
{
    // Perform actions here under the administrator's security context
}
// We're back to "normal" privileges here

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

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

ความคิดเห็นในตัวอย่างของคุณ:

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

ฉันกำลังดิ้นรนเพื่อหาคำพูด แต่หนังสือ "Object Solutions" ของ Grady Booch มีเรื่องราวเล็ก ๆ น้อย ๆ เกี่ยวกับทีมนักพัฒนา C ที่เปลี่ยนมาใช้ C ++ เห็นได้ชัดว่าพวกเขาได้รับการฝึกอบรมและได้รับการบอกเล่าจากฝ่ายบริหารว่าพวกเขาต้องทำสิ่งต่าง ๆ "เชิงวัตถุ" ผู้เขียนใช้เครื่องมือชี้วัดโค้ดและพบว่าจำนวนเฉลี่ยของวิธีการต่อชั้นเรียนเท่ากับ 1 และมีการแปรผันของวลี "ลงมือทำ" ฉันต้องบอกว่าฉันไม่เคยพบปัญหานี้มาก่อน แต่ดูเหมือนจะเป็นอาการของคนที่ถูกบังคับให้สร้างโค้ดเชิงวัตถุโดยที่ไม่เข้าใจวิธีการทำเช่นนั้นและทำไม


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

@ แซคฉันไม่เคยคิดถึงมันในแง่เหล่านั้นแม้ว่าฉันจะได้รับรู้ถึง RAII ใน C ++ แล้วก็ตาม ในโลก C # มันเรียกว่ารูปแบบที่ใช้แล้วทิ้งและแนะนำเป็นอย่างยิ่งสำหรับทุกสิ่งที่มีทรัพยากร (โดยทั่วไปไม่มีการจัดการ) เพื่อให้ฟรีหลังจากอายุการใช้งาน ข้อแตกต่างที่สำคัญของตัวอย่างนี้คือโดยทั่วไปแล้วคุณจะไม่ใช้ตัวดำเนินการที่มีราคาแพงในตัวสร้าง เช่นเมธอด Open () ของ SqlConnection ยังคงต้องเรียกใช้หลังจาก Constructor
Daniel B

14

เลขที่

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

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


7

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

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

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


4

เคยมีเหตุผลในการทำงานของวัตถุทั้งหมดในนวกรรมิกหรือไม่?

เลขที่

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

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

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

1
"หากพวกเขาไม่ได้รับคำสั่งให้ทำเช่นนั้นโปรแกรมเมอร์ในอนาคตจะไม่มีแนวโน้มที่จะล้อมรอบการเรียกตัวสร้างเหล่านี้ด้วยรหัสป้องกัน" - จุดดี.
เกรแฮม

2

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

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

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


3
ฉันค่อนข้างมั่นใจว่าโปรแกรมเมอร์รายนี้ไม่เคยได้ยินคำว่า
เทอรีเคน

ฉันไม่คิดว่าโปรแกรมเมอร์กำลังพยายามสร้างสิ่งที่เป็นนามธรรม Java ที่เทียบเท่าจะต้องใช้วิธีนามธรรม (การวางแผนสำหรับ) polymorphism ไม่มีหลักฐานว่าที่นี่
Kevin A. Naudé

1

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


1

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

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

แม้ว่าจะมีคลาสยูทิลิตี้ แต่คนส่วนใหญ่ก็ไม่คิดว่าจะมีคลาสแบบสแตติกที่ซ้อนกันอยู่

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

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


1

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

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

var parser = XMLParser()
var x = parser.parse(string)
string a = x.LookupTag(s)

มันไม่ได้ดีไปกว่านี้อีกแล้ว

 var x = ParsedXML(string)
 string a = x.LookupTag(s)

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

x.UpdateView(v)

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

var x = new ComputeStatistics(inputFile)
int max = x.MaxOptions;
int mean = x.AverageOption;
int sd = x.StandardDeviation;
int k = x.Kurtosis;
...

ดังนั้นในฐานะผู้ร่วมเขียนโปรแกรม Python / C # ดูเหมือนจะไม่แปลกสำหรับฉัน


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

1

กรณีหนึ่งอยู่ในใจที่ตัวสร้าง / destructor ทำงานทั้งหมด:

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

ฉันยังได้เขียนสิ่งที่มีจำนวนของรหัสตัวสร้างเพียงอย่างเดียวเพื่อแก้ไขข้อผิดพลาดไลบรารีรันไทม์ (การแก้ไขรหัสจริงอาจทำให้เกิดปัญหาอื่น ๆ ) ไม่มีตัวทำลายเนื่องจากไม่จำเป็นต้องเลิกทำการแก้ไข


-1

ฉันเห็นด้วยกับ AndyBursh ดูเหมือนว่าปัญหาการขาดความรู้บางอย่าง

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


-4

"ฉันถูกสอนมานานแล้วว่าวัตถุที่สร้างอินสแตนซ์ในลูปโดยทั่วไปเป็นความคิดที่ไม่ดี"

ใช่คุณอาจจะจำได้ว่าทำไมเราถึงต้องการ StringBuilder

Java มีสองโรงเรียน

ผู้สร้างได้รับการส่งเสริมโดยคนแรกซึ่งสอนให้เราใช้ซ้ำ (เพราะการแบ่งปัน = ตัวตนกับประสิทธิภาพ) อย่างไรก็ตามในต้นปี 2000 ฉันเริ่มอ่านว่าการสร้างออบเจ็กต์ใน Java นั้นมีราคาถูก (เมื่อเทียบกับ C ++) และ GC นั้นมีประสิทธิภาพมากที่การใช้ซ้ำนั้นไม่มีประโยชน์และสิ่งเดียวที่สำคัญคือประสิทธิภาพของโปรแกรมเมอร์ สำหรับการผลิตเขาต้องเขียนโค้ดที่จัดการได้ซึ่งหมายถึงการทำให้เป็นโมดูล (aka การ จำกัด ขอบเขต) ดังนั้น,

นี้ไม่ดี

byte[] array = new byte[kilos or megas]
for_loop:
  use(array)

ดีจัง.

for_loop:
  byte[] array = new byte[kilos or megas]
  use(array)

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

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

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

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

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

"ไม่ต้องทำอะไรในคอนสตรัคเตอร์ของคุณมันเป็นเพียงการเริ่มต้นเท่านั้น"

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


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

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