สิ่งนี้จะถูกโปรแกรมใน non-OO ได้อย่างไร? [ปิด]


11

การอ่านบทความที่เหยียดหยามเกี่ยวกับข้อเสียของ OOP เพื่อสนับสนุนกระบวนทัศน์อื่น ๆ ที่ฉันพบเจอตัวอย่างที่ฉันไม่สามารถหาข้อผิดพลาดได้มากเกินไป

ฉันต้องการที่จะเปิดให้มีการโต้แย้งของผู้เขียนและแม้ว่าฉันสามารถเข้าใจประเด็นทางทฤษฎีของพวกเขาตัวอย่างหนึ่งโดยเฉพาะอย่างยิ่งฉันมีเวลายากที่จะลองจินตนาการว่ามันจะนำมาใช้ที่ดีขึ้นในการพูดภาษา FP

จาก: http://www.smashcompany.com/technology/object-oriented-programming-is-an- ราคา-disaster-which-must-end

// Consider the case where “SimpleProductManager” is a child of
// “ProductManager”:

public class SimpleProductManager implements ProductManager {
    private List products;

    public List getProducts() {
        return products;
    }

    public void increasePrice(int percentage) {
        if (products != null) {
            for (Product product : products) {
                double newPrice = product.getPrice().doubleValue() *
                (100 + percentage)/100;
                product.setPrice(newPrice);
            }
        }
    }

    public void setProducts(List products) {
        this.products = products;
    }
}

// There are 3 behaviors here:

getProducts()

increasePrice()

setProducts()

// Is there any rational reason why these 3 behaviors should be linked to
// the fact that in my data hierarchy I want “SimpleProductManager” to be
// a child of “ProductManager”? I can not think of any. I do not want the
// behavior of my code linked together with my definition of my data-type
// hierarchy, and yet in OOP I have no choice: all methods must go inside
// of a class, and the class declaration is also where I declare my
// data-type hierarchy:

public class SimpleProductManager implements ProductManager

// This is a disaster.

โปรดทราบว่าฉันไม่ได้มองหาการโต้แย้งหรือคัดค้านข้อโต้แย้งของผู้เขียนสำหรับ "มีเหตุผลใดเหตุผลว่าทำไม 3 พฤติกรรมเหล่านี้ควรเชื่อมโยงกับลำดับชั้นข้อมูล?"

สิ่งที่ฉันถามโดยเฉพาะคือตัวอย่างนี้จะเป็นตัวอย่าง / โปรแกรมในภาษา FP อย่างไร (รหัสจริงไม่ใช่ในทางทฤษฎี)


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

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

20
ฉันได้ประโยค 10 ข้อไปสู่การพูดจาโผงผางของบทความและยอมแพ้ ไม่สนใจผู้ชายที่อยู่หลังผ้าม่านนั้น ในข่าวอื่น ๆ ฉันไม่รู้ว่า True Scotsmen เป็นโปรแกรมเมอร์ OOP เป็นหลัก
Robert Harvey

11
อีกคำโม้จากคนที่เขียนรหัสขั้นตอนในภาษา OO แล้วสงสัยว่าทำไม OO ไม่ทำงานสำหรับเขา
TheCatWhisperer

11
แม้ว่ามันจะเป็นความจริงอย่างไม่ต้องสงสัยเลยว่า OOP เป็นหายนะของการออกแบบนับตั้งแต่เริ่มต้นจนจบ - และฉันภูมิใจที่ได้เป็นส่วนหนึ่งของมัน! - บทความนี้อ่านไม่ได้และตัวอย่างที่คุณให้นั้นเป็นการโต้แย้งว่าลำดับชั้นของคลาสที่ออกแบบไม่ดีนั้นได้รับการออกแบบมาไม่ดี
Eric Lippert

คำตอบ:


42

ในรูปแบบ FP Productจะเป็นคลาสที่ไม่เปลี่ยนรูปproduct.setPriceจะไม่กลายพันธุ์Productวัตถุ แต่จะส่งคืนวัตถุใหม่แทนและincreasePriceฟังก์ชันจะเป็นฟังก์ชัน "สแตนด์อโลน" การใช้ไวยากรณ์ที่คล้ายกันเช่นคุณ (C # / Java ชอบ) ฟังก์ชั่นเทียบเท่าอาจมีลักษณะเช่นนี้:

 public List increasePrice(List products, int percentage) {
    if (products != null) {
        return products.Select(product => {
                double newPrice = product.getPrice().doubleValue() *
                    (100 + percentage)/100;
                return product.setPrice(newPrice);     
               });
    }
    else return null;
}

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


7
วิธีในการทำให้ "FP มากกว่านี้": 1) ใช้บางที / เป็นตัวเลือกแทนความสามารถในการเขียนฟังก์ชั่นทั้งหมดแทนฟังก์ชั่นบางส่วนและใช้ฟังก์ชันตัวช่วยเรียงลำดับที่สูงขึ้นเพื่อทำให้นามธรรมหายไป "if (x! = null)" ตรรกะ. 2) ใช้เลนส์เพื่อกำหนดราคาที่เพิ่มขึ้นสำหรับผลิตภัณฑ์เดียวในแง่ของการใช้เปอร์เซ็นต์การเพิ่มขึ้นในบริบทของเลนส์กับราคาของผลิตภัณฑ์ 3) ใช้แอปพลิเคชั่น / องค์ประกอบ / การแกงบางส่วนเพื่อหลีกเลี่ยงแลมบ์ดาที่ชัดเจนสำหรับแผนที่ / เลือกการโทร
แจ็ค

6
ต้องบอกว่าฉันเกลียดความคิดของคอลเลกชันอาจเป็นโมฆะแทนที่จะว่างเปล่าโดยการออกแบบ ภาษาที่ใช้งานได้พร้อมด้วยการสนับสนุน tuple / คอลเล็กชันดั้งเดิมทำงานในลักษณะนั้น แม้ใน OOP ฉันเกลียดการกลับไปnullที่ซึ่งคอลเล็กชันเป็นประเภทส่งคืน / คุยโวมากกว่า
Berin Loritsch

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

@ Mark: แน่นอนและฉันคิดว่า OP รู้เรื่องนี้อยู่แล้ว ฉันเข้าใจคำถามว่า "วิธีการแสดงสิ่งนี้ในลักษณะที่ใช้งานได้" ไม่ใช่ข้อบังคับในภาษาที่ไม่ใช่ OOP
Doc Brown

@Mark FP และ OO ไม่แยกผู้อื่น
Pieter B

17

สิ่งที่ฉันถามโดยเฉพาะคือตัวอย่างนี้จะเป็นตัวอย่าง / โปรแกรมในภาษา FP อย่างไร (รหัสจริงไม่ใช่ในทางทฤษฎี)

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

(mapcar (lambda (x) (* x 2)) '(1 2 3))

ไปแล้ว ภาษาอื่นจะคล้ายกันโดยความแตกต่างที่คุณจะได้รับประโยชน์จากประเภทที่ชัดเจนด้วยความหมาย "การจับคู่" ที่ใช้งานได้ตามปกติ ลองดู Haskell:

incPrice :: (Num) -> [Num] -> [Num]  
incPrice _ [] = []  
incPrice percentage (x:xs) = x*percentage : incPrice percentage xs  

(หรืออะไรทำนองนั้นมันมีอายุมาแล้ว ... )

ฉันต้องการที่จะเปิดให้มีการโต้แย้งของผู้เขียน

ทำไม? ฉันพยายามอ่านบทความ; ฉันต้องยอมแพ้หลังจากหน้าและสแกนส่วนที่เหลืออย่างรวดเร็ว

ปัญหาของบทความไม่ใช่ว่าเป็นเรื่องของ OOP ฉันไม่ใช่ "pro OOP" แบบสุ่ม ๆ ฉันได้ตั้งโปรแกรมด้วยกระบวนทัศน์ทางตรรกะการทำงานและ OOP บ่อยครั้งในภาษาเดียวกันเมื่อเป็นไปได้และบ่อยครั้งที่ไม่มีสามสิ่งใด ๆ จำเป็นอย่างแท้จริงหรือแม้กระทั่งในระดับแอสเซมเบลอร์ ฉันจะไม่พูดว่ากระบวนทัศน์ใด ๆ เหล่านั้นยิ่งใหญ่กว่าสิ่งอื่นในทุกแง่มุม ฉันจะเถียงว่าฉันชอบภาษา X มากกว่า Y ใช่ไหม แน่นอนฉันต้องการ! แต่นั่นไม่ใช่สิ่งที่บทความนั้นเกี่ยวกับ

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

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


4
"ชัดเจนอย่างล้นเหลือว่าเขาไม่มีความสนใจในการอภิปรายเขาอยู่ในสงครามครูเสด" มี upvote สำหรับอัญมณีนี้
ร่าเริง

คุณไม่ต้องการข้อ จำกัด เกี่ยวกับตัวเลขในรหัส Haskell ของคุณใช่ไหม คุณจะโทรหา (*) เป็นอย่างอื่นได้อย่างไร
jk

@jk. มันมีอายุมานานแล้วที่ฉันได้ Haskell นั่นเป็นเพียงเพื่อสนองความต้องการของ OP สำหรับคำตอบที่เขามองหา ;) หากมีคนต้องการแก้ไขรหัสของฉันรู้สึกฟรี แต่แน่นอนฉันจะเปลี่ยนเป็น Num
AnoE

7

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

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

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

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

แต่เดี๋ยวก่อนคุณสามารถมีคอลเลกชันและมวลรวมของบางประเภท: ตั้งค่า [หมวดหมู่], (รหัสส่วนลด -> ราคา), (ปริมาณ -> จำนวนส่วนลด) และอื่น ๆ สิ่งเหล่านี้เหมาะสมกับอะไร? เราสร้างแยกCategoryManagerเพื่อติดตามหมวดหมู่ที่แตกต่างกันทั้งหมดหรือไม่หรือความรับผิดชอบนั้นเป็นของCategoryชั้นเรียนที่เราสร้างไว้แล้วหรือไม่?

ตอนนี้ฟังก์ชั่นเกี่ยวกับฟังก์ชั่นที่ให้ส่วนลดราคาถ้าคุณมีรายการจำนวนหนึ่งจากสองหมวดหมู่ที่ต่างกัน นั่นไปในProductชั้นCategoryเรียนDiscountRuleคลาสCategoryManagerห้องเรียนหรือเราต้องการอะไรใหม่ ๆ หรือไม่? DiscountRuleProductCategoryFactoryBuilderนี่คือวิธีการที่เราจบลงด้วยสิ่งที่ชอบ

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

def mapPrices(f: Int => Int)(products: Traversable[Product]): Traversable[Product] =
  products map {x => x.copy(price = f(x.price))}

def increasePrice(percentage: Int)(price: Int): Int =
  price * (percentage + 100) / 100

mapPrices(increasePrice(25))(products)

ฉันอาจจะเพิ่มฟังก์ชั่นราคาอื่น ๆ ที่เกี่ยวข้องที่นี่เหมือนdecreasePrice, applyBulkDiscountฯลฯ

เนื่องจากเรายังใช้คอลเลกชันProductsรุ่น OOP จึงจำเป็นต้องมีวิธีการในการจัดการคอลเลกชันนั้น แต่คุณไม่ต้องการให้โมดูลนี้เกี่ยวกับการเลือกผลิตภัณฑ์คุณต้องการให้เป็นราคา การเชื่อมต่อข้อมูล - ฟังก์ชั่นบังคับให้คุณโยนแผ่นการจัดการคอลเลกชันในนั้นด้วย

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


2

เพียงแค่แยกข้อมูลและฟังก์ชั่นในขณะที่ผู้เขียนกำลังทำให้ดูเหมือนจะเป็นเช่นนี้ใน F # ("ภาษา FP")

module Product =

    type Product = {
        Price : decimal
        ... // other properties not mentioned
    }

    let increasePrice ( percentage : int ) ( product : Product ) : Product =
        let newPrice = ... // calculate

        { product with Price = newPrice }

คุณสามารถทำการเพิ่มราคาในรายการผลิตภัณฑ์ด้วยวิธีนี้

let percentage = 10
let products : Product list = ...  // load?

products
|> List.map (Product.increasePrice percentage)

หมายเหตุ: หากคุณไม่คุ้นเคยกับ FP ทุกฟังก์ชั่นจะส่งกลับค่า มาจากภาษาที่เหมือน C คุณสามารถใช้ประโยคสุดท้ายในฟังก์ชั่นราวกับว่ามันreturnอยู่ตรงหน้า

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

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


1

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

นี่คือ In Typescript (ดังนั้นจึงมีคำอธิบายประกอบประเภททั้งหมด) typescript (เช่น javascript) เป็นภาษาที่มีหลายโดเมน

export class Product extends Object {
    name: string;
    price: number;
    category: string;
}

products: Product[] = [
    new Product( { name: "Tablet", "price": 20.99, category: 'Electronics' } ),
    new Product( { name: "Phone", "price": 500.00, category: 'Electronics' } ),
    new Product( { name: "Car", "price": 13500.00, category: 'Auto' } )
];

// find all electronics and double their price
let newProducts = products
    .filter( ( product: Product ) => product.category === 'Electronics' )
    .map( ( product: Product ) => {
        product.price *= 2;
        return product;
    } );

console.log( newProducts );

ในรายละเอียด (และอีกครั้งไม่ใช่ผู้เชี่ยวชาญของ FP) สิ่งที่ต้องเข้าใจคือมีพฤติกรรมที่กำหนดไว้ล่วงหน้าไม่มาก ไม่มีวิธี "เพิ่มราคา" ที่ใช้การเพิ่มราคาในรายการทั้งหมดเนื่องจากแน่นอนว่าไม่ใช่ OOP: ไม่มีคลาสที่จะกำหนดพฤติกรรมดังกล่าว แทนที่จะสร้างวัตถุที่เก็บรายการผลิตภัณฑ์คุณเพียงแค่สร้างอาร์เรย์ของผลิตภัณฑ์ จากนั้นคุณสามารถใช้โพรซีเดอร์ FP มาตรฐานเพื่อจัดการอาเรย์นี้ในแบบที่คุณต้องการ: กรองเพื่อเลือกรายการเฉพาะแผนที่เพื่อปรับเปลี่ยนภายใน ฯลฯ ... คุณจบลงด้วยการควบคุมรายละเอียดของรายการผลิตภัณฑ์โดยไม่ต้องถูก จำกัด โดย API ที่ SimpleProductManager ให้คุณ นี่อาจเป็นข้อได้เปรียบโดยบางคน มันก็เป็นความจริงเช่นกันว่าคุณไม่ได้ ไม่ต้องกังวลกับสัมภาระใด ๆ ที่เกี่ยวข้องกับคลาส ProductManager ท้ายที่สุดไม่ต้องกังวลกับ "SetProducts" หรือ "GetProducts" เนื่องจากไม่มีวัตถุที่ซ่อนผลิตภัณฑ์ของคุณ: คุณเพียงแค่มีรายการผลิตภัณฑ์ที่คุณใช้งานอยู่ อีกครั้งนี่อาจเป็นข้อได้เปรียบหรือเสียเปรียบทั้งนี้ขึ้นอยู่กับสถานการณ์ / บุคคลที่คุณกำลังคุยด้วย นอกจากนี้ยังเห็นได้ชัดว่าไม่มีลำดับชั้นของชั้นเรียน (ซึ่งเป็นสิ่งที่เขาบ่นเกี่ยวกับ) เพราะไม่มีชั้นเรียนในสถานที่แรก นี่อาจเป็นข้อได้เปรียบหรือเสียเปรียบทั้งนี้ขึ้นอยู่กับสถานการณ์ / บุคคลที่คุณกำลังคุยด้วย นอกจากนี้ยังเห็นได้ชัดว่าไม่มีลำดับชั้นของชั้นเรียน (ซึ่งเป็นสิ่งที่เขาบ่นเกี่ยวกับ) เพราะไม่มีชั้นเรียนในสถานที่แรก นี่อาจเป็นข้อได้เปรียบหรือเสียเปรียบทั้งนี้ขึ้นอยู่กับสถานการณ์ / บุคคลที่คุณกำลังคุยด้วย นอกจากนี้ยังเห็นได้ชัดว่าไม่มีลำดับชั้นของชั้นเรียน (ซึ่งเป็นสิ่งที่เขาบ่นเกี่ยวกับ) เพราะไม่มีชั้นเรียนในสถานที่แรก

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

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

** หมายเหตุ: เห็นได้ชัดว่ามีชั้นเรียนหนึ่งในตัวอย่างของฉัน: ระดับสินค้า ในกรณีนี้มันเป็นเพียง data container ที่โง่เง่า: ฉันไม่คิดว่าการใช้มันจะเป็นการละเมิดหลักการของ FP เป็นผู้ช่วยในการตรวจสอบประเภทมากกว่า

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


2
นี่ไม่ใช่ตัวอย่าง OOP จริง ๆ ในความรู้สึกแบบคลาสสิก ใน OOP จริงข้อมูลจะถูกรวมเข้ากับพฤติกรรม ที่นี่คุณแยกทั้งสอง มันไม่จำเป็นต้องเป็นสิ่งเลวร้าย (จริง ๆ แล้วฉันพบว่ามันสะอาดกว่า) แต่ไม่ใช่สิ่งที่ฉันจะเรียกว่า OOP แบบคลาสสิก
Robert Harvey

0

ดูเหมือนว่าฉันจะไม่เห็นว่า SimpleProductManager เป็นลูก (ขยายหรือสืบทอด) ของบางสิ่งบางอย่าง

การติดตั้ง ProductManager เพียงอย่างเดียวซึ่งเป็นสัญญาที่กำหนดสิ่งที่การกระทำ (พฤติกรรม) วัตถุต้องทำ

ถ้ามันจะเป็นเด็ก (หรือดีกว่ากล่าวว่าคลาสที่สืบทอดหรือคลาสที่ขยายการทำงานของคลาสอื่น) มันจะถูกเขียนเป็น:

class SimpleProductManager extends ProductManager {
    ...
}

ดังนั้นโดยทั่วไปผู้เขียนพูดว่า:

มีวัตถุบางอย่างที่พฤติกรรม: setProducts, เพิ่มราคา, getProducts และเราไม่สนใจว่าวัตถุนั้นมีพฤติกรรมอื่นหรือไม่

คลาส SimpleProductManager ใช้งาน โดยพื้นฐานแล้วมันดำเนินการกระทำ

มันอาจจะเรียกว่า PercentagePriceIncreaser เนื่องจากพฤติกรรมหลักคือการเพิ่มราคาด้วยค่าเปอร์เซ็นต์

แต่เราสามารถนำคลาสอื่นมาใช้: ValuePriceIncreaser ซึ่งพฤติกรรมจะเป็น:

public void increasePrice(int number) {
    if (products != null) {
        for (Product product : products) {
            double newPrice = product.getPrice() + number;
            product.setPrice(newPrice);
        }
    }
}

จากมุมมองภายนอกไม่มีอะไรเปลี่ยนแปลงอินเทอร์เฟซเหมือนกันยังคงมีสามวิธีเดียวกัน แต่ลักษณะการทำงานแตกต่างกัน

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

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