การใช้วิธีการคงที่จำนวนมากเป็นสิ่งที่ไม่ดีหรือไม่?


97

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

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

นั่นเป็นแนวทางที่สมเหตุสมผลหรือไม่?


ใช่แล้ว. ตรวจสอบสิ่งนี้: yegor256.com/2014/05/05/oop-alternative-to-utility-classes.html
yegor256

คำตอบ:


154

วิธีการคงที่ทั่วไปมีสองประเภท:

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

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


นี่เป็นปัญหาที่ฉันต้องแก้ - การใช้หรือใช้ในทางที่ผิดของวัตถุ Singleton
โอเวอร์แล็ค

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

1
คำว่า "ฟังก์ชันบริสุทธิ์" และ "ฟังก์ชันไม่บริสุทธิ์" เป็นชื่อที่กำหนดในการเขียนโปรแกรมเชิงฟังก์ชันสำหรับสิ่งที่คุณเรียกว่าสถิตยศาสตร์ "ปลอดภัย" และ "ไม่ปลอดภัย"
Omnimike

19

วัตถุที่ไม่มีสภาวะภายในเป็นสิ่งที่น่าสงสัย

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

ในบางครั้งการออกแบบขั้นตอนจะทำในภาษาวัตถุ


6
ฉันได้ยินสิ่งที่คุณกำลังพูด แต่วัตถุทางคณิตศาสตร์จะห่อหุ้มอะไรก็ได้นอกจากพฤติกรรมได้อย่างไร?
JonoW

10
เขาแค่พูดว่าน่าสงสัยไม่ผิดและเขาพูดถูกจริงๆ
Bill K

2
@JonoW: คณิตศาสตร์เป็นกรณีพิเศษที่มีฟังก์ชันไร้สัญชาติจำนวนมาก แน่นอนว่าถ้าคุณกำลังเขียนโปรแกรม Functional ใน Java คุณจะมีฟังก์ชั่นไร้สัญชาติมากมาย
ล็อต

14

นี่เป็นเพียงการติดตามคำตอบที่ยอดเยี่ยมของ John Millikin


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

public class StaticClassVersionOne {
    public static void doSomeFunkyThing(int arg);
}

ซึ่งคุณเรียกว่า:

StaticClassVersionOne.doSomeFunkyThing(42);

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

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

อาจเป็นหรือไม่ใช่สถานการณ์ที่เป็นไปได้ แต่ฉันคิดว่ามันก็คุ้มค่าที่จะพิจารณา


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

6

ตัวเลือกอื่นคือการเพิ่มเป็นวิธีการที่ไม่คงที่บนวัตถุต้นกำเนิด:

กล่าวคือการเปลี่ยนแปลง:

public class BarUtil {
    public static Foo transform(Bar toFoo) { ... }
}

เป็น

public class Bar {
    ...
    public Foo transform() { ...}
}

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


5

ชั้นเรียนแบบคงที่นั้นใช้ได้ตราบเท่าที่ใช้ในสถานที่ที่เหมาะสม

วิธีการที่เป็นวิธีการ 'leaf' (ไม่ได้แก้ไขสถานะเป็นเพียงการแปลงอินพุตอย่างใดอย่างหนึ่ง) ตัวอย่างที่ดีคือสิ่งต่างๆเช่น Path.Combine สิ่งต่างๆเหล่านี้มีประโยชน์และเหมาะสำหรับไวยากรณ์ที่สั้นกว่า

ปัญหาที่ฉันมีกับสถิตเป็นจำนวนมาก:

ประการแรกถ้าคุณมีคลาสแบบคงที่การอ้างอิงจะถูกซ่อนไว้ พิจารณาสิ่งต่อไปนี้:

public static class ResourceLoader
{
    public static void Init(string _rootPath) { ... etc. }
    public static void GetResource(string _resourceName)  { ... etc. }
    public static void Quit() { ... etc. }
}

public static class TextureManager
{
    private static Dictionary<string, Texture> m_textures;

    public static Init(IEnumerable<GraphicsFormat> _formats) 
    {
        m_textures = new Dictionary<string, Texture>();

        foreach(var graphicsFormat in _formats)
        {
              // do something to create loading classes for all 
              // supported formats or some other contrived example!
        }
    }

    public static Texture GetTexture(string _path) 
    {
        if(m_textures.ContainsKey(_path))
            return m_textures[_path];

        // How do we know that ResourceLoader is valid at this point?
        var texture = ResourceLoader.LoadResource(_path);
        m_textures.Add(_path, texture);
        return texture; 
    }

    public static Quit() { ... cleanup code }       
}

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

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

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

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

นี่คือบทความดีๆเกี่ยวกับปัญหา: http://gamearchitect.net/2008/09/13/an-anatomy-of-despair-managers-and-contexts/


4

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

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

  • บางภาษายังมีตัวแปรระดับคลาสซึ่งจะอนุญาตให้มีการห่อหุ้มข้อมูลและวิธีการแบบคงที่

4

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

ในกรณีของคุณที่คุณแค่เปลี่ยน A เป็น B ให้บอกว่าสิ่งที่เราทำคือการเปลี่ยนข้อความให้เปลี่ยนจากเดิม

"hello" =>(transform)=> "<b>Hello!</b>"

ถ้าอย่างนั้นวิธีคงที่จะสมเหตุสมผล

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

class Interface{
    method toHtml(){
        return transformed string (e.g. "<b>Hello!</b>")
    }

    method toConsole(){
        return transformed string (e.g. "printf Hello!")
    }
}


class Object implements Interface {
    mystring = "hello"

    //the implementations of the interface would yield the necessary 
    //functionality, and it is reusable across the board since it 
    //is an interface so... you can make it specific to the object

   method toHtml()
   method toConsole()
}

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

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


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

3

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

ดังนั้นคำตอบของฉันคือคลาสคงที่ไม่ได้แย่ แต่อย่างใด แต่อาจจะง่ายกว่าที่จะเริ่มสร้างอินสแตนซ์ในตอนนี้จากนั้นจึงต้องทำการ refactor ในภายหลัง


3

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


2

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

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

และวิธีการคงไม่มีข้อได้เปรียบที่คล้ายกัน

ใช่พวกเขาไม่ดี


1

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


1

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


1

หากเป็นวิธียูทิลิตี้ก็เป็นการดีที่จะทำให้มันคงที่ Guava และ Apache Commons สร้างขึ้นจากหลักการนี้

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

ดังนั้นในตรรกะแอปของฉันฉันมักจะมีการเรียกเมธอดเหมือนยูทิลิตี้แบบคงที่ขนาดเล็ก ได้แก่

static cutNotNull(String s, int length){
  return s == null ? null : s.substring(0, length);
}

ข้อดีอย่างหนึ่งคือฉันไม่ได้ทดสอบวิธีดังกล่าว :-)


1

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

   public class BusinessService
   {

        public Guid CreateItem(Item newItem, Guid userID, Guid ownerID)
        {
            var newItemId = itemsRepository.Create(createItem, userID, ownerID);
            **var searchItem = ItemsProcessor.SplitItem(newItem);**
            searchRepository.Add(searchItem);
            return newItemId;
        }
    }

คุณเห็นวิธีการแบบคงที่เรียกว่าItemsProcessor.SplitItem(newItem);มันทำให้เกิดกลิ่น

  • คุณไม่ได้ประกาศการพึ่งพาอย่างชัดเจนและหากคุณไม่ได้เจาะลึกลงไปในโค้ดคุณอาจมองข้ามการเชื่อมต่อระหว่างคลาสของคุณกับคอนเทนเนอร์เมธอดแบบคงที่
  • คุณไม่สามารถทดสอบBusinessServiceแยกจากItemsProcessor(เครื่องมือทดสอบส่วนใหญ่ไม่จำลองคลาสแบบคงที่) และทำให้การทดสอบหน่วยเป็นไปไม่ได้ ไม่มีการทดสอบหน่วย == คุณภาพต่ำ

0

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

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