Python 3 có phải là lỗi không?

Fulfillment by Amazon [FBA] là dịch vụ mà chúng tôi cung cấp cho người bán để họ có thể lưu trữ sản phẩm của mình tại các trung tâm hoàn thiện đơn hàng của Amazon và chúng tôi trực tiếp đóng gói, vận chuyển và cung cấp dịch vụ khách hàng cho những sản phẩm này. Một cái gì đó chúng tôi hy vọng bạn sẽ đặc biệt thích. Các mặt hàng FBA đủ điều kiện để được Giao hàng MIỄN PHÍ và Amazon Prime

Nếu bạn là người bán, Fulfillment by Amazon có thể giúp bạn phát triển doanh nghiệp của mình. Tìm hiểu thêm về chương trình

Trong phát triển phần mềm, thiết kế thường được coi là bước thực hiện trước khi lập trình. Điều này không đúng; . Trong chương này, chúng ta sẽ đề cập đến các chủ đề sau

  • hướng đối tượng nghĩa là gì
  • Sự khác biệt giữa thiết kế hướng đối tượng và lập trình hướng đối tượng
  • Các nguyên tắc cơ bản của thiết kế hướng đối tượng
  • Ngôn ngữ mô hình hóa thống nhất cơ bản [UML] và khi nó không xấu
 

Giới thiệu hướng đối tượng

Mọi người đều biết đối tượng là gì. một thứ hữu hình mà chúng ta có thể cảm nhận, cảm nhận và thao tác. Những đồ vật đầu tiên chúng ta tương tác thường là đồ chơi trẻ em. Các khối gỗ, hình dạng bằng nhựa và các mảnh ghép quá khổ là những đồ vật đầu tiên phổ biến. Em bé học nhanh rằng một số đồ vật làm những việc nhất định. chuông reo, các nút được nhấn và đòn bẩy được kéo

Định nghĩa của một đối tượng trong phát triển phần mềm không quá khác biệt. Các đối tượng phần mềm có thể không phải là những thứ hữu hình mà bạn có thể nhặt, cảm nhận hoặc cảm nhận được, nhưng chúng là những mô hình của một thứ gì đó có thể thực hiện một số việc nhất định và hoàn thành một số việc nhất định đối với chúng. Chính thức, một đối tượng là một tập hợp dữ liệu và các hành vi liên quan

Vì vậy, biết đối tượng là gì, hướng đối tượng có nghĩa là gì? . Vì vậy, hướng đối tượng có nghĩa là hướng chức năng vào các đối tượng mô hình hóa. Đây là một trong nhiều kỹ thuật được sử dụng để mô hình hóa các hệ thống phức tạp. Nó được định nghĩa bằng cách mô tả một tập hợp các đối tượng tương tác thông qua dữ liệu và hành vi của chúng

Nếu bạn đã đọc bất kỳ lời quảng cáo nào, có lẽ bạn đã bắt gặp các thuật ngữ phân tích hướng đối tượng, thiết kế hướng đối tượng, phân tích và thiết kế hướng đối tượng và lập trình hướng đối tượng. Đây đều là những khái niệm có liên quan chặt chẽ với nhau dưới cái ô hướng đối tượng chung

Trên thực tế, phân tích, thiết kế và lập trình đều là các giai đoạn phát triển phần mềm. Gọi chúng là hướng đối tượng chỉ đơn giản là xác định mức độ phát triển phần mềm đang được theo đuổi

Phân tích hướng đối tượng [OOA] là quá trình xem xét một vấn đề, hệ thống hoặc tác vụ [mà ai đó muốn biến thành một ứng dụng] và xác định các đối tượng cũng như tương tác giữa các đối tượng đó. Giai đoạn phân tích là tất cả về những gì cần phải được thực hiện

Đầu ra của giai đoạn phân tích là một tập hợp các yêu cầu. Nếu chúng tôi hoàn thành giai đoạn phân tích trong một bước, chúng tôi sẽ biến một nhiệm vụ, chẳng hạn như tôi cần một trang web, thành một tập hợp các yêu cầu. Ví dụ, đây hoặc một số yêu cầu về những gì khách truy cập trang web có thể cần làm [in nghiêng thể hiện hành động, in đậm thể hiện đối tượng]

  • Xem lại lịch sử của chúng tôi
  • Ứng tuyển công việc
  • Duyệt, so sánh và đặt hàng sản phẩm

Theo một số cách, phân tích là cách gọi sai. Em bé mà chúng ta đã thảo luận trước đó không phân tích các khối và mảnh ghép. Thay vào đó, cô ấy khám phá môi trường của mình, điều khiển các hình dạng và xem chúng có thể phù hợp ở đâu. Một cách diễn đạt tốt hơn có thể là khám phá hướng đối tượng. Trong phát triển phần mềm, các giai đoạn phân tích ban đầu bao gồm phỏng vấn khách hàng, nghiên cứu quy trình của họ và loại bỏ các khả năng

Thiết kế hướng đối tượng [OOD] là quá trình chuyển đổi các yêu cầu đó thành một đặc tả triển khai. Người thiết kế phải đặt tên cho các đối tượng, xác định các hành vi và chỉ định chính thức đối tượng nào có thể kích hoạt các hành vi cụ thể trên các đối tượng khác. Giai đoạn thiết kế là tất cả về cách mọi thứ nên được thực hiện

Đầu ra của giai đoạn thiết kế là một đặc tả thực hiện. Nếu chúng ta hoàn thành giai đoạn thiết kế trong một bước duy nhất, chúng ta sẽ biến các yêu cầu được xác định trong quá trình phân tích hướng đối tượng thành một tập hợp các lớp và giao diện có thể được triển khai [lý tưởng] trong bất kỳ ngôn ngữ lập trình hướng đối tượng nào.

Lập trình hướng đối tượng [OOP] là quá trình chuyển đổi thiết kế được xác định hoàn hảo này thành một chương trình hoạt động thực hiện chính xác những gì Giám đốc điều hành yêu cầu ban đầu

Vâng, đúng. Sẽ thật tuyệt nếu thế giới đáp ứng được lý tưởng này và chúng ta có thể lần lượt theo dõi các giai đoạn này, theo thứ tự hoàn hảo, giống như tất cả các sách giáo khoa cũ đã bảo chúng ta. Như thường lệ, thế giới thực âm u hơn nhiều. Cho dù chúng ta có cố gắng tách biệt các giai đoạn này thế nào đi chăng nữa, chúng ta sẽ luôn tìm thấy những thứ cần phân tích sâu hơn trong khi thiết kế. Khi chúng tôi đang lập trình, chúng tôi tìm thấy các tính năng cần làm rõ trong thiết kế

Hầu hết sự phát triển của thế kỷ 21 diễn ra theo mô hình phát triển lặp đi lặp lại. Trong quá trình phát triển lặp lại, một phần nhỏ của nhiệm vụ được mô hình hóa, thiết kế và lập trình, sau đó chương trình được xem xét và mở rộng để cải thiện từng tính năng và bao gồm các tính năng mới trong một loạt các chu kỳ phát triển ngắn

Phần còn lại của cuốn sách này là về lập trình hướng đối tượng, nhưng trong chương này, chúng ta sẽ đề cập đến các nguyên tắc hướng đối tượng cơ bản trong bối cảnh thiết kế. Điều này cho phép chúng tôi hiểu các khái niệm [khá đơn giản] này mà không cần phải tranh luận với cú pháp phần mềm hoặc dấu vết của Python

 

Đối tượng và lớp

Vì vậy, một đối tượng là một tập hợp dữ liệu với các hành vi liên quan. Làm thế nào để chúng ta phân biệt giữa các loại đối tượng? . Táo và cam không được lập mô hình thường xuyên trong chương trình máy tính, nhưng hãy giả sử chúng ta đang thực hiện một ứng dụng kiểm kê cho một trang trại trái cây. Để tạo thuận lợi cho ví dụ, chúng ta có thể giả sử rằng táo được đựng trong thùng và cam được đựng trong giỏ

Bây giờ, chúng ta có bốn loại đối tượng. táo, cam, giỏ và thùng. Trong mô hình hướng đối tượng, thuật ngữ được sử dụng cho một loại đối tượng là lớp. Vì vậy, về mặt kỹ thuật, chúng ta hiện có bốn lớp đối tượng

Điều quan trọng là phải hiểu sự khác biệt giữa một đối tượng và một lớp. Lớp mô tả đối tượng. Chúng giống như bản thiết kế để tạo ra một đối tượng. Bạn có thể có ba quả cam ngồi trên bàn trước mặt bạn. Mỗi quả cam là một đối tượng riêng biệt, nhưng cả ba đều có các thuộc tính và hành vi liên quan đến một lớp. lớp chung của cam

Mối quan hệ giữa bốn lớp đối tượng trong hệ thống kiểm kê của chúng tôi có thể được mô tả bằng Ngôn ngữ mô hình hóa thống nhất [luôn được gọi là UML, vì các từ viết tắt ba chữ cái không bao giờ lỗi thời] sơ đồ lớp. Đây là sơ đồ lớp đầu tiên của chúng tôi

Biểu đồ này cho thấy một quả Cam bằng cách nào đó được liên kết với một cái Giỏ và một quả táo cũng được liên kết bằng một cách nào đó với một cái Thùng. Hiệp hội là cách cơ bản nhất để hai lớp có liên quan

UML rất phổ biến đối với các nhà quản lý và đôi khi bị các lập trình viên chê bai. Cú pháp của sơ đồ UML nói chung là khá rõ ràng; . UML cũng khá dễ vẽ và khá trực quan. Rốt cuộc, nhiều người, khi mô tả các lớp và mối quan hệ của chúng, một cách tự nhiên sẽ vẽ các hộp có các đường kẻ giữa chúng. Có một tiêu chuẩn dựa trên các sơ đồ trực quan này giúp các lập trình viên dễ dàng giao tiếp với các nhà thiết kế, người quản lý và với nhau

Tuy nhiên, một số lập trình viên cho rằng UML là một sự lãng phí thời gian. Trích dẫn sự phát triển lặp đi lặp lại, họ sẽ lập luận rằng các đặc tả chính thức được thực hiện trong các sơ đồ UML ưa thích sẽ trở nên dư thừa trước khi chúng được triển khai và việc duy trì các sơ đồ chính thức này sẽ chỉ lãng phí thời gian và không mang lại lợi ích cho bất kỳ ai.

Tùy thuộc vào cấu trúc công ty liên quan, điều này có thể đúng hoặc không. Tuy nhiên, mọi nhóm lập trình bao gồm nhiều hơn một người đôi khi sẽ phải ngồi xuống và băm nhỏ các chi tiết của hệ thống con mà họ hiện đang làm việc. UML cực kỳ hữu ích trong các phiên động não này để giao tiếp nhanh chóng và dễ dàng. Ngay cả những tổ chức chế giễu sơ đồ lớp chính thức cũng có xu hướng sử dụng một số phiên bản không chính thức của UML trong các cuộc họp thiết kế hoặc thảo luận nhóm của họ

Hơn nữa, người quan trọng nhất mà bạn sẽ phải giao tiếp là chính bạn. Tất cả chúng ta đều nghĩ rằng mình có thể nhớ những quyết định thiết kế mà mình đã đưa ra, nhưng sẽ luôn có câu hỏi Tại sao tôi lại làm như vậy? . Nếu chúng ta giữ lại những mẩu giấy mà chúng ta đã lập sơ đồ ban đầu khi bắt đầu thiết kế, thì cuối cùng chúng ta sẽ thấy chúng là một tài liệu tham khảo hữu ích

Tuy nhiên, chương này không có nghĩa là hướng dẫn về UML. Có rất nhiều trong số đó có sẵn trên internet, cũng như rất nhiều sách về chủ đề này. UML bao gồm nhiều hơn các sơ đồ lớp và đối tượng; . Chúng ta sẽ xử lý một số cú pháp sơ đồ lớp phổ biến trong phần thảo luận về thiết kế hướng đối tượng này. Bạn có thể chọn cấu trúc theo ví dụ và trong tiềm thức bạn sẽ chọn cú pháp lấy cảm hứng từ UML trong các phiên thiết kế cá nhân hoặc nhóm của riêng bạn

Biểu đồ ban đầu của chúng ta, mặc dù chính xác, nhưng không nhắc nhở chúng ta rằng táo được đựng trong thùng hay một quả táo có thể đựng bao nhiêu thùng. Nó chỉ cho chúng ta biết rằng táo bằng cách nào đó được liên kết với thùng. Mối liên hệ giữa các lớp thường rõ ràng và không cần giải thích thêm, nhưng chúng tôi có tùy chọn để làm rõ thêm nếu cần

Cái hay của UML là hầu hết mọi thứ đều không bắt buộc. Chúng ta chỉ cần xác định càng nhiều thông tin trong sơ đồ càng có ý nghĩa đối với tình huống hiện tại. Trong một phiên bảng trắng nhanh, chúng ta có thể nhanh chóng vẽ các đường giữa các hộp. Trong một tài liệu chính thức, chúng ta có thể đi vào chi tiết hơn. Trong trường hợp táo và thùng, chúng ta có thể khá tự tin rằng mối liên hệ là nhiều táo bỏ vào một thùng, nhưng để đảm bảo không ai nhầm lẫn với một quả táo làm hỏng một thùng, chúng ta có thể cải tiến biểu đồ như hình minh họa

Sơ đồ này cho chúng ta biết rằng những quả cam được đựng trong giỏ, với một mũi tên nhỏ cho biết quả cam được đựng trong những quả gì. Nó cũng cho chúng ta biết số lượng đối tượng đó có thể được sử dụng trong hiệp hội ở cả hai phía của mối quan hệ. Một Rổ có thể chứa nhiều đồ vật màu Cam [được biểu thị bằng dấu *]. Bất kỳ một quả Cam nào cũng có thể bỏ vào đúng một Giỏ. Con số này được gọi là bội số của đối tượng. Bạn cũng có thể nghe nó được mô tả là cardinality. Đây thực sự là những thuật ngữ hơi khác biệt. Số lượng đề cập đến số lượng mục thực tế trong tập hợp, trong khi bội số chỉ định mức độ nhỏ hoặc mức độ lớn của tập hợp

Đôi khi tôi quên mất đầu cuối của mối quan hệ được cho là có bội số nào. Bội số gần nhất với một lớp là số đối tượng của lớp đó có thể được liên kết với bất kỳ một đối tượng nào ở đầu kia của liên kết. Đối với quả táo nằm trong liên kết thùng, đọc từ trái sang phải, nhiều thể hiện của lớp Apple [tức là nhiều đối tượng Apple] có thể đi vào bất kỳ một Thùng nào. Đọc từ phải sang trái, chính xác một Thùng có thể được liên kết với bất kỳ Apple nào

 

Chỉ định các thuộc tính và hành vi

Bây giờ chúng ta đã nắm được một số thuật ngữ hướng đối tượng cơ bản. Đối tượng là thể hiện của các lớp có thể liên kết với nhau. Một thể hiện đối tượng là một đối tượng cụ thể với tập hợp dữ liệu và hành vi của chính nó; . Điều đó đủ đơn giản, nhưng hãy đi sâu vào ý nghĩa của hai từ đó, dữ liệu và hành vi

Dữ liệu mô tả đối tượng

Hãy bắt đầu với dữ liệu. Dữ liệu thể hiện các đặc điểm riêng của một đối tượng nhất định. Một lớp có thể định nghĩa các nhóm đặc điểm cụ thể được chia sẻ bởi tất cả các đối tượng từ lớp đó. Bất kỳ đối tượng cụ thể nào cũng có thể có các giá trị dữ liệu khác nhau cho các đặc điểm nhất định. Ví dụ, ba quả cam trên bàn của chúng ta [nếu chúng ta chưa ăn] mỗi quả có thể nặng một lượng khác nhau. Lớp màu cam có thể có thuộc tính trọng số để biểu diễn dữ liệu đó. Tất cả các thể hiện của lớp màu cam đều có thuộc tính trọng lượng, nhưng mỗi màu cam có một giá trị khác nhau cho thuộc tính này. Tuy nhiên, các thuộc tính không nhất thiết phải là duy nhất; . Ví dụ thực tế hơn, hai đối tượng đại diện cho các khách hàng khác nhau có thể có cùng giá trị cho thuộc tính tên

Các thuộc tính thường được gọi là thành viên hoặc thuộc tính. Một số tác giả gợi ý rằng các thuật ngữ có ý nghĩa khác nhau, thông thường các thuộc tính có thể thiết lập được, trong khi các thuộc tính chỉ đọc. Trong Python, khái niệm chỉ đọc khá vô nghĩa, vì vậy trong suốt cuốn sách này, chúng ta sẽ thấy hai thuật ngữ được sử dụng thay thế cho nhau. Ngoài ra, như chúng ta sẽ thảo luận trong Chương 5 , Khi Nào Sử Dụng Lập Trình Hướng Đối Tượng, từ khóa thuộc tính có một ý nghĩa đặc biệt trong Python đối với một đối tượng cụ thể. .

Trong ứng dụng kiểm kê trái cây của chúng tôi, người nông dân trồng trái cây có thể muốn biết cam đến từ vườn nào, được hái khi nào và nặng bao nhiêu. Họ cũng có thể muốn theo dõi nơi lưu trữ từng Giỏ hàng. Táo có thể có thuộc tính màu và thùng có thể có các kích cỡ khác nhau. Một số thuộc tính này cũng có thể thuộc về nhiều lớp [chúng ta cũng có thể muốn biết khi nào táo được hái], nhưng với ví dụ đầu tiên này, chúng ta hãy thêm một vài thuộc tính khác vào sơ đồ lớp của chúng ta

Tùy thuộc vào mức độ chi tiết của thiết kế, chúng tôi cũng có thể chỉ định loại cho từng thuộc tính. Các loại thuộc tính thường là các kiểu nguyên thủy là tiêu chuẩn cho hầu hết các ngôn ngữ lập trình, chẳng hạn như số nguyên, số dấu phẩy động, chuỗi, byte hoặc Boolean. Tuy nhiên, chúng cũng có thể biểu diễn các cấu trúc dữ liệu như danh sách, cây hoặc đồ thị hoặc đáng chú ý nhất là các lớp khác. Đây là một lĩnh vực mà giai đoạn thiết kế có thể trùng lặp với giai đoạn lập trình. Các nguyên hàm hoặc đối tượng khác nhau có sẵn trong một ngôn ngữ lập trình có thể khác với những gì có sẵn trong ngôn ngữ lập trình khác

Thông thường, chúng ta không cần quá quan tâm đến các loại dữ liệu ở giai đoạn thiết kế, vì các chi tiết dành riêng cho triển khai được chọn trong giai đoạn lập trình. Tên chung thường đủ cho thiết kế. Nếu thiết kế của chúng tôi yêu cầu một loại bộ chứa danh sách, các lập trình viên Java có thể chọn sử dụng LinkedList hoặc ArrayList khi triển khai nó, trong khi các lập trình viên Python [đó là chúng tôi. ] có thể chọn giữa danh sách tích hợp sẵn và bộ dữ liệu

Trong ví dụ trồng cây ăn quả của chúng tôi cho đến nay, các thuộc tính của chúng tôi đều là các thuộc tính nguyên thủy cơ bản. Tuy nhiên, có một số thuộc tính ẩn mà chúng ta có thể làm rõ—các liên kết. Đối với một quả cam nhất định, chúng ta có thể có một thuộc tính đề cập đến cái giỏ chứa quả cam đó

Hành vi là hành động

Bây giờ chúng ta đã biết dữ liệu là gì, thuật ngữ không xác định cuối cùng là hành vi. Hành vi là hành động có thể xảy ra trên một đối tượng. Các hành vi có thể được thực hiện trên một lớp đối tượng cụ thể được gọi là các phương thức. Ở cấp độ lập trình, các phương thức giống như các hàm trong lập trình có cấu trúc, nhưng chúng có quyền truy cập một cách kỳ diệu vào tất cả dữ liệu được liên kết với đối tượng này. Giống như hàm, phương thức cũng có thể nhận tham số và trả về giá trị

Các tham số của một phương thức được cung cấp cho nó dưới dạng danh sách các đối tượng cần được truyền vào phương thức đó. Các trường hợp đối tượng thực tế được truyền vào một phương thức trong một lời gọi cụ thể thường được gọi là đối số. Các đối tượng này được phương thức sử dụng để thực hiện bất kỳ hành vi hoặc tác vụ nào mà nó phải thực hiện. Giá trị trả về là kết quả của tác vụ đó

Chúng tôi đã mở rộng ví dụ so sánh táo và cam của mình thành một ứng dụng kiểm kê cơ bản [nếu hơi phức tạp]. Hãy kéo dài nó thêm một chút và xem liệu nó có bị đứt không. Một hành động có thể được liên kết với cam là hành động chọn. Nếu bạn nghĩ về việc triển khai, hãy chọn sẽ cần thực hiện hai việc

  • Đặt quả cam vào giỏ bằng cách cập nhật thuộc tính Giỏ của quả cam
  • Thêm màu cam vào danh sách Màu cam trên Giỏ đã cho

Vì vậy, pick cần biết nó đang giao dịch với rổ nào. Chúng tôi làm điều này bằng cách cung cấp cho phương thức chọn một tham số Basket. Vì người nông dân trồng trái cây của chúng tôi cũng bán nước trái cây nên chúng tôi có thể thêm phương thức ép vào lớp Cam. Khi được gọi, phương thức ép có thể trả về lượng nước trái cây đã lấy, đồng thời loại bỏ Cam khỏi Giỏ mà nó ở trong

Lớp Rổ có thể có hành động bán. Khi một giỏ được bán, hệ thống hàng tồn kho của chúng tôi có thể cập nhật một số dữ liệu về các đối tượng chưa được xác định để tính toán lợi nhuận và kế toán. Ngoài ra, giỏ cam của chúng tôi có thể bị hỏng trước khi chúng tôi có thể bán chúng, vì vậy chúng tôi thêm phương thức loại bỏ. Hãy thêm các phương thức này vào sơ đồ của chúng ta

Việc thêm các thuộc tính và phương thức vào các đối tượng riêng lẻ cho phép chúng ta tạo ra một hệ thống các đối tượng tương tác với nhau. Mỗi đối tượng trong hệ thống là thành viên của một lớp nào đó. Các lớp này chỉ định loại dữ liệu mà đối tượng có thể chứa và phương thức nào có thể được gọi trên đó. Dữ liệu trong mỗi đối tượng có thể ở trạng thái khác với các thể hiện khác của cùng một lớp;

Phân tích và thiết kế hướng đối tượng là tất cả về việc tìm ra những đối tượng đó là gì và chúng nên tương tác như thế nào. Phần tiếp theo mô tả các nguyên tắc có thể được sử dụng để làm cho những tương tác đó trở nên đơn giản và trực quan nhất có thể

 

Ẩn chi tiết và tạo giao diện chung

Mục đích chính của việc mô hình hóa một đối tượng trong thiết kế hướng đối tượng là xác định giao diện chung của đối tượng đó sẽ là gì. Giao diện là tập hợp các thuộc tính và phương thức mà các đối tượng khác có thể truy cập để tương tác với đối tượng đó. Họ không cần và thường không được phép truy cập vào hoạt động bên trong của đối tượng

Một ví dụ phổ biến trong thế giới thực là truyền hình. Giao diện của chúng tôi với truyền hình là điều khiển từ xa. Mỗi nút trên điều khiển từ xa đại diện cho một phương thức có thể được gọi trên đối tượng truyền hình. Khi chúng tôi, với tư cách là đối tượng gọi, truy cập các phương thức này, chúng tôi không biết hoặc không quan tâm liệu tivi có nhận tín hiệu từ kết nối cáp, đĩa vệ tinh hay thiết bị hỗ trợ internet hay không. Chúng tôi không quan tâm tín hiệu điện tử nào được gửi để điều chỉnh âm lượng hay liệu âm thanh có được dành cho loa hoặc tai nghe hay không. Nếu chúng tôi mở tivi để truy cập vào các hoạt động bên trong, ví dụ như chia tín hiệu đầu ra cho cả loa ngoài và một bộ tai nghe, chúng tôi sẽ làm mất hiệu lực bảo hành.

Quá trình che giấu việc thực hiện một đối tượng này được gọi một cách thích hợp là che giấu thông tin. Đôi khi nó còn được gọi là đóng gói, nhưng đóng gói thực sự là một thuật ngữ bao gồm tất cả hơn. Dữ liệu được đóng gói không nhất thiết phải ẩn. Đóng gói, theo nghĩa đen, là tạo ra một viên nang [hãy nghĩ đến việc tạo ra một viên nang thời gian]. Nếu bạn đặt một loạt thông tin vào một viên nang thời gian, khóa và chôn vùi nó, nó sẽ được đóng gói và thông tin sẽ bị ẩn. Ngược lại, nếu viên nang thời gian chưa bị chôn vùi và được mở khóa hoặc làm bằng nhựa trong, các vật phẩm bên trong vẫn được gói gọn nhưng không có thông tin nào được che giấu.

Sự khác biệt giữa đóng gói và ẩn thông tin phần lớn không liên quan, đặc biệt là ở cấp độ thiết kế. Nhiều tài liệu tham khảo thực tế sử dụng các thuật ngữ này thay thế cho nhau. Là lập trình viên Python, chúng ta không thực sự có hoặc không cần che giấu thông tin thực sự [chúng ta sẽ thảo luận lý do của việc này trong Chương 2 , Đối tượng trong Python] .

Tuy nhiên, giao diện công khai là rất quan trọng. Nó cần được thiết kế cẩn thận vì rất khó thay đổi nó trong tương lai. Thay đổi giao diện sẽ phá vỡ mọi đối tượng máy khách đang truy cập nó. Chúng ta có thể thay đổi tất cả các phần bên trong mà chúng ta muốn, ví dụ, để làm cho nó hiệu quả hơn hoặc để truy cập dữ liệu qua mạng cũng như cục bộ và các đối tượng máy khách vẫn có thể nói chuyện với nó, không bị sửa đổi, sử dụng giao diện chung. Mặt khác, nếu chúng ta thay đổi giao diện bằng cách thay đổi tên thuộc tính được truy cập công khai hoặc thứ tự hoặc loại đối số mà một phương thức có thể chấp nhận, thì tất cả các lớp máy khách cũng sẽ phải được sửa đổi. Khi thiết kế giao diện công cộng, hãy giữ cho nó đơn giản. Luôn thiết kế giao diện của một đối tượng dựa trên mức độ dễ sử dụng của nó chứ không phải mức độ khó viết mã [lời khuyên này cũng áp dụng cho giao diện người dùng]

Hãy nhớ rằng, các đối tượng chương trình có thể đại diện cho các đối tượng thực, nhưng điều đó không làm cho chúng trở thành đối tượng thực. Họ là những người mẫu. Một trong những món quà lớn nhất của nghề người mẫu là khả năng bỏ qua những chi tiết không liên quan. Chiếc xe mô hình mà tôi đã chế tạo khi còn nhỏ trông giống như một chiếc Thunderbird 1956 thực sự ở bên ngoài, nhưng rõ ràng là nó không chạy. Khi tôi còn quá trẻ để lái xe, những chi tiết này quá phức tạp và không liên quan. Mô hình là sự trừu tượng hóa của một khái niệm thực

Trừu tượng hóa là một thuật ngữ hướng đối tượng khác liên quan đến đóng gói và che giấu thông tin. Trừu tượng có nghĩa là xử lý mức độ chi tiết phù hợp nhất với một nhiệm vụ nhất định. Đó là quá trình trích xuất một giao diện công cộng từ các chi tiết bên trong. Người lái xe ô tô cần tương tác với hệ thống lái, chân ga và phanh. Hoạt động của động cơ, hệ thống truyền động và hệ thống con phanh không quan trọng đối với người lái. Mặt khác, một thợ máy làm việc ở một mức độ trừu tượng khác, điều chỉnh động cơ và làm chảy máu phanh. Đây là một ví dụ về hai mức độ trừu tượng cho một chiếc xe hơi

Bây giờ, chúng tôi có một số thuật ngữ mới đề cập đến các khái niệm tương tự. Hãy tóm tắt tất cả thuật ngữ này trong một vài câu. trừu tượng hóa là quá trình đóng gói thông tin với các giao diện công khai và riêng tư. Các giao diện riêng tư có thể bị che giấu thông tin

Bài học quan trọng rút ra từ tất cả các định nghĩa này là làm cho các mô hình của chúng ta có thể hiểu được đối với các đối tượng khác phải tương tác với chúng. Điều này có nghĩa là chú ý cẩn thận đến các chi tiết nhỏ. Đảm bảo các phương thức và thuộc tính có tên hợp lý. Khi phân tích một hệ thống, các đối tượng thường đại diện cho danh từ trong vấn đề ban đầu, trong khi các phương thức thường là động từ. Các thuộc tính có thể hiển thị dưới dạng tính từ hoặc nhiều danh từ hơn. Đặt tên cho các lớp, thuộc tính và phương thức của bạn cho phù hợp

Khi thiết kế giao diện, hãy tưởng tượng bạn là đối tượng và bạn rất quan tâm đến quyền riêng tư. Đừng để các đối tượng khác có quyền truy cập vào dữ liệu về bạn trừ khi bạn cảm thấy việc họ có nó là điều tốt nhất cho bạn. Đừng cung cấp cho họ một giao diện để buộc bạn thực hiện một nhiệm vụ cụ thể trừ khi bạn chắc chắn rằng bạn muốn họ có thể làm điều đó với bạn

 

Thành phần

Cho đến nay, chúng ta đã học cách thiết kế hệ thống dưới dạng một nhóm các đối tượng tương tác, trong đó mỗi tương tác liên quan đến việc xem các đối tượng ở mức độ trừu tượng phù hợp. Nhưng chúng ta vẫn chưa biết cách tạo ra các mức trừu tượng này. Có nhiều cách để làm điều này; . Nhưng thậm chí hầu hết các mẫu thiết kế đều dựa trên hai nguyên tắc hướng đối tượng cơ bản được gọi là thành phần và kế thừa. Thành phần đơn giản hơn, vì vậy hãy bắt đầu với nó. Chapter 8, Strings and Serialization, and Chapter 9, The Iterator Pattern. But even most design patterns rely on two basic object-oriented principles known as composition and inheritance. Composition is simpler, so let's start with it.

Sáng tác là hành động thu thập một số đối tượng lại với nhau để tạo ra một đối tượng mới. Thành phần thường là một lựa chọn tốt khi một đối tượng là một phần của đối tượng khác. Chúng ta đã thấy một gợi ý đầu tiên về bố cục trong ví dụ cơ học. Một chiếc ô tô chạy bằng nhiên liệu hóa thạch bao gồm động cơ, hộp số, bộ khởi động, đèn pha và kính chắn gió, cùng nhiều bộ phận khác. Ngược lại, động cơ bao gồm các pít-tông, trục khuỷu và van. Trong ví dụ này, thành phần là một cách tốt để cung cấp mức độ trừu tượng. Đối tượng Car có thể cung cấp giao diện theo yêu cầu của người lái xe, đồng thời cấp quyền truy cập vào các bộ phận cấu thành của nó, điều này mang lại mức độ trừu tượng sâu hơn phù hợp cho thợ cơ khí. Tất nhiên, những bộ phận cấu thành đó có thể được chia nhỏ hơn nếu thợ máy cần thêm thông tin để chẩn đoán sự cố hoặc điều chỉnh động cơ

Ô tô là một ví dụ mở đầu phổ biến về bố cục, nhưng nó không quá hữu ích khi thiết kế hệ thống máy tính. Các đối tượng vật lý dễ dàng chia thành các đối tượng thành phần. Mọi người đã làm điều này ít nhất kể từ khi người Hy Lạp cổ đại ban đầu cho rằng các nguyên tử là đơn vị vật chất nhỏ nhất [tất nhiên, họ không có quyền truy cập vào máy gia tốc hạt]. Các hệ thống máy tính nói chung ít phức tạp hơn các đối tượng vật lý, tuy nhiên việc xác định các đối tượng thành phần trong các hệ thống đó không xảy ra một cách tự nhiên.

Các đối tượng trong một hệ thống hướng đối tượng đôi khi đại diện cho các đối tượng vật lý như con người, sách hoặc điện thoại. Tuy nhiên, thường xuyên hơn, chúng đại diện cho những ý tưởng trừu tượng. Người có tên, sách có tựa, điện thoại dùng để gọi. Cuộc gọi, tiêu đề, tài khoản, tên, cuộc hẹn và thanh toán thường không được coi là đối tượng trong thế giới vật chất, nhưng chúng đều là các thành phần được mô hình hóa thường xuyên trong hệ thống máy tính

Hãy thử lập mô hình một ví dụ hướng đến máy tính hơn để xem hoạt động của bố cục. Chúng ta sẽ xem xét thiết kế của một trò chơi cờ trên máy vi tính. Đây là một trò tiêu khiển rất phổ biến trong giới học thuật những năm 80 và 90. Mọi người đã dự đoán rằng một ngày nào đó máy tính sẽ có thể đánh bại một bậc thầy cờ vua của con người. Khi điều này xảy ra vào năm 1997 [Deep Blue của IBM đánh bại nhà vô địch cờ vua thế giới, Gary Kasparov], sự quan tâm đến vấn đề này giảm dần. Ngày nay, máy tính luôn chiến thắng

Là một phân tích cấp cao, cơ bản, một ván cờ được chơi giữa hai người chơi, sử dụng một bộ cờ có một bàn cờ chứa sáu mươi bốn vị trí trong một lưới 8x8. Bàn cờ có thể có hai bộ mười sáu quân cờ có thể được di chuyển luân phiên bởi hai người chơi theo những cách khác nhau. Mỗi mảnh có thể lấy các mảnh khác. Bàn cờ sẽ được yêu cầu tự vẽ trên màn hình máy tính sau mỗi lượt chơi

Tôi đã xác định một số đối tượng có thể có trong phần mô tả bằng cách sử dụng chữ in nghiêng và một vài phương thức chính sử dụng chữ in đậm. Đây là bước đầu tiên phổ biến trong việc biến một phân tích hướng đối tượng thành một thiết kế. Tại thời điểm này, để nhấn mạnh bố cục, chúng ta sẽ tập trung vào bàn cờ mà không cần lo lắng quá nhiều về người chơi hoặc các loại quân cờ khác nhau

Hãy bắt đầu ở mức trừu tượng cao nhất có thể. Chúng tôi có hai người chơi tương tác với Bộ cờ vua bằng cách thay phiên nhau thực hiện các nước đi

Điều này trông không giống như các sơ đồ lớp trước đây của chúng tôi, đó là một điều tốt vì nó không phải là một. Đây là sơ đồ đối tượng, còn được gọi là sơ đồ thể hiện. Nó mô tả hệ thống ở một trạng thái cụ thể trong thời gian và đang mô tả các thể hiện cụ thể của các đối tượng, không phải sự tương tác giữa các lớp. Hãy nhớ rằng, cả hai người chơi đều là thành viên của cùng một lớp, vì vậy sơ đồ lớp trông hơi khác một chút

Sơ đồ cho thấy chính xác hai người chơi có thể tương tác với một bộ cờ vua. Điều này cũng chỉ ra rằng bất kỳ người chơi nào cũng chỉ có thể chơi với một Bộ cờ tại một thời điểm.

Tuy nhiên, chúng ta đang thảo luận về thành phần, không phải UML, vì vậy hãy nghĩ xem Bộ cờ bao gồm những gì. Chúng tôi không quan tâm người chơi bao gồm những gì vào lúc này. Chúng tôi có thể giả định rằng người chơi có tim và não, cùng các cơ quan khác, nhưng chúng không liên quan đến mô hình của chúng tôi. Thật vậy, không có gì ngăn cản người chơi nói trên trở thành Deep Blue, thứ không có trái tim cũng như khối óc

Vậy bộ cờ vua bao gồm một bàn cờ và 32 quân cờ. Hội đồng quản trị tiếp tục bao gồm 64 vị trí. Bạn có thể lập luận rằng các quân cờ không phải là một phần của bộ cờ vua vì bạn có thể thay thế các quân cờ trong một bộ cờ vua bằng một bộ quân cờ khác. Mặc dù điều này khó xảy ra hoặc không thể xảy ra trong phiên bản cờ vua được vi tính hóa, nhưng nó giới thiệu cho chúng ta cách tổng hợp

Tập hợp gần như chính xác như thành phần. Sự khác biệt là các đối tượng tổng hợp có thể tồn tại độc lập. Không thể có một vị trí được liên kết với một bàn cờ khác, vì vậy chúng tôi nói bàn cờ bao gồm các vị trí. Nhưng các quân cờ, có thể tồn tại độc lập với bộ cờ, được cho là có mối quan hệ tổng thể với bộ đó.

Một cách khác để phân biệt giữa tập hợp và thành phần là suy nghĩ về tuổi thọ của đối tượng. Nếu đối tượng tổng hợp [bên ngoài] kiểm soát thời điểm các đối tượng liên quan [bên trong] được tạo và hủy, thì thành phần là phù hợp nhất. Nếu đối tượng liên quan được tạo độc lập với đối tượng tổng hợp hoặc có thể tồn tại lâu hơn đối tượng đó, thì mối quan hệ tổng hợp sẽ có ý nghĩa hơn. Ngoài ra, hãy nhớ rằng thành phần là tổng hợp; . Bất kỳ mối quan hệ tổng hợp nào cũng là mối quan hệ tổng hợp, nhưng không phải ngược lại

Hãy mô tả thành phần Bộ cờ vua hiện tại của chúng ta và thêm một số thuộc tính cho các đối tượng để giữ các mối quan hệ tổng hợp

Mối quan hệ thành phần được biểu diễn trong UML dưới dạng một viên kim cương rắn. Viên kim cương rỗng thể hiện mối quan hệ tổng hợp. Bạn sẽ nhận thấy rằng bàn cờ và các quân cờ được lưu trữ như một phần của Bộ cờ vua giống hệt như cách tham chiếu đến chúng được lưu trữ như một thuộc tính trên bộ cờ vua. Điều này cho thấy, một lần nữa, trong thực tế, sự khác biệt giữa tổng hợp và bố cục thường không còn quan trọng nữa khi bạn đã qua giai đoạn thiết kế. Khi được triển khai, chúng hoạt động theo cùng một cách. Tuy nhiên, có thể giúp phân biệt giữa hai loại này khi nhóm của bạn đang thảo luận về cách các đối tượng khác nhau tương tác với nhau. Thông thường, bạn có thể coi chúng là cùng một thứ, nhưng khi bạn cần phân biệt giữa chúng [thường là khi nói về thời gian tồn tại của các đối tượng liên quan], thật tuyệt khi biết sự khác biệt

 

Di sản

Chúng tôi đã thảo luận ba loại mối quan hệ giữa các đối tượng. hiệp hội, thành phần và tập hợp. Tuy nhiên, chúng tôi chưa chỉ định đầy đủ bộ cờ của mình và những công cụ này dường như không cung cấp cho chúng tôi tất cả sức mạnh mà chúng tôi cần. Chúng tôi đã thảo luận về khả năng người chơi có thể là con người hoặc đó có thể là một phần mềm có trí tuệ nhân tạo. Có vẻ không đúng khi nói rằng người chơi được liên kết với con người hoặc việc triển khai trí tuệ nhân tạo là một phần của đối tượng người chơi. Điều chúng tôi thực sự cần là khả năng nói rằng Deep Blue là một người chơi hoặc Gary Kasparov là một người chơi

Là một mối quan hệ được hình thành bởi sự kế thừa. Kế thừa là mối quan hệ nổi tiếng nhất, nổi tiếng và được sử dụng nhiều nhất trong lập trình hướng đối tượng. Thừa kế giống như một cây phả hệ. Họ của ông nội tôi là Phillips và cha tôi được thừa hưởng cái tên đó. Tôi được thừa hưởng nó từ anh ấy. Trong lập trình hướng đối tượng, thay vì kế thừa các tính năng và hành vi từ một người, một lớp có thể kế thừa các thuộc tính và phương thức từ lớp khác

Ví dụ, có 32 quân cờ trong bộ cờ vua của chúng ta, nhưng chỉ có sáu loại quân khác nhau [quân, xe, tượng, mã, vua và hậu], mỗi quân có hành vi khác nhau khi được di chuyển. Tất cả các loại quân cờ này đều có các thuộc tính, chẳng hạn như màu sắc và bộ cờ mà chúng tham gia, nhưng chúng cũng có hình dạng độc đáo khi được vẽ trên bàn cờ và thực hiện các nước đi khác nhau. Hãy xem sáu loại quân có thể kế thừa từ một lớp Mảnh như thế nào

Các mũi tên rỗng chỉ ra rằng các lớp mảnh riêng lẻ kế thừa từ lớp Mảnh. Tất cả các lớp con tự động có thuộc tính chess_set và color được kế thừa từ lớp cơ sở. Mỗi quân cờ cung cấp một thuộc tính hình dạng khác nhau [được vẽ trên màn hình khi hiển thị bàn cờ] và một phương thức di chuyển khác để di chuyển quân cờ đến vị trí mới trên bàn cờ ở mỗi lượt.

Chúng ta thực sự biết rằng tất cả các lớp con của lớp Piece cần phải có một phương thức di chuyển; . Có thể là chúng tôi muốn tạo một phiên bản mới của trò chơi cờ vua có thêm một quân cờ [quân phù thủy]. Thiết kế hiện tại của chúng tôi sẽ cho phép chúng tôi thiết kế tác phẩm này mà không cần đưa ra phương pháp di chuyển. Sau đó, tấm ván sẽ nghẹt thở khi nó yêu cầu quân cờ tự di chuyển

Chúng ta có thể khắc phục điều này bằng cách tạo một phương thức di chuyển giả trên lớp Piece. Sau đó, các lớp con có thể ghi đè phương thức này bằng cách triển khai cụ thể hơn. Ví dụ: việc triển khai mặc định có thể bật lên thông báo lỗi cho biết Không thể di chuyển phần đó

Các phương thức ghi đè trong các lớp con cho phép phát triển các hệ thống hướng đối tượng rất mạnh. Ví dụ: nếu chúng tôi muốn triển khai lớp Người chơi bằng trí tuệ nhân tạo, chúng tôi có thể cung cấp phương thức tính toán_move lấy một đối tượng Board và quyết định quân cờ sẽ di chuyển ở đâu. Một lớp rất cơ bản có thể chọn ngẫu nhiên một mảnh và hướng và di chuyển nó cho phù hợp. Sau đó, chúng tôi có thể ghi đè phương thức này trong một lớp con với triển khai Deep Blue. Lớp đầu tiên sẽ phù hợp để đấu với người mới bắt đầu; . Điều quan trọng là các phương thức khác trong lớp, chẳng hạn như các phương thức thông báo cho bàn cờ biết nước đi đã được chọn, không cần phải thay đổi;

Trong trường hợp quân cờ, việc cung cấp cách triển khai mặc định cho phương thức di chuyển là không thực sự hợp lý. Tất cả những gì chúng ta cần làm là xác định rằng phương thức di chuyển là bắt buộc trong bất kỳ lớp con nào. Điều này có thể được thực hiện bằng cách biến Piece thành một lớp trừu tượng với phương thức di chuyển được khai báo là trừu tượng. Phương pháp trừu tượng về cơ bản nói điều này

Chúng tôi yêu cầu phương thức này tồn tại trong bất kỳ lớp con không trừu tượng nào, nhưng chúng tôi từ chối chỉ định triển khai trong lớp này

Thật vậy, có thể tạo một lớp hoàn toàn không triển khai bất kỳ phương thức nào. Một lớp như vậy sẽ chỉ đơn giản cho chúng ta biết lớp đó nên làm gì, nhưng hoàn toàn không đưa ra lời khuyên nào về cách thực hiện. Theo cách nói hướng đối tượng, các lớp như vậy được gọi là giao diện

Kế thừa cung cấp sự trừu tượng

Cùng khám phá từ dài nhất trong argot hướng đối tượng. Tính đa hình là khả năng xử lý một lớp khác nhau, tùy thuộc vào lớp con nào được triển khai. Chúng tôi đã thấy nó hoạt động với hệ thống quân cờ mà chúng tôi đã mô tả. Nếu chúng ta thiết kế xa hơn một chút, có lẽ chúng ta sẽ thấy rằng đối tượng Bàn cờ có thể chấp nhận nước đi từ người chơi và gọi chức năng di chuyển trên quân cờ. Bàn cờ không bao giờ biết nó đang xử lý loại quân nào. Tất cả những gì nó phải làm là gọi phương thức di chuyển và lớp con thích hợp sẽ đảm nhiệm việc di chuyển nó dưới dạng Mã hoặc Tốt

Đa hình khá hay, nhưng nó là một từ hiếm khi được sử dụng trong lập trình Python. Python tiến thêm một bước trong quá khứ cho phép một lớp con của một đối tượng được coi như một lớp cha. Một bàn cờ được triển khai bằng Python có thể lấy bất kỳ đối tượng nào có phương thức di chuyển, cho dù đó là quân tượng, ô tô hay vịt. Khi được gọi di chuyển, Tượng sẽ di chuyển theo đường chéo trên bàn cờ, ô tô sẽ đi đến một nơi nào đó và vịt sẽ bơi hoặc bay tùy thuộc vào tâm trạng của nó.

Kiểu đa hình này trong Python thường được gọi là kiểu gõ vịt. nếu nó đi như vịt hoặc bơi như vịt thì đó là vịt. Chúng tôi không quan tâm liệu nó có thực sự là một con vịt hay không [là nền tảng của tài sản thừa kế], chỉ quan tâm đến việc nó bơi hay đi. Ngỗng và thiên nga có thể dễ dàng cung cấp hành vi giống vịt mà chúng tôi đang tìm kiếm. Điều này cho phép các nhà thiết kế trong tương lai tạo ra các loại chim mới mà không thực sự chỉ định hệ thống phân cấp thừa kế cho các loài chim sống dưới nước. Nó cũng cho phép họ tạo ra các hành vi thả vào hoàn toàn khác mà các nhà thiết kế ban đầu chưa bao giờ lên kế hoạch cho. Ví dụ: các nhà thiết kế trong tương lai có thể tạo ra một chú chim cánh cụt đang đi, đang bơi hoạt động trên cùng một giao diện mà không bao giờ gợi ý rằng chim cánh cụt là vịt

đa thừa kế

Khi chúng ta nghĩ về sự thừa kế trong cây phả hệ của chính mình, chúng ta có thể thấy rằng chúng ta thừa hưởng các đặc điểm không chỉ từ một bậc cha mẹ. Khi những người lạ nói với một người mẹ đầy tự hào rằng con trai cô ấy có đôi mắt của cha nó, cô ấy thường sẽ trả lời theo kiểu, vâng, nhưng anh ấy đã xỏ mũi tôi

Thiết kế hướng đối tượng cũng có thể có tính năng đa kế thừa như vậy, cho phép một lớp con kế thừa chức năng từ nhiều lớp cha. Trong thực tế, đa kế thừa có thể là một công việc phức tạp và một số ngôn ngữ lập trình [nổi tiếng nhất là Java] nghiêm cấm điều này. Tuy nhiên, đa kế thừa có thể có công dụng của nó. Thông thường, nó có thể được sử dụng để tạo các đối tượng có hai nhóm hành vi riêng biệt. Ví dụ: một đối tượng được thiết kế để kết nối với máy quét và gửi fax tài liệu được quét có thể được tạo bằng cách kế thừa từ hai đối tượng máy quét và máy fax riêng biệt

Miễn là hai lớp có các giao diện riêng biệt, thì việc một lớp con kế thừa từ cả hai lớp thường không có hại. Tuy nhiên, sẽ lộn xộn nếu chúng ta kế thừa từ hai lớp cung cấp các giao diện chồng chéo. Ví dụ: nếu chúng ta có một lớp mô tô có phương thức di chuyển và một lớp thuyền cũng có phương thức di chuyển và chúng ta muốn hợp nhất chúng thành phương tiện lội nước cuối cùng, làm thế nào để lớp kết quả biết phải làm gì khi chúng ta gọi di chuyển

Thông thường, cách tốt nhất để đối phó với nó là tránh nó. Nếu bạn có một thiết kế hiển thị như thế này, có lẽ bạn đang làm sai. Lùi lại một bước, phân tích lại hệ thống và xem liệu bạn có thể loại bỏ mối quan hệ đa thừa kế để ưu tiên cho một số liên kết hoặc thiết kế tổng hợp khác không

Kế thừa là một công cụ rất mạnh để mở rộng hành vi. Nó cũng là một trong những tiến bộ khả thi nhất của thiết kế hướng đối tượng so với các mô hình trước đó. Do đó, nó thường là công cụ đầu tiên mà các lập trình viên hướng đối tượng tìm đến. Tuy nhiên, điều quan trọng là phải nhận ra rằng sở hữu một cái búa không biến vít thành đinh. Kế thừa là giải pháp hoàn hảo cho mối quan hệ rõ ràng, nhưng nó có thể bị lạm dụng. Các lập trình viên thường sử dụng tính kế thừa để chia sẻ mã giữa hai loại đối tượng chỉ có liên quan xa nhau, không có mối quan hệ nào trong tầm nhìn. Mặc dù đây không nhất thiết là một thiết kế tồi, nhưng đây là một cơ hội tuyệt vời để hỏi tại sao họ quyết định thiết kế theo cách đó và liệu một mối quan hệ hoặc mẫu thiết kế khác có phù hợp hơn không

 

nghiên cứu trường hợp

Hãy liên kết tất cả kiến ​​thức hướng đối tượng mới của chúng ta lại với nhau bằng cách thực hiện một vài lần lặp lại thiết kế hướng đối tượng trên một ví dụ hơi thực tế. Hệ thống chúng tôi sẽ lập mô hình là một danh mục thư viện. Các thư viện đã theo dõi hàng tồn kho của họ trong nhiều thế kỷ, ban đầu sử dụng danh mục thẻ và gần đây hơn là hàng tồn kho điện tử. Các thư viện hiện đại có các danh mục dựa trên web mà chúng ta có thể truy vấn từ nhà của mình

Hãy bắt đầu với một phân tích. Thủ thư địa phương đã yêu cầu chúng tôi viết một chương trình danh mục thẻ mới vì chương trình cũ dựa trên Windows XP của họ rất xấu và lỗi thời. Điều đó không cung cấp cho chúng tôi nhiều chi tiết, nhưng trước khi bắt đầu hỏi thêm thông tin, hãy xem xét những gì chúng tôi đã biết về danh mục thư viện

Danh mục chứa danh sách sách. Mọi người tìm kiếm chúng để tìm sách về các chủ đề nhất định, với tiêu đề cụ thể hoặc của một tác giả cụ thể. Sách có thể được xác định duy nhất bằng Mã số sách tiêu chuẩn quốc tế [ISBN]. Mỗi cuốn sách có một số Hệ thống thập phân Dewey [DDS] được chỉ định để giúp tìm thấy nó trên một giá sách cụ thể

Phân tích đơn giản này cho chúng ta biết một số đối tượng rõ ràng trong hệ thống. Chúng tôi nhanh chóng xác định Sách là đối tượng quan trọng nhất, với một số thuộc tính đã được đề cập, chẳng hạn như tác giả, tiêu đề, chủ đề, ISBN và số DDS và danh mục dưới dạng một loại trình quản lý sách

Chúng tôi cũng nhận thấy một vài đối tượng khác có thể cần hoặc không cần được mô hình hóa trong hệ thống. Đối với mục đích lập danh mục, tất cả những gì chúng ta cần để tìm kiếm một cuốn sách theo tác giả là một thuộc tính author_name trên cuốn sách. Tuy nhiên, tác giả cũng là đối tượng và chúng tôi có thể muốn lưu trữ một số dữ liệu khác về tác giả. Khi suy ngẫm về điều này, chúng ta có thể nhớ rằng một số sách có nhiều tác giả. Đột nhiên, ý tưởng có một thuộc tính author_name duy nhất trên các đối tượng có vẻ hơi ngớ ngẩn. Một danh sách các tác giả được liên kết với mỗi cuốn sách rõ ràng là một ý tưởng tốt hơn

Mối quan hệ giữa tác giả và cuốn sách rõ ràng là sự liên kết, vì bạn sẽ không bao giờ nói cuốn sách là tác giả [đó không phải là tài sản thừa kế] và việc nói rằng cuốn sách có một tác giả, mặc dù đúng về mặt ngữ pháp, không có nghĩa là tác giả là một phần của cuốn sách [không phải . Thật vậy, bất kỳ một tác giả nào cũng có thể được liên kết với nhiều cuốn sách

Chúng ta cũng nên chú ý đến danh từ [danh từ luôn là ứng cử viên tốt cho đối tượng] kệ. Kệ có phải là một đối tượng cần được mô hình hóa trong hệ thống biên mục không?

DDS được thiết kế để giúp xác định vị trí sách vật lý trong thư viện. Như vậy, việc lưu trữ thuộc tính DDS cùng với sách là đủ để xác định vị trí của nó, bất kể nó được lưu trữ trên kệ nào. Vì vậy, ít nhất là trong thời điểm hiện tại, chúng ta có thể xóa kệ khỏi danh sách các đối tượng tranh chấp của mình

Một đối tượng nghi vấn khác trong hệ thống là người dùng. Chúng tôi có cần biết bất cứ điều gì về một người dùng cụ thể, chẳng hạn như tên, địa chỉ hoặc danh sách sách quá hạn của họ không? . Trong tâm trí của chúng tôi, chúng tôi cũng lưu ý rằng tác giả và người dùng đều là những loại người cụ thể;

Vì mục đích lập danh mục, chúng tôi quyết định hiện tại chúng tôi không cần xác định người dùng. Chúng tôi có thể cho rằng người dùng sẽ tìm kiếm danh mục, nhưng chúng tôi không phải chủ động lập mô hình cho họ trong hệ thống, ngoài việc cung cấp giao diện cho phép họ tìm kiếm

Chúng tôi đã xác định được một vài thuộc tính trên sách, nhưng danh mục có những thuộc tính nào?

Còn về hành vi thì sao? . Có hành vi nào trên sách không?

Các câu hỏi trong phần thảo luận trước đều là một phần của giai đoạn phân tích hướng đối tượng. Nhưng xen kẽ với các câu hỏi, chúng tôi đã xác định được một số đối tượng chính là một phần của thiết kế. Thật vậy, những gì bạn vừa thấy là một số bước vi mô giữa phân tích và thiết kế

Có khả năng, tất cả các lần lặp lại này sẽ diễn ra trong cuộc gặp đầu tiên với thủ thư. Tuy nhiên, trước cuộc họp này, chúng ta đã có thể phác thảo một thiết kế cơ bản nhất cho các đối tượng mà chúng ta đã xác định cụ thể, như sau

Được trang bị sơ đồ cơ bản này và một cây bút chì để cải thiện nó một cách tương tác, chúng tôi gặp gỡ thủ thư. Họ nói với chúng tôi rằng đây là một khởi đầu tốt, nhưng các thư viện không chỉ phục vụ sách; . Tất cả các loại mặt hàng này có thể được xác định duy nhất bằng số UPC, mặc dù. Chúng tôi nhắc thủ thư rằng họ phải tìm các mục trên giá và những mục này có thể không được UPC sắp xếp. Thủ thư giải thích rằng mỗi loại được tổ chức theo một cách khác nhau. Các đĩa CD chủ yếu là sách nói và chúng chỉ có hai chục trong kho, vì vậy chúng được sắp xếp theo họ của tác giả. DVD được chia thành thể loại và sắp xếp thêm theo tiêu đề. Các tạp chí được sắp xếp theo tiêu đề và sau đó được tinh chỉnh theo số lượng và số phát hành. Sách, như chúng ta đã đoán, được sắp xếp theo số DDS

Nếu không có kinh nghiệm thiết kế hướng đối tượng trước đây, chúng ta có thể cân nhắc thêm các danh sách DVD, CD, tạp chí và sách riêng biệt vào danh mục của mình và lần lượt tìm kiếm từng danh sách. Vấn đề là, ngoại trừ một số thuộc tính mở rộng nhất định và xác định vị trí thực của vật phẩm, tất cả các vật phẩm này đều hoạt động giống nhau. Đây là công việc thừa kế. Chúng tôi nhanh chóng cập nhật sơ đồ UML của mình như sau

Thủ thư hiểu ý chính của sơ đồ phác thảo của chúng tôi, nhưng hơi bối rối bởi chức năng xác định vị trí. Chúng tôi giải thích bằng cách sử dụng trường hợp sử dụng cụ thể khi người dùng đang tìm kiếm từ bunnies. Trước tiên, người dùng gửi yêu cầu tìm kiếm đến danh mục. Danh mục truy vấn danh sách mặt hàng nội bộ của nó và tìm thấy một cuốn sách và một đĩa DVD có chú thỏ trong tiêu đề. Tại thời điểm này, danh mục không quan tâm đến việc nó đang chứa DVD, sách, CD hay tạp chí; . Tuy nhiên, người dùng muốn biết cách tìm các mục vật lý, vì vậy danh mục sẽ thiếu sót nếu nó chỉ trả về một danh sách các tiêu đề. Vì vậy, nó gọi phương thức định vị trên hai mục mà nó đã phát hiện ra. Phương thức xác định vị trí của sách trả về một số DDS có thể được sử dụng để tìm giá chứa sách. DVD được định vị bằng cách trả về thể loại và tiêu đề của DVD. Sau đó, người dùng có thể truy cập phần DVD, tìm phần chứa thể loại đó và tìm DVD cụ thể được sắp xếp theo tiêu đề

Như chúng tôi giải thích, chúng tôi phác họa sơ đồ trình tự UML, giải thích cách các đối tượng khác nhau giao tiếp

Trong khi sơ đồ lớp mô tả mối quan hệ giữa các lớp, sơ đồ trình tự mô tả trình tự cụ thể của các thông báo được truyền giữa các đối tượng. Đường đứt nét treo trên mỗi đối tượng là đường sống mô tả thời gian tồn tại của đối tượng. Các hộp rộng hơn trên mỗi vòng đời thể hiện quá trình xử lý đang hoạt động trong đối tượng đó [ở nơi không có hộp, đối tượng về cơ bản là không hoạt động, chờ đợi điều gì đó xảy ra]. Các mũi tên nằm ngang giữa các đường cứu sinh cho biết các thông điệp cụ thể. Các mũi tên nét liền biểu thị các phương thức đang được gọi, trong khi các mũi tên nét đứt có đầu liền nét biểu thị các giá trị trả về của phương thức

Nửa đầu mũi tên biểu thị các thông báo không đồng bộ được gửi đến hoặc từ một đối tượng. Thông báo không đồng bộ thường có nghĩa là đối tượng đầu tiên gọi một phương thức trên đối tượng thứ hai, phương thức này sẽ trả về ngay lập tức. Sau một số xử lý, đối tượng thứ hai gọi một phương thức trên đối tượng đầu tiên để cung cấp cho nó một giá trị. Điều này trái ngược với các cuộc gọi phương thức thông thường, thực hiện xử lý trong phương thức và trả về giá trị ngay lập tức

Sơ đồ trình tự, giống như tất cả các sơ đồ UML, chỉ được sử dụng tốt nhất khi cần thiết. Không có điểm nào trong việc vẽ sơ đồ UML vì mục đích vẽ sơ đồ. Tuy nhiên, khi bạn cần truyền đạt một loạt các tương tác giữa hai đối tượng, biểu đồ trình tự là một công cụ rất hữu ích

Thật không may, sơ đồ lớp của chúng tôi cho đến nay vẫn là một thiết kế lộn xộn. Chúng tôi nhận thấy rằng các diễn viên trên DVD và nghệ sĩ trên CD đều là những loại người, nhưng đang được đối xử khác với các tác giả cuốn sách. Thủ thư cũng nhắc nhở chúng tôi rằng hầu hết các đĩa CD của họ là sách nói, có tác giả thay vì nghệ sĩ

Làm thế nào chúng ta có thể đối phó với những loại người khác nhau đóng góp cho một danh hiệu? . Tuy nhiên, thừa kế có thực sự cần thiết ở đây? . Nếu chúng ta đang thực hiện một mô phỏng kinh tế, thì sẽ hợp lý khi đưa ra các lớp tác nhân và tác giả riêng biệt cũng như các phương thức tính toán_thu nhập và thực hiện công việc khác nhau, nhưng với mục đích lập danh mục, chỉ cần biết người đó đã đóng góp như thế nào cho mục đó là đủ. Sau khi suy nghĩ thấu đáo, chúng tôi nhận ra rằng tất cả các mục đều có một hoặc nhiều đối tượng Contributor, vì vậy chúng tôi chuyển mối quan hệ tác giả từ cuốn sách sang lớp cha của nó

Tính đa dạng của mối quan hệ Contributor/LibraryItem là nhiều-nhiều, như được biểu thị bằng ký tự * ở cả hai đầu của một mối quan hệ. Bất kỳ một mục thư viện nào cũng có thể có nhiều người đóng góp [ví dụ: một số diễn viên và đạo diễn trên DVD]. Và nhiều tác giả viết nhiều sách nên được gắn vào nhiều hạng mục thư viện

Thay đổi nhỏ này, mặc dù trông sạch sẽ và đơn giản hơn một chút, nhưng đã làm mất một số thông tin quan trọng. Chúng tôi vẫn có thể biết ai đã đóng góp cho một mục thư viện cụ thể, nhưng chúng tôi không biết họ đã đóng góp như thế nào. Họ là đạo diễn hay diễn viên?

Sẽ thật tuyệt nếu chúng ta có thể thêm một thuộc tính loại người đóng góp vào lớp Người đóng góp, nhưng điều này sẽ thất bại khi xử lý những người đa tài, những người vừa viết sách vừa đạo diễn phim.

Một tùy chọn là thêm các thuộc tính vào từng lớp con LibraryItem của chúng tôi để chứa thông tin chúng tôi cần, chẳng hạn như Tác giả trên Sách hoặc Nghệ sĩ trên CD, sau đó tạo mối quan hệ với tất cả các thuộc tính đó trỏ đến lớp Contributor. Vấn đề với điều này là chúng ta mất đi rất nhiều sự thanh lịch đa hình. Nếu chúng tôi muốn liệt kê những người đóng góp cho một mục, chúng tôi phải tìm các thuộc tính cụ thể trên mục đó, chẳng hạn như Tác giả hoặc Diễn viên. Chúng ta có thể giải quyết vấn đề này bằng cách thêm một phương thức GetContributors trên lớp LibraryItem mà các lớp con có thể ghi đè. Sau đó, danh mục không bao giờ phải biết những thuộc tính mà các đối tượng đang truy vấn;

Chỉ cần nhìn vào sơ đồ lớp này, có cảm giác như chúng ta đang làm sai điều gì đó. Nó cồng kềnh và dễ vỡ. Nó có thể làm mọi thứ chúng ta cần, nhưng có vẻ như nó sẽ khó duy trì hoặc mở rộng. Có quá nhiều mối quan hệ và quá nhiều lớp sẽ bị ảnh hưởng bởi những sửa đổi đối với bất kỳ lớp nào. Nó trông giống như mì spaghetti và thịt viên

Bây giờ chúng ta đã khám phá tính kế thừa dưới dạng một tùy chọn và thấy nó phù hợp, chúng ta có thể xem lại sơ đồ dựa trên thành phần trước đây của mình, nơi Contributor được gắn trực tiếp vào LibraryItem. Với một số suy nghĩ, chúng ta có thể thấy rằng chúng ta thực sự chỉ cần thêm một mối quan hệ nữa vào một lớp hoàn toàn mới để xác định loại người đóng góp. Đây là một bước quan trọng trong thiết kế hướng đối tượng. Chúng tôi hiện đang thêm một lớp vào thiết kế nhằm hỗ trợ các đối tượng khác, thay vì mô hình hóa bất kỳ phần nào của các yêu cầu ban đầu. Chúng tôi đang tái cấu trúc thiết kế để tạo điều kiện thuận lợi cho các đối tượng trong hệ thống, thay vì các đối tượng trong cuộc sống thực. Tái cấu trúc là một quá trình thiết yếu trong việc bảo trì một chương trình hoặc thiết kế. Mục tiêu của tái cấu trúc là cải thiện thiết kế bằng cách di chuyển mã xung quanh, loại bỏ mã trùng lặp hoặc các mối quan hệ phức tạp để tạo ra các thiết kế đơn giản hơn, thanh lịch hơn

Lớp mới này bao gồm một Người đóng góp và một thuộc tính bổ sung xác định loại đóng góp mà người đó đã thực hiện cho LibraryItem đã cho. Có thể có nhiều đóng góp như vậy cho một Mục thư viện cụ thể và một người đóng góp có thể đóng góp theo cùng một cách cho các mục khác nhau. Sơ đồ sau đây truyền đạt thiết kế này rất tốt

Lúc đầu, mối quan hệ thành phần này trông kém tự nhiên hơn so với các mối quan hệ dựa trên thừa kế. Tuy nhiên, nó có ưu điểm là cho phép chúng ta thêm các loại đóng góp mới mà không cần thêm lớp mới vào thiết kế. Kế thừa là hữu ích nhất khi các lớp con có một số loại chuyên môn hóa. Chuyên môn hóa là tạo hoặc thay đổi các thuộc tính hoặc hành vi trên lớp con để làm cho nó khác với lớp cha. Có vẻ ngớ ngẩn khi tạo ra một loạt các lớp trống chỉ để xác định các loại đối tượng khác nhau [thái độ này ít phổ biến hơn đối với các nhà lập trình Java và mọi thứ khác là đối tượng, nhưng nó phổ biến đối với các nhà thiết kế Python thực dụng hơn]. Nếu chúng ta nhìn vào phiên bản kế thừa của sơ đồ, chúng ta có thể thấy một loạt các lớp con không thực sự làm gì cả

Đôi khi, điều quan trọng là phải nhận ra khi nào không sử dụng các nguyên tắc hướng đối tượng. Ví dụ về thời điểm không sử dụng thừa kế này là một lời nhắc nhở tốt rằng các đối tượng chỉ là công cụ chứ không phải quy tắc

 

bài tập

Đây là một cuốn sách thực tế, không phải là một cuốn sách giáo khoa. Như vậy, tôi không gán một đống bài toán phân tích hướng đối tượng giả để tạo thiết kế cho bạn phân tích và thiết kế. Thay vào đó, tôi muốn cung cấp cho bạn một số ý tưởng mà bạn có thể áp dụng cho các dự án của riêng mình. Nếu bạn đã có kinh nghiệm về hướng đối tượng trước đó, bạn sẽ không cần nỗ lực nhiều cho chương này. Tuy nhiên, chúng là những bài tập tinh thần hữu ích nếu bạn đã sử dụng Python được một thời gian, nhưng chưa bao giờ thực sự quan tâm đến tất cả những thứ thuộc lớp đó

Đầu tiên, hãy nghĩ về một dự án lập trình gần đây mà bạn đã hoàn thành. Xác định đối tượng nổi bật nhất trong thiết kế. Cố gắng nghĩ ra càng nhiều thuộc tính cho đối tượng này càng tốt. Nó có như sau không. Màu?

Hãy suy nghĩ về các loại thuộc tính. Họ là người nguyên thủy hay lớp học? . Đối tượng có những phương pháp hoặc hành vi nào khác?

Bây giờ, hãy nghĩ về một dự án sắp tới. Không quan trọng dự án là gì; . Nó không phải là một ứng dụng hoàn chỉnh; . Thực hiện phân tích hướng đối tượng cơ bản. Xác định các yêu cầu và các đối tượng tương tác. Phác thảo sơ đồ lớp có mức trừu tượng cao nhất trên hệ thống đó. Xác định các đối tượng tương tác chính. Xác định các đối tượng hỗ trợ nhỏ. Đi vào chi tiết các thuộc tính và phương thức của một số thuộc tính thú vị nhất. Đưa các đối tượng khác nhau đến các mức độ trừu tượng khác nhau. Tìm kiếm những nơi mà bạn có thể sử dụng thừa kế hoặc thành phần. Tìm kiếm những nơi mà bạn nên tránh thừa kế

Mục tiêu không phải là thiết kế một hệ thống [mặc dù bạn hoàn toàn có thể làm như vậy nếu khuynh hướng đáp ứng cả tham vọng và thời gian sẵn có]. Mục tiêu là nghĩ về thiết kế hướng đối tượng. Tập trung vào các dự án mà bạn đã thực hiện hoặc dự kiến ​​sẽ thực hiện trong tương lai, chỉ đơn giản là biến nó thành hiện thực.

Cuối cùng, hãy truy cập công cụ tìm kiếm yêu thích của bạn và tra cứu một số hướng dẫn về UML. Có hàng tá, vì vậy hãy tìm một phương pháp phù hợp với phương pháp nghiên cứu ưa thích của bạn. Phác thảo một số sơ đồ lớp hoặc sơ đồ trình tự cho các đối tượng bạn đã xác định trước đó. Đừng quá chú tâm vào việc ghi nhớ cú pháp [xét cho cùng, nếu nó quan trọng, bạn luôn có thể tra cứu lại nó]; . Điều gì đó sẽ đọng lại trong não của bạn và nó có thể giúp giao tiếp dễ dàng hơn một chút nếu bạn có thể nhanh chóng phác thảo sơ đồ cho cuộc thảo luận OOP tiếp theo của mình

Là đối tượng Python 3

Python là ngôn ngữ lập trình hướng đối tượng . Lập trình hướng đối tượng [OOP] tập trung vào việc tạo các mẫu mã có thể tái sử dụng, trái ngược với lập trình thủ tục, tập trung vào các hướng dẫn theo trình tự rõ ràng.

Python có phải là OOP không?

Chủ Đề