簡體   English   中英

一般編程問題。 什么時候使用OOP?

[英]General programming question. When to use OOP?

我的程序需要做兩件事。

  1. 從網頁中提取內容。

  2. 做一些網頁的東西。

但是,有很多網頁,如Twitter和Facebook。

我應該這樣做嗎?

def facebookExtract():
    code here
def twitterExtract():
    code here
def myspaceExtract():
    code here
def facebookProcess():
    code here
def twitterProcess():
    code here
def myspaceProcess():
    code here

或者,我應該上某種課嗎? 什么時候建議使用類,什么時候建議只使用函數?

“我的計划需要做兩件事。”

當你這樣開始時,無法看到對象。 你的觀點是不對的。

改變你的想法。

“我的程序與東西一起工作”

這是OO的想法。 你的程序使用什么“東西”? 定義東西。 那些是你的基礎課程。 每種東西都有一個類。

“我的程序從各種來源獲取東西”

每個來源都有一個班級。

“我的程序顯示的東西”

這通常是東西的訪問器方法和一些“報告”類的組合,這些類收集部分內容以顯示它。

當你開始定義“東西”而不是“做”時,你正在做OO編程。 OO適用於所有事物,因為每個程序都涉及“做”和“東西”。 你可以選擇“做”POV(可以是程序性的或功能性的),或者你可以選擇“東西”POV(面向對象)。

我最喜歡的經驗法則:如果你有疑問(不言而喻的假設:“你是一個理性的人而不是狂熱的人”;-),那就制作並使用一些課程。 我經常發現自己將最初編寫為簡單函數的代碼重構為類 - 例如,任何時候簡單函數與彼此通信的最佳方式都是全局變量,這是代碼氣味,強烈暗示系統的分解是不是很好 - 通常重構OOP方式是一個合理的解決方案。

Python是多范式的,但它的核心范例是OOP(很像C ++)。 當程序或功能方法(可能通過生成器和c)對於系統的某些部分來說是最佳的時,這通常是突出的 - 例如,靜態函數也是代碼氣味,並且如果您的類具有任何大量的那些,那么提示重構事物以避免這種要求。

因此,假設您對Python提供的所有范例有着豐富的把握 - 如果您仍然存在疑問,那么這表明您可能希望為系統的那一部分進行OOP! 僅僅因為Python支持OOP甚至比它支持函數式編程等更全面。

從您的骨架代碼來看,在我看來,每個提取/進程對都屬於一起,可能需要通信狀態,因此一小部分具有提取和處理方法的類似乎很自然。

由你決定。 在python中編程時,我個人試圖遠離Java風格的類。 相反,我使用dicts和/或簡單對象。

例如,在定義了這些函數(你在問題中定義的函數)之后,我會創建一個簡單的dict,也許是這樣的:

{ 'facebook' : { 'process' : facebookProcess, 'extract': facebookExtract }, 
 ..... 
}

或者,更好的是,使用內省自動獲取進程/提取函數:

def processor(sitename):
    return getattr(module, sitename + 'Process')

def extractor(sitename):
    return getattr(module, sitename + 'Extractor')

其中module是當前模塊(或具有這些功能的模塊)。

要將此模塊作為對象:

import sys
module = sys.modules[__name__]

當然假設泛型main函數做了這樣的事情:

figure out sitename based on input.
    get the extractor function for the site
    get processor function for the site
    call the extractor then the processor

將盡可能多的常見內容放在一個函數中。 一旦你盡可能多地考慮了因素,就建立一個機制來分支到每個網站的相應功能。

一種可能的方法是使用python的if/else子句,但是如果你有很多這樣的函數,你可能想要更優雅的東西,比如

F = __import__('yourproject.facebookmodule')

這使您可以將特定於facebook的代碼放在其自己的區域中。 由於您傳遞__import__()一個字符串,您可以根據您正在訪問的站點在運行時修改它,然后只需在您的通用工作程序代碼中調用函數F.

更多相關內容: http//effbot.org/zone/import-confusion.htm

您可以在有意義的時候使用OOP,它可以更快地開發解決方案,並且可以使最終結果更易於閱讀,理解和維護。

在這種情況下,創建一個通用的Extractor接口/類然后有Twitter,MySpace,Facebook等的子類可能是有意義的,但這實際上取決於特定於站點的提取方式。 這種抽象的想法是隱藏這些細節。 如果你能做到,那就有意義了。 如果你不能,你可能需要一個不同的方法。

也可以從程序解決方案的良好分解中獲得類似的益處。

記住,在一天結束時,所有這些東西都只是工具。 選擇最適合那個特定工作的工作,而不是挑選錘子,然后嘗試將所有東西變成釘子。

我經常定義解決問題的課程有幾個原因,我將在下面給出一個我的想法的例子。 我沒有關於混合OO模型和程序風格的任何內容,這通常更多地反映了你的工作社會而不是個人宗教。 如果這是其他維護者所期望的,那么它通常可以為類層次結構設置程序外觀。 (請原諒PHP語法。)

  • 我正在制定策略,我可以遵循通用模型。 因此,對您的任務進行可能的建模可能涉及獲取一些東西來咀嚼傳遞的URL。 如果您想要簡化外部邏輯並刪除條件,則此方法有效。 這表明我可以將DNRY用於gather()方法。

     // batch process method function MunchPages( $list_of_urls ) { foreach( $list_of_urls as $url ) { $muncher = PageMuncher::MuncherForUrl( $url ); $muncher->gather(); $muncher->process(); } } // factory method encaps strategy selection function MuncherForUrl( $url ) { if( strpos( $url, 'facebook.com' )) return new FacebookPageMuncher( $url ); if( ... ) return new .... ; } // common tasks defined in base PageMuncher class PageMuncher { function gather() { /* use some curl or what */ } function process() {} } class FacebookPageMuncher extends PageMuncher { function process() { /* I do it 'this' way for FB */ } } 

  • 我正在創建一組理想隱藏的例程,更好的是共享。 這方面的一個例子可能是擁有一個定義任務共有的工具箱方法的類。 更具體的任務可以擴展工具箱以開發自己的行為。

     class PageMuncherUtils { static function begin( $html, $context ) { // process assertions about html and context } static function report_fail( $context ) {} static function exit_retry( $context ) {} } // elsewhere I compose the methods in cases I don't wish to inherit them class TwitterPageMuncher { function validateAnchor( $html, $context ) { if( ! PageMuncherUtils::begin( $html, $context )) return PageMuncherUtils::report_fail( $context ); } } 

  • 我想組織我的代碼來向維護者傳達更廣泛的意義。 考慮一下,如果我有一個遠程服務我正在接口,我可能會在他們的界面中潛入不同的API,我想將這些例程分組到類似的主題中。 下面,我展示了一個示例,我喜歡定義一個定義公共常量的類,一個定義基本服務方法的類,以及一個更具體的天氣警報類,因為警報應該知道如何刷新自己,它比天氣更具體服務本身,但也利用WeatherAPI常量。

     class WeatherAPI { const URL = 'http://weather.net'; const URI_TOMORROW = '/nextday/'; const URI_YESTERDAY= '/yesterday/'; const API_KEY = '123'; } class WeatherService { function get( $uri ) { } function forecast( $dateurl ) { } function alerts( $dateurl ) { return new WeatherAlert( $this->get( WeatherAPI::URL.$date ."?api=".WeatherAPI::API_KEY )); } } class WeatherAlert { function refresh() {} } // exercise: $alert = WeatherService::alerts( WeatherAPI::URI_TOMORROW ); $alert->refresh(); 
  • 暫無
    暫無

    聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

     
    粵ICP備18138465號  © 2020-2024 STACKOOM.COM