Lớp học không đại diện cho bất cứ điều gì - nó có đúng không?


42

Tôi chỉ thiết kế ứng dụng của mình và tôi không chắc liệu tôi có hiểu RẮN và OOP chính xác không. Các lớp nên làm 1 việc và làm tốt nhưng mặt khác, chúng nên đại diện cho các đối tượng thực mà chúng ta làm việc cùng.

Trong trường hợp của tôi, tôi thực hiện trích xuất tính năng trên một tập dữ liệu và sau đó tôi thực hiện phân tích học máy. Tôi giả sử rằng tôi có thể tạo ba lớp

  1. FeatureExtractor
  2. Bộ dữ liệu
  3. Máy phân tích

Nhưng lớp FeatureExtractor không đại diện cho bất cứ điều gì, nó làm một cái gì đó làm cho nó trở thành một thói quen hơn là một lớp. Nó sẽ chỉ có một hàm sẽ được sử dụng: extract_features ()

Có đúng không khi tạo các lớp không đại diện cho một thứ nhưng làm một thứ?

EDIT: không chắc có vấn đề gì không nhưng tôi đang sử dụng Python

Và nếu extract_features () sẽ trông như thế: có đáng để tạo một lớp đặc biệt để giữ phương thức đó không?

def extract_features(df):
    extr = PhrasesExtractor()
    extr.build_vocabulary(df["Text"].tolist())

    sent = SentimentAnalyser()
    sent.load()

    df = add_features(df, extr.features)
    df = mark_features(df, extr.extract_features)
    df = drop_infrequent_features(df)
    df = another_processing1(df)
    df = another_processing2(df)
    df = another_processing3(df)
    df = set_sentiment(df, sent.get_sentiment)
    return df

13
Điều này trông hoàn toàn tốt như là một chức năng. Xem xét ba điều bạn liệt kê dưới dạng mô-đun là ok và bạn có thể muốn đặt chúng vào các tệp khác nhau, nhưng điều đó không có nghĩa là chúng cần phải là các lớp.
Bergi

31
Xin lưu ý rằng việc sử dụng các phương pháp không phải OO trong Python là khá phổ biến và được chấp nhận.
jpmc26

13
Bạn có thể quan tâm đến Thiết kế hướng tên miền. "Các lớp nên đại diện cho các đối tượng từ thế giới thực" là sai ... chúng nên đại diện cho các đối tượng trong miền . Tên miền thường được liên kết mạnh mẽ với thế giới thực, nhưng tùy thuộc vào ứng dụng, một số thứ có thể hoặc không thể được coi là đối tượng hoặc một số thứ "trong thực tế" có thể kết thúc hoặc được liên kết hoặc giống hệt nhau trong miền của ứng dụng.
Bakuriu

1
Khi bạn trở nên quen thuộc hơn với OOP, tôi nghĩ bạn sẽ thấy rằng các lớp rất hiếm khi tương ứng một-một với các thực thể trong thế giới thực. Ví dụ, đây là một bài luận tranh luận về việc cố gắng nhồi nhét tất cả các chức năng liên quan đến một thực thể trong thế giới thực trong một lớp duy nhất rất thường là một mô hình chống: lập
trình.97things.oreilly.com / wiki / index.php / Lỗi

1
"họ nên đại diện cho các đối tượng thực sự chúng ta làm việc với." không cần thiết. Rất nhiều ngôn ngữ có một lớp luồng đại diện cho một luồng byte, đó là một khái niệm trừu tượng chứ không phải là một 'đối tượng thực'. Về mặt kỹ thuật, một hệ thống tệp không phải là một 'đối tượng thực', nó chỉ là một khái niệm, nhưng đôi khi có các lớp đại diện cho một hệ thống tệp hoặc một phần của nó.
Pharap

Câu trả lời:


96

Các lớp nên làm 1 việc và làm tốt

Vâng, đó thường là một cách tiếp cận tốt.

nhưng mặt khác họ nên đại diện cho đối tượng thực sự mà chúng ta làm việc cùng.

Không, đó là một sự hiểu lầm phổ biến của IMHO. Người mới bắt đầu truy cập OOP thường là "bắt đầu với các đối tượng đại diện cho những thứ từ thế giới thực" , đó là sự thật.

Tuy nhiên, bạn không nên dừng lại với điều này !

Các lớp có thể (và nên) được sử dụng để cấu trúc chương trình của bạn theo nhiều cách khác nhau. Mô hình hóa các đối tượng từ thế giới thực là một khía cạnh của điều này, nhưng không phải là duy nhất. Tạo các mô-đun hoặc các thành phần cho một nhiệm vụ cụ thể là một trường hợp sử dụng hợp lý khác cho các lớp. Một "trình trích xuất tính năng" có thể là một mô-đun như vậy và thậm chí nó chỉ chứa một phương thức công khaiextract_features() , tôi sẽ ngạc nhiên nếu không chứa nhiều phương thức riêng tư và có thể một số trạng thái được chia sẻ. Vì vậy, có một lớp học FeatureExtractorsẽ giới thiệu một vị trí tự nhiên cho các phương pháp riêng tư này.

Lưu ý bên lề: trong các ngôn ngữ như Python hỗ trợ khái niệm mô-đun riêng biệt, người ta cũng có thể sử dụng mô-đun FeatureExtractorcho việc này, nhưng trong bối cảnh của câu hỏi này, đây là IMHO một sự khác biệt không đáng kể.

Hơn nữa, một "trình trích xuất tính năng" có thể được hình dung là "một người hoặc bot trích xuất các tính năng". Đó là một "thứ" trừu tượng, có thể không phải là thứ bạn sẽ tìm thấy trong thế giới thực, nhưng bản thân cái tên là một sự trừu tượng hữu ích, mang đến cho mọi người một khái niệm về trách nhiệm của lớp đó là gì. Vì vậy, tôi không đồng ý rằng lớp này không "đại diện cho bất cứ điều gì".


33
Tôi đặc biệt thích rằng bạn đề cập đến vấn đề nội bộ. Tôi thường thấy rằng đó là yếu tố quyết định cho việc tôi tạo một thứ gì đó thành một lớp hay một hàm trong Python.
David Z

17
Bạn dường như khuyên bạn nên viêm lớp Class. Đừng tạo một lớp cho cái này, nó là một antipotype kiểu Java. Nếu đó là một chức năng, làm cho nó một chức năng. Trạng thái bên trong là không liên quan: các chức năng có thể có điều đó (thông qua việc đóng cửa).
Konrad Rudolph

25
@KonradRudolph: bạn dường như đã bỏ lỡ rằng đây không phải là về việc tạo một chức năng. Đây là về một đoạn mã yêu cầu một số chức năng, một tên chung và có thể một số trạng thái được chia sẻ. Sử dụng một mô-đun cho điều này có thể hợp lý trong các ngôn ngữ với khái niệm mô-đun ngoài các lớp.
Doc Brown

8
@DocBrown Tôi sẽ không đồng ý. Đó là một lớp học với một phương thức công khai. API khôn ngoan, không thể phân biệt với một chức năng. Xem câu trả lời của tôi để biết chi tiết. Sử dụng các lớp phương thức đơn có thể được biện minh nếu bạn cần tạo một loại cụ thể để thể hiện một trạng thái. Nhưng đây không phải là trường hợp ở đây (và thậm chí sau đó, các chức năng đôi khi có thể được sử dụng).
Konrad Rudolph

6
@DocBrown Tôi bắt đầu hiểu ý của bạn: bạn đang nói về các chức năng được gọi từ bên trong extract_features? Tôi chỉ giả định rằng chúng là các chức năng công cộng từ nơi khác. Đủ công bằng, tôi đồng ý rằng nếu đây là riêng tư thì có lẽ họ nên đi vào một mô-đun (nhưng vẫn: không phải là một lớp, trừ khi họ chia sẻ trạng thái), cùng với extract_features. (Điều đó nói rằng, tất nhiên bạn có thể khai báo chúng cục bộ bên trong chức năng đó.)
Konrad Rudolph

44

Doc Brown là tại chỗ: các lớp không cần phải đại diện cho các đối tượng trong thế giới thực. Họ chỉ cần có ích . Các lớp học về cơ bản chỉ là các loại bổ sung, và những gì không inthoặc stringtương ứng với trong thế giới thực? Chúng là những mô tả trừu tượng, không cụ thể, những thứ hữu hình.

Điều đó nói rằng, trường hợp của bạn là đặc biệt. Theo mô tả của bạn:

Và nếu extract_features () sẽ trông như thế: có đáng để tạo một lớp đặc biệt để giữ phương thức đó không?

Bạn hoàn toàn đúng: nếu mã của bạn như được hiển thị, sẽ không có việc sử dụng nó thành một lớp. Có một cuộc nói chuyện nổi tiếng lập luận rằng việc sử dụng các lớp như vậy trong Python là mùi mã và các hàm đơn giản thường là đủ. Trường hợp của bạn là một ví dụ hoàn hảo về điều này.

Việc lạm dụng các lớp là do thực tế là OOP đã trở thành xu hướng chủ đạo với Java trong những năm 1990. Thật không may, Java tại thời điểm đó thiếu một số tính năng ngôn ngữ hiện đại (chẳng hạn như các bao đóng), điều đó có nghĩa là nhiều khái niệm khó hoặc không thể diễn đạt nếu không sử dụng các lớp. Chẳng hạn, trong Java gần đây không thể có các phương thức mang trạng thái (tức là đóng). Thay vào đó, bạn phải viết một lớp để mang trạng thái và tiếp xúc với một phương thức duy nhất (được gọi là một cái gì đó giống như invoke).

Thật không may, phong cách lập trình này đã trở nên phổ biến vượt xa Java (một phần do một cuốn sách kỹ thuật phần mềm có ảnh hưởng rất khác), ngay cả trong các ngôn ngữ không yêu cầu cách giải quyết như vậy.

Trong Python, các lớp rõ ràng là một công cụ rất quan trọng và nên được sử dụng tự do. Nhưng chúng không phải là công cụ duy nhất và không có lý do gì để sử dụng chúng khi chúng không có ý nghĩa. Đó là một quan niệm sai lầm phổ biến rằng các chức năng miễn phí không có chỗ trong OOP.


Sẽ rất hữu ích khi thêm rằng nếu các hàm được gọi trong ví dụ trên thực tế là các hàm riêng tư, việc gói chúng trong một mô-đun hoặc lớp sẽ hoàn toàn phù hợp. Nếu không, tôi hoàn toàn đồng ý.
Leliel

11
Cũng hữu ích để nhớ rằng "OOP" không có nghĩa là "viết một loạt các lớp". Các hàm là các đối tượng trong Python, vì vậy không cần phải coi đây là "không phải OOP". Thay vào đó, nó chỉ đơn giản là sử dụng lại các loại / lớp tích hợp và "tái sử dụng" là một trong những hạt sạn trong lập trình. Việc gói nó trong một lớp sẽ ngăn chặn việc sử dụng lại, vì không có gì tương thích với API mới này (trừ khi __call__được xác định, trong trường hợp đó chỉ sử dụng một hàm!)
Warbo

3
Ngoài ra về chủ đề "các lớp so với các chức năng tự do": eev.ee/blog/2013/03/03/iêu
Joker_vD

1
Không phải vậy đâu, mặc dù trong Python "các hàm tự do" cũng là các đối tượng có kiểu phơi bày một phương thức __call__()? Điều đó thực sự rất khác với một thể hiện của lớp bên trong ẩn danh? Cú pháp, chắc chắn nhưng từ một thiết kế ngôn ngữ, có vẻ như một sự khác biệt ít quan trọng hơn bạn trình bày ở đây.
JimmyJames

1
@JimmyJames Phải. Toàn bộ vấn đề là họ cung cấp cùng chức năng cho mục đích cụ thể nhưng sử dụng đơn giản hơn.
Konrad Rudolph

36

Tôi chỉ thiết kế ứng dụng của mình và tôi không chắc liệu tôi có hiểu RẮN và OOP chính xác không.

Đã ở đây hơn 20 năm và tôi cũng không chắc chắn.

Các lớp nên làm 1 việc và làm tốt

Khó đi sai đây.

họ nên đại diện cho các đối tượng thực sự chúng ta làm việc với.

Ồ vậy sao Hãy để tôi giới thiệu cho bạn một lớp học phổ biến và thành công nhất mọi thời đại : String. Chúng tôi sử dụng nó cho văn bản. Và đối tượng trong thế giới thực mà nó đại diện là:

Ngư dân giữ 10 con cá treo lơ lửng trên dây

Tại sao không, không phải tất cả các lập trình viên đều bị ám ảnh với câu cá. Ở đây chúng tôi đang sử dụng một cái gì đó gọi là một phép ẩn dụ. Bạn có thể tạo ra những mô hình của những thứ không thực sự tồn tại. Đó là ý tưởng phải rõ ràng. Bạn đang tạo ra hình ảnh trong tâm trí của độc giả của bạn. Những hình ảnh đó không phải là thật. Chỉ cần hiểu dễ dàng.

Một thiết kế OOP tốt sẽ phân cụm các thông điệp (phương thức) xung quanh dữ liệu (trạng thái) để các phản ứng đối với các thông báo đó có thể thay đổi tùy thuộc vào dữ liệu đó. Nếu làm điều đó mô hình một số điều thế giới thực, spiffy. Nếu không, oh tốt. Miễn là nó có ý nghĩa với người đọc, nó ổn.

Bây giờ chắc chắn, bạn có thể nghĩ về nó như thế này:

thư lễ hội bị đình chỉ từ một chuỗi đọc "HÃY LÀM NHỮNG ĐIỀU!"

nhưng nếu bạn nghĩ rằng điều này phải tồn tại trong thế giới thực trước khi bạn có thể sử dụng phép ẩn dụ, thì sự nghiệp lập trình của bạn sẽ liên quan đến rất nhiều nghệ thuật và thủ công.


1
Một chuỗi hình ảnh đẹp ...
Zev Spitz

Tại thời điểm này tôi không chắc "chuỗi" thậm chí là ẩn dụ. Nó chỉ có một cụ thể có nghĩa là trong lĩnh vực lập trình, cũng như những từ như classtablecolumn...
Kyralessa

@Kyralessa bạn ether dạy cho người mới về phép ẩn dụ hoặc bạn để nó là phép màu đối với họ. Xin hãy cứu tôi khỏi những lập trình viên tin vào phép thuật.
candied_orange

6

Coi chừng! Không nơi nào RẮN nói rằng một lớp chỉ nên "làm một việc". Nếu đó là trường hợp, các lớp sẽ chỉ có một phương thức duy nhất và thực sự sẽ không có sự khác biệt giữa các lớp và hàm.

RẮN nói rằng một lớp nên thể hiện một trách nhiệm duy nhất . Đây là những loại giống như phản ứng của những người trong một nhóm: Người lái xe, luật sư, kẻ móc túi, người thiết kế đồ họa, v.v ... Mỗi người trong số họ có thể thực hiện nhiều nhiệm vụ (liên quan), nhưng tất cả đều liên quan đến một trách nhiệm.

Điểm chính của điều này là - nếu có sự thay đổi trong các yêu cầu, lý tưởng nhất là bạn chỉ cần sửa đổi một lớp duy nhất. Điều này chỉ làm cho mã dễ hiểu hơn, dễ sửa đổi hơn và giảm rủi ro.

Không có quy tắc rằng một đối tượng nên đại diện cho "một điều thực". Đây chỉ là truyền thuyết về hàng hóa vì OO ban đầu được phát minh để sử dụng trong mô phỏng. Nhưng chương trình của bạn không phải là mô phỏng (một vài ứng dụng OO hiện đại), vì vậy quy tắc này không được áp dụng. Miễn là mỗi lớp có trách nhiệm được xác định rõ, bạn sẽ ổn.

Nếu một lớp thực sự chỉ có một phương thức duy nhất lớp đó không có bất kỳ trạng thái nào, bạn có thể xem xét biến nó thành một hàm độc lập. Điều này là tốt hàng ngày và tuân theo các nguyên tắc KISS và YAGNI - không cần phải tạo một lớp nếu bạn có thể giải quyết nó bằng một hàm. Mặt khác, nếu bạn có lý do để tin rằng bạn có thể cần trạng thái nội bộ hoặc nhiều triển khai, bạn cũng có thể biến nó thành một lớp học trước. Bạn sẽ phải sử dụng phán đoán tốt nhất của bạn ở đây.


+1 cho "không cần tạo lớp nếu bạn có thể giải quyết nó bằng hàm". Đôi khi ai đó cần nói lên sự thật.
tchrist

5

Có đúng không khi tạo các lớp không đại diện cho một thứ nhưng làm một thứ?

Nói chung là ổn.

Không có một chút mô tả cụ thể hơn những gì FeatureExtractorlớp được cho là chính xác thì thật khó để nói.

Dù sao, ngay cả khi FeatureExtractorchỉ hiển thị một extract_features()chức năng công khai , tôi có thể nghĩ đến việc cấu hình nó với một Strategylớp, trong đó xác định chính xác cách trích xuất nên được thực hiện.

Một ví dụ khác là một lớp có chức năng Mẫu .

Và có nhiều Mẫu thiết kế hành vi hơn , dựa trên các mô hình lớp.


Khi bạn thêm một số mã để làm rõ.

Và nếu extract_features () sẽ trông như thế: có đáng để tạo một lớp đặc biệt để giữ phương thức đó không?

Dòng

 sent = SentimentAnalyser()

chính xác bao gồm những gì tôi có nghĩa là bạn có thể cấu hình một lớp với Chiến lược .

Nếu bạn có một giao diện cho SentimentAnalyserlớp đó , bạn có thể chuyển nó đến FeatureExtractorlớp tại điểm xây dựng của nó, thay vì khớp trực tiếp với việc triển khai cụ thể đó trong chức năng của bạn.


2
Tôi không thấy một lý do để thêm độ phức tạp (một FeatureExtractorlớp) chỉ để giới thiệu sự phức tạp hơn nữa (một giao diện cho SentimentAnalyserlớp). Nếu việc tách rời là mong muốn, thì extract_featurescó thể lấy get_sentimenthàm làm đối số ( loadcuộc gọi dường như không phụ thuộc vào hàm và chỉ được gọi cho các hiệu ứng của nó). Cũng lưu ý rằng Python không có / khuyến khích giao diện.
Warbo

1
@warbo - ngay cả khi bạn cung cấp hàm làm đối số, bằng cách biến nó thành hàm, bạn hạn chế các triển khai tiềm năng phù hợp với định dạng của hàm, nhưng nếu cần phải quản lý trạng thái liên tục giữa một lần gọi và tiếp theo (ví dụ a CacheingFeatureExtractorhoặc a TimeSeriesDependentFeatureExtractor) thì một đối tượng sẽ phù hợp hơn nhiều. Chỉ vì không cần một đối tượng hiện tại không có nghĩa là sẽ không bao giờ có.
Jules

3
@Jules Trước tiên, bạn không cần nó (YAGNI), thứ hai là các hàm Python có thể tham chiếu trạng thái liên tục (đóng) nếu bạn cần (bạn sẽ không), thứ ba sử dụng hàm không hạn chế bất cứ điều gì vì bất kỳ đối tượng nào có __call__phương thức sẽ tương thích nếu bạn cần nó (bạn sẽ không), thứ tư bằng cách thêm một trình bao bọc giống như FeatureExtractorbạn đang làm cho mã không tương thích với tất cả các mã khác từng được viết (trừ khi bạn cung cấp một __call__phương thức, trong trường hợp đó, một hàm sẽ đơn giản hơn rõ ràng )
Warbo

0

Các mô hình và tất cả các ngôn ngữ / khái niệm ưa thích sang một bên: những gì bạn đã vấp phải là một Công việc hoặc Quy trình hàng loạt .

Vào cuối ngày, ngay cả một chương trình OOP thuần túy cũng cần bằng cách nào đó được điều khiển bởi một cái gì đó, để thực sự thực hiện công việc; phải có một điểm vào bằng cách nào đó. Ví dụ, trong mẫu MVC, trình điều khiển "C" nhận các sự kiện nhấp chuột, v.v. từ GUI và sau đó phối hợp các thành phần khác. Trong các công cụ dòng lệnh cổ điển, một hàm "chính" sẽ làm tương tự.

Có đúng không khi tạo các lớp không đại diện cho một thứ nhưng làm một thứ?

Lớp của bạn đại diện cho một thực thể làm một cái gì đó và sắp xếp mọi thứ khác. Bạn có thể đặt tên cho nó là Trình điều khiển , Công việc , Chính hoặc bất cứ điều gì xuất hiện trong tâm trí.

Và nếu extract_features () sẽ trông như thế: có đáng để tạo một lớp đặc biệt để giữ phương thức đó không?

Điều đó phụ thuộc vào hoàn cảnh (và tôi không quen với cách thông thường được thực hiện trong Python). Nếu đây chỉ là một công cụ dòng lệnh one-shot nhỏ, thì một phương thức thay vì một lớp sẽ ổn. Phiên bản đầu tiên của chương trình của bạn có thể thoát khỏi một phương thức, chắc chắn. Nếu, sau này, bạn thấy rằng bạn kết thúc với hàng tá phương thức như vậy, thậm chí có thể có các biến toàn cục được trộn lẫn, thì đã đến lúc tái cấu trúc thành các lớp.


3
Lưu ý rằng trong các tình huống như thế này, việc gọi các "phương thức" thủ tục độc lập có thể gây nhầm lẫn. Hầu hết các ngôn ngữ, bao gồm Python, gọi chúng là "hàm". "Phương thức" là các hàm / thủ tục được liên kết với một thể hiện cụ thể của một lớp, điều này trái ngược với cách sử dụng thuật ngữ của bạn :)
Warbo

Đúng vậy, @Warbo. Hoặc chúng ta có thể gọi chúng là thủ tục hoặc defun hoặc sub hoặc ...; và chúng có thể là các phương thức lớp (sic) không liên quan đến một thể hiện. Tôi hy vọng người đọc nhẹ nhàng sẽ có thể trừu tượng đi ý nghĩa dự định. :)
AnoE

@Warbo thật tốt khi biết điều đó! Hầu hết các tài liệu học tập tôi đã đi qua nói rằng các thuật ngữ chức năng và phương pháp có thể thay thế cho nhau và đó chỉ là một sở thích phụ thuộc vào ngôn ngữ.
Dom

@Dom Nói chung, một hàm "" thuần ") là ánh xạ từ giá trị đầu vào sang giá trị đầu ra; "thủ tục" là một chức năng cũng có thể gây ra hiệu ứng (ví dụ như xóa một tệp); cả hai đều được gửi tĩnh (tức là tra cứu trong phạm vi từ vựng). "Phương thức" là một hàm hoặc thủ tục (thường) được gửi động (tra cứu) từ một giá trị (được gọi là "đối tượng"), được tự động ràng buộc với một đối số (ẩn thishoặc rõ ràng self) của phương thức. Các phương thức của một đối tượng được đệ quy "công khai" lẫn nhau, do đó việc thay thế foogây ra tất cả các self.foolệnh gọi sử dụng thay thế này.
Warbo

0

Chúng ta có thể nghĩ về OOP như mô hình hóa hành vi của một hệ thống. Lưu ý rằng hệ thống không phải tồn tại trong 'thế giới thực', mặc dù các phép ẩn dụ trong thế giới thực đôi khi có thể hữu ích (ví dụ: "đường ống", "nhà máy", v.v.).

Nếu hệ thống mong muốn của chúng ta quá phức tạp để mô hình hóa tất cả cùng một lúc, chúng ta có thể chia nó thành các phần nhỏ hơn và mô hình hóa chúng ("miền vấn đề"), có thể liên quan đến việc phá vỡ thêm, và cứ thế cho đến khi chúng ta có được những mảnh ghép có hành vi phù hợp (nhiều hơn hoặc ít hơn) của một số đối tượng ngôn ngữ tích hợp như số, chuỗi, danh sách, v.v.

Khi chúng ta có những mảnh đơn giản đó, chúng ta có thể kết hợp chúng lại với nhau để mô tả hành vi của các mảnh lớn hơn, chúng ta có thể kết hợp với nhau thành các mảnh lớn hơn, và cứ như vậy cho đến khi chúng ta có thể mô tả tất cả các thành phần của miền cần thiết cho toàn bộ hệ thống.

Đây là giai đoạn "kết hợp với nhau" nơi chúng ta có thể viết một số lớp. Chúng ta viết các lớp khi không có một đối tượng hiện hành theo cách chúng ta muốn. Ví dụ: tên miền của chúng tôi có thể chứa "foos", bộ sưu tập các foos được gọi là "bar" và bộ sưu tập các thanh được gọi là "bazs". Chúng tôi có thể nhận thấy rằng foos đủ đơn giản để mô hình với các chuỗi, vì vậy chúng tôi làm điều đó. Chúng tôi thấy rằng các thanh yêu cầu nội dung của chúng phải tuân theo một số ràng buộc cụ thể không khớp với bất cứ điều gì Python cung cấp, trong trường hợp đó chúng tôi có thể viết một lớp mới để thực thi ràng buộc này. Có lẽ bazs không có đặc thù như vậy, vì vậy chúng tôi chỉ có thể đại diện cho họ với một danh sách.

Lưu ý rằng chúng ta có thể viết một lớp mới cho mỗi một trong các thành phần đó (foos, bar và bazs), nhưng chúng ta không cần phải có một cái gì đó có hành vi đúng. Đặc biệt, để một lớp trở nên hữu ích, nó cần phải 'cung cấp' thứ gì đó (dữ liệu, phương thức, hằng, lớp con, v.v.), vì vậy ngay cả khi chúng ta có nhiều lớp lớp tùy chỉnh, cuối cùng chúng ta cũng phải sử dụng một số tính năng tích hợp; ví dụ, nếu chúng ta đã viết một lớp mới cho foos thì có lẽ nó chỉ chứa một chuỗi, vậy tại sao bạn không quên lớp foo và thay vào đó là lớp bar chứa các chuỗi đó? Hãy nhớ rằng các lớp cũng là một đối tượng tích hợp, chúng chỉ là một đối tượng đặc biệt linh hoạt.

Khi chúng tôi có mô hình miền của mình, chúng tôi có thể lấy một số trường hợp cụ thể của các phần đó và sắp xếp chúng thành một "mô phỏng" của hệ thống cụ thể mà chúng tôi muốn mô hình hóa (ví dụ: "hệ thống máy học cho ...").

Khi chúng tôi có mô phỏng này, chúng tôi có thể chạy nó và xin chào, chúng tôi có một hệ thống học máy (mô phỏng) hoạt động cho ... (hoặc bất cứ điều gì khác mà chúng tôi đang tạo mô hình).


Bây giờ, trong tình huống cụ thể của bạn, bạn đang cố gắng mô hình hóa hành vi của thành phần "trình trích xuất tính năng". Câu hỏi là, có bất kỳ đối tượng tích hợp nào hoạt động như một "trình trích xuất tính năng", hoặc bạn sẽ cần phải chia nó thành những điều đơn giản hơn? Có vẻ như các trình trích xuất tính năng hoạt động rất giống các đối tượng hàm, vì vậy tôi nghĩ rằng bạn sẽ ổn khi sử dụng chúng làm mô hình của mình.


Một điều cần lưu ý khi tìm hiểu về các loại khái niệm này là các ngôn ngữ khác nhau có thể cung cấp các tính năng và đối tượng tích hợp khác nhau (và tất nhiên, một số thậm chí không sử dụng thuật ngữ như "đối tượng"!). Do đó, các giải pháp có ý nghĩa trong một ngôn ngữ có thể ít hữu ích hơn trong một ngôn ngữ khác (điều này thậm chí có thể áp dụng cho các phiên bản khác nhau của cùng một ngôn ngữ!).

Trong lịch sử, rất nhiều tài liệu OOP (đặc biệt là "các mẫu thiết kế") đã tập trung vào Java, khá khác với Python. Ví dụ, các lớp Java không phải là các đối tượng, Java không có các đối tượng hàm cho đến gần đây, Java có kiểm tra kiểu nghiêm ngặt (khuyến khích các giao diện và phân lớp) trong khi Python khuyến khích gõ vịt, Java không có các đối tượng mô đun, số nguyên Java / phao / v.v. không phải là các đối tượng, lập trình meta / hướng nội trong Java yêu cầu "phản chiếu", v.v.

Tôi không cố gắng chọn Java (như một ví dụ khác, rất nhiều lý thuyết OOP xoay quanh Smalltalk, một lần nữa rất khác với Python), tôi chỉ cố gắng chỉ ra rằng chúng ta phải suy nghĩ rất kỹ về bối cảnh và những hạn chế trong đó các giải pháp đã được phát triển và liệu điều đó có phù hợp với tình huống chúng ta đang gặp phải hay không.

Trong trường hợp của bạn, một đối tượng chức năng có vẻ như là một lựa chọn tốt. Nếu bạn đang tự hỏi tại sao một số hướng dẫn "thực hành tốt nhất" không đề cập đến các đối tượng hàm như một giải pháp khả thi, thì đó có thể đơn giản là vì các hướng dẫn đó được viết cho các phiên bản Java cũ!


0

Nói một cách thực tế, khi tôi có một "thứ linh tinh làm điều gì đó quan trọng và cần tách biệt", và nó không có một ngôi nhà rõ ràng, tôi đặt nó trong một Utilitiesphần và sử dụng nó như là quy ước đặt tên của tôi. I E. FeatureExtractionUtility.

Quên về số lượng phương thức trong một lớp; một phương pháp duy nhất hôm nay có thể cần phát triển thành năm phương pháp vào ngày mai. Vấn đề là một cấu trúc tổ chức rõ ràng và nhất quán, chẳng hạn như một khu vực tiện ích cho các bộ sưu tập các chức năng linh tinh.

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.