General programming issue. When to use OOP?

My program should do 2 things.

  • Extract material from the web page.

  • Make material with a web page.

However, there are many web pages such as Twitter and Facebook.

Should I do this?

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

Or should I have some kind of class? When is it recommended to use classes, and when is it recommended to just use functions?

+2
source share
6 answers

My favorite rule of thumb: if in doubt (the unspoken assumption: "you are a reasonable person, not a fanatic" ;-), create and use some classes. I often found that code refactoring, originally written as simple functions, into classes - for example, at any time when simple functions are the “best way to communicate with each other” - these are globals, that the smell of code, a strong hint that system factoring not very good - and often refactoring the OOP path is a smart solution to this.

Python is a multi-paradigm, but its central paradigm is OOP (such as C ++). When a procedural or functional approach (perhaps through generators and c) is optimal for some part of the system, which usually stands out - for example, static functions are also a smell of code, and if your classes have a significant amount of such, this is a hint for reorganizing things to avoid this requirements.

So, assuming that you have a rich understanding of all the paradigms that Python gives - if in doubt, this suggests that you probably want to switch to OOP for this part of your system! Just because Python supports OOP even more than it supports functional programming, etc.

From your very skeletal code, it seems to me that each extraction / process pair belongs together and probably should report state, so a small set of classes with extraction and processing methods seems natural.

+10
source

"My program should do 2 things."

When you start like this, objects are not visible. You are wrong in the future.

Change your mindset.

"My program works with the material"

This is OO thinking. What “things” does your program work with? Define the material. These are your main classes. There is a class for every type of thing.

"My program receives material from various sources"

There is a class for each source here.

"My program displays material"

This is usually a combination of access methods for materials, as well as some “reporting” classes that collect parts of the material to display it.

When you start defining “stuff” rather than “doing,” you do OO programming. OO refers to everything, since each individual program includes "do" and "stuff." You can choose to “make” POV (which can be procedural or functional), or you can choose “stuff” POV (object-oriented).

+14
source

This is for you. I personally try to stay away from Java style classes when programming in python. Instead, I use dicts and / or simple objects.

For example, after defining these functions (those that you defined in the question), I would create a simple dict, perhaps like this:

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

or, better yet, use introspection to automatically get the process / extraction function:

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

Where module is the current module (or the module that has these functions).

To get this module as an object:

 import sys module = sys.modules[__name__] 

Assuming, of course, that the main core function does something like this:

  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
+3
source

Put so much common material together in one function. Once you have packed so many possibilities, create a mechanism for branching for the corresponding function for each website.

One possible way to do this is with python if/else suggestions, but if you have many of these features, you might need something more elegant, like

F = __import__('yourproject.facebookmodule')

This allows you to put facebook-specific code in its own area. Since you are passing the __import__() , you can change it at runtime based on which site you are accessing, and then just call the F function in your common worker code.

More on this here: http://effbot.org/zone/import-confusion.htm

+2
source

You use OOP when it makes sense, when it speeds up solution development, and when it makes it easier to read, understand, and support the end result.

In this case, it may make sense to create a common Extractor interface / class and then have subclasses for Twitter, MySpace, Facebook, etc., but it really depends on how it depends on a particular site. The idea of ​​this kind of abstraction is to hide such details. If you can do this, it makes sense. If you cannot, you may need a different approach.

It is also possible that similar advantages can be obtained due to the good decomposition of the procedural solution.

Remember that at the end of the day these are all just tools. Choose the best one for this particular job, rather than picking a hammer, and then trying to turn everything into a nail.

+1
source

I regularly define classes for solving problems for several reasons, I will describe an example of my thinking below. I have no compromise on mixing OO models and procedural styles, which are often more a reflection of your working society than your personal religion. Often this works to have a procedural facade of the class hierarchy, if other proponents expect it. (Please excuse the PHP syntax.)

I develop strategies, and I can follow the general model. Therefore, a possible simulation of your task may include getting something to chew on the submitted URLs. This works if you want to simplify external logic and remove conventions. This shows that I can use DNRY for the gather () method.
 // 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 */ } } 

I create a set of routines that are ideally hidden and nonetheless accessible. An example of this is a class that defines toolbar methods common to a task. More specific tasks can expand the set of tools for developing your own behavior.
 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 ); } } 

I want to organize my code in order to convey a broader meaning to the maintainer. Keep in mind that if I have at least one remote service that I interact with, I could dive into different APIs within my interface, and I want to group these procedures on similar topics. Below I show an example of how I like to define a class that defines common constants, a class that defines the basic methods of service, and a more specific class for meteorological warnings, because the warning should know how to update itself, and this is more specific than the weather service itself but also uses WeatherAPI constants.
 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(); 
+1
source

All Articles