Lập trình hướng đối tượng trong ngôn ngữ hướng đối tượng [đã đóng]


15

Gần đây tôi được giao một nhiệm vụ tạo ra một máy tính với các hàm cộng, trừ, nhân, chia và sức mạnh bằng cách sử dụng Lập trình hướng đối tượng . Tôi đã hoàn thành nhiệm vụ này. Tuy nhiên, sau đó tôi đã lập trình lại toàn bộ chương trình mà không sử dụng kỹ thuật / phương pháp Hướng đối tượng .

Điều tôi nhận thấy rằng độ dài mã của tôi đã giảm khá đáng kể và nó khá dễ hiểu. Vì vậy, câu hỏi của tôi ở đây là khi nào tôi nên sử dụng lập trình hướng đối tượng? Có thể tạo chương trình mà không có Định hướng đối tượng trong Ngôn ngữ hướng đối tượng không? Vui lòng giúp tôi ra cái này

PS: Tôi không yêu cầu ở đây nói cho tôi biết giá trị của Lập trình hướng đối tượng so với lập trình thủ tục.


12
Hoàn toàn không có lý do để tránh áp dụng các kỹ thuật khác nhau khi cần thiết. Bạn là lập trình viên sẽ cần cân nhắc ưu và nhược điểm trong từng trường hợp. Khá thường xuyên nó đi xuống phong cách cá nhân.
ChaosPandion

3
Tôi chưa bao giờ có vấn đề. Ngôn ngữ gần như luôn luôn là một công cụ theo quy định được đưa ra cho nhóm và / hoặc kiến ​​trúc khác.


8
Thực hiện cùng một chương trình có và không có kỹ thuật OO là một bài tập tốt để học một cái gì đó, tôi không thể hiểu tại sao một số người ở đây dường như từ chối điều này hoặc hạ thấp bạn. Nhưng vấn đề với câu hỏi của bạn là nó đã được hỏi ở đây hơn một lần, dưới các hình thức khác nhau. Và mặc dù bạn phủ nhận nó, bạn đang hỏi về giá trị của Lập trình hướng đối tượng so với lập trình thủ tục. Và C ++ không phải là ngôn ngữ OO, nó là ngôn ngữ lai.
Doc Brown

3
Thêm một tính năng hiển thị công thức bạn đã nhập và sau đó thêm hàm căn bậc hai (Đừng làm điều này trước, đó sẽ là gian lận.) Và cho chúng tôi biết suy nghĩ của bạn.
JeffO

Câu trả lời:


25

C ++ không phải là "chỉ" một ngôn ngữ OO, nó là một ngôn ngữ đa mô hình. Vì vậy, nó cho phép bạn quyết định hoặc chống lại lập trình OO hoặc trộn cả hai. Sử dụng các kỹ thuật OO sẽ thêm cấu trúc vào chương trình của bạn - từ đó bạn sẽ được hưởng lợi khi chương trình của bạn đạt đến một kích thước hoặc độ phức tạp nhất định. Cấu trúc bổ sung này, tuy nhiên, đi kèm với giá của các dòng mã bổ sung. Vì vậy, đối với các chương trình "nhỏ", cách tốt nhất thường là triển khai chúng theo kiểu không OO trước và thêm ngày càng nhiều kỹ thuật OO sau khi chương trình bắt đầu phát triển qua nhiều năm (điều này có thể sẽ không xảy ra với "tập thể dục "Các chương trình, nhưng là vòng đời điển hình cho rất nhiều chương trình kinh doanh).

Phần khó khăn là không bỏ lỡ thời điểm khi sự phức tạp của chương trình của bạn đạt đến kích thước đòi hỏi nhiều cấu trúc hơn. Nếu không, bạn sẽ kết thúc với một đống mã spaghetti khổng lồ.


Nếu các chương trình "tập thể dục" đơn giản bắt đầu phát triển, cách tốt nhất là thực hiện nó theo cách mà nó có thể được thực hiện lại sau đó. Cảm ơn bạn đã chia sẻ điều đó :) +1
FaizanRabbani

@CarlSmith: hoàn toàn. Nhưng khi tôi viết câu trả lời của mình, tôi đã cố gắng tập trung vào điểm và thang điểm của câu hỏi thực tế.
Doc Brown

10

Làm thế nào để các lập trình viên chuyên nghiệp đưa ra phán quyết kêu gọi có nên đi OOP hay không? Nó sẽ thực sự hữu ích cho tôi.

Đối với tôi, có hai điểm quyết định. Đầu tiên, đôi khi nó sẽ rõ ràng ngay từ đầu. Sẽ có rất nhiều loại tương tự mà tất cả đều chia sẻ các phương thức phổ biến khác nhau rộng rãi trong chi tiết triển khai của chúng. Ví dụ, tôi đang xây dựng một hệ thống quy trình công việc và tôi cần khả năng thực hiện các nhiệm vụ tùy ý. Để chạy tác vụ, tôi đã triển khai một lớp cơ sở mà mỗi tác vụ được kế thừa từ đó, với một Execute()phương thức trừu tượng. Các lớp kế thừa đã cung cấp việc thực hiện, nhưng hệ thống dòng công việc có thể bắt đầu thực thi mà không biết gì về loại nhiệm vụ nào đang được chạy.

Hầu hết các dự án không phải là rõ ràng mặc dù. Điểm quyết định thứ hai là khi một tập hợp con của dự án đã phát triển thành một mớ lớn các câu lệnh if-then hoặc câu lệnh chuyển đổi và đặc biệt là khi các câu lệnh if-then đó yêu cầu rất nhiều mã thiết lập để chạy chính xác. Tôi cảm thấy bản thân bắt đầu mất logic của những gì tôi đang cố gắng thực hiện và mã bắt đầu cảm thấy mong manh. Tại thời điểm đó, thường là một dấu hiệu cho thấy đã đến lúc cấu trúc lại mã thành các lớp cơ sở với các triển khai cụ thể.

Một phần lớn của việc chuyển sang một phong cách hướng đối tượng trái ngược với phong cách chức năng là chuyển đổi các câu lệnh if-then thành các câu lệnh "chạy hành động này". Thay vì một tập hợp các câu lệnh if-then khổng lồ, bạn chỉ cần nói mã để chạy hành động của nó. Hành động nào thực sự được chạy phụ thuộc vào việc triển khai bạn cung cấp.

Ví dụ: đây là kiểu chức năng trong mã giả kiểu C #:

if ( action == "email" ) { 
    callEmailFunction(userInfo);
}
else if ( action == "sms" ) { 
    callSmsFunction(userInfo);
}
else if ( action == "web" ) { 
    endpoint = "http://127.0.0.1/confirm";
    confirmWeb(endpoint, userinfo);
} 
...

Nhưng có lẽ bạn có thể viết lại nó thành một cái gì đó như thế này:

interface IConfirmable {
    void Confirm(UserInfo userinfo);
}

public class ConfirmEmail : IConfirmable { 
    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via email
    }
}

public class ConfirmSms : IConfirmable { 
    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via email
    }
}

public class ConfirmWeb : IConfirmable { 
    // this is a constructor
    public ConfirmWeb(string endpoint) { 
        ...
    }

    public void Confirm(UserInfo userinfo) {
        // do the appropriate thing to confirm via web
    }
} 

Và sau đó là mã:

// An implementation that decides which implementation of the base class to use
// This replaces the if-then statements in the functional programmming.
IConfirmable confirmer = ConfirmerFactory.GetConfirmer();

// get the userinfo however you get it, 
// which would be the same way you get it in the functional example.
UserInfo userinfo = ...;

// perform the action.
confirmer.Confirm(userinfo);

Bây giờ, khi có rất ít mã bên trong if-then, điều này có vẻ như rất nhiều công việc không nhận được lợi ích. Và khi có rất ít mã trong if-then, điều đó là chính xác: đó là rất nhiều công việc cho mã khó hiểu hơn.

Nhưng phong cách hướng đối tượng thực sự tỏa sáng khi bạn có nhiều hơn một hành động chứ không chỉ là Confirm()phương thức cần được thực hiện. Có thể bạn có một thói quen khởi tạo, ba hoặc nhiều phương thức hành động có thể chạy và một Cleanup()phương thức. Thuật toán cơ sở là giống hệt nhau, ngoại trừ nó thực hiện các cuộc gọi của nó vào các đối tượng thích hợp thực hiện một lớp cơ sở chung. Bây giờ bạn bắt đầu thấy một lợi ích thực sự cho các đối tượng theo phong cách theo định hướng: các thuật toán cơ bản là nhiều dễ đọc hơn nếu nó được kiểm tra if-then báo cáo tại mỗi bước của con đường.


+1 để phân tích chi tiết. :) Tôi có vài suy nghĩ về điều này.
FaizanRabbani

1
Ngoài ra: vui lòng ngừng đăng bình luận "cảm ơn" trên mỗi câu trả lời. Chúng tôi muốn tập trung vào chỉ câu hỏi và câu trả lời, không thảo luận.
Philip Kendall

5
Ví dụ đó là cấp bách hơn chức năng.
OrangeDog


1
Chỉ cần một lưu ý, khi bạn nghiêng về một loạt các câu lệnh if / other hoặc switch, luôn luôn là một tùy chọn để xem xét một số loại bảng tìm kiếm. Vì vậy, một cách khác để viết lại theo dòng var dict = new Dictionary<string,Action<UserInfo>{ { "email", callEmailFunction }, { "sms", callSmsFunction } }; dict[ action ]( userInfo );(dict có thể là tĩnh, xử lý lỗi bị bỏ qua)
stijn

3

Có, việc sử dụng mã kiểu cũ là hoàn toàn bình thường, miễn là phạm vi dự án của bạn được biết đến hoặc bị giới hạn. Nếu bạn có kế hoạch mở rộng chương trình hoặc dự án của bạn thì OOP là một cách để đi, bởi vì bạn có thể duy trì và mở rộng mã của mình một cách liền mạch, mặt khác nếu bạn lập kế hoạch và đã đưa ra kết luận rằng bạn sẽ không bao giờ lên kế hoạch mở rộng dự án bạn thực hiện sau đó viết mã mà không có OOP sẽ đủ. Điều đó không có nghĩa là nếu bạn sử dụng phương pháp không OOP, bạn không bao giờ có thể nâng cấp dự án của mình nhưng đó sẽ là một việc tẻ nhạt. OOP là để giúp chúng ta hình dung khái niệm của chúng ta như thể đó là một sinh vật thực sự bởi vì chúng ta hiểu những điều đó tốt hơn bất cứ điều gì khác.


1
"Điều đó không có nghĩa là nếu bạn sử dụng phương pháp không OOP, bạn không bao giờ có thể nâng cấp dự án của mình nhưng đó sẽ là một việc tẻ nhạt.": OOP giúp mở rộng dự án của bạn khi hầu hết các tiện ích mở rộng liên quan đến việc thêm các lớp mới (ví dụ: thêm các widget mới vào GUI). Khi hầu hết các phần mở rộng liên quan đến việc thêm các hoạt động mới, thì một thiết kế thủ tục có thể hiệu quả hơn.
Giorgio

1
Từ khi nào "không hướng đối tượng" được gọi là "kiểu cũ"?
DanielSank
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.