Object-oriented – When should something be a class? And are the chosen classes good OO design

class-designdesigndesign-patternsobject-orientedobject-oriented-design

My background:

I am new to programming. Python is my only programming knowledge. I program as a hobby, and I'm teaching myself by reading copious amounts of books.

I understand enough about OOP to write OO software. However, I keep feeling uneasy about the things I write… The design seems messy, etc. And I'm unsure as to what should be a class, method, or function.

I have read OOP books such as, 'Object Oriented Thought'. Such books are useful, however, they always deal with easy topics such as making a 'blackjack' game. The applications that I want to write, however, are not based on easy-to-imagine, real world objects.

The application:

I am currently working on a project. The aim of the software is to download images and video from my favourite blogs. (eg, Google Blogger blogs, or WordPress hosted blogs.)

(Yes, it is easy to make, and I've already made it, but the problem is I want to learn how to make elegant and properly designed OO software.)

Classes:

I have decided on the following classes:

  1. API Client: This will make it easier to deal with sending and receiving various API requests.
  2. BloggerClient, WordPressClient: I will inherit from a generic API Client class, so that I can specialize with specific APIs, eg. Google's, Tumblr's, and WordPress' APIs.
  3. Parser: A generic media parser. This will get the media from the blogs.
  4. BloggerParser, WordPressParser: I will inherit from the generic Parser, so I can grab posts and media specific to each website.

Use Case:

I will present an example of getting images from a WordPress.com blog.

  1. WordPressParser asks WordPressClient to get blog-posts from photography.wordpress.com
    1. WordPressClient sends an API request to WordPress.
    2. WordPress Client receives a response and sends the posts to WordPressParser.
    3. WordPressParser parses the media links/urls from each blog-post.
    4. The media links are downloaded to disk.

The problems:

I actually don't know if I have made good choices here.

For example, I need the media (photo and video) downloaded to disk. In this case should I make 'download_media()' methods in the Parser class, or is it better design to create a Downloader class?

'Parse' could easily be a method, instead I have used 'Parser', so it could easily be a class. I really don't know when something should be a class or a method.

Should there be a class for BlogPosts? It seems to me that blog-posts are objects (the equivalent to pages of a book, perhaps).

I seem to be taking verbs, 'download', 'parse', and then converting them to nouns in order to make them appear as valid classes.

I feel very lost and confused. Again, the purpose for me is to learn how to properly make and design OO software. I'm not looking just to get the program to work.

Here is the sourcecode for each of my classes so far:

API Client: http://pastebin.com/QRdPqM5F

Base Parser: http://pastebin.com/kV8gBEe6

Parser: http://pastebin.com/cC0yPYdK

In terms of extensibility, I will be adding more websites in the future, so I need something maintainable.

I hope someone could advise me as to what I'm doing wrong. You can view my source code in the links above to really see what I'm talking about.

Thank you!

Best Answer

WordPressParser asks WordPressClient to get blog-posts...

Is this really what a parser should do? Asking to get blog posts is not "parsing" by any definition of the term.

It's like scissors sending you an invitation to come over to your local barber shop. Now, scissors surely have their business in making it happen, but triggering this entire chain of events doesn't sound like something they should be in charge of.

For example, I need the media (photo and video) downloaded to disk. In this case should I make 'download_media()' methods in the Parser class, or is it better design to create a Downloader class?

I would create a separate class, because:

  1. Downloading is a different responsibility than parsing - keep single responsibility principle in mind. It helps to keep track of which class does what as the project grows and allows to keep the code flexible - easy to change.

  2. Different parsers may handle downloading in a similar, or even identical manner. By extracting this functionality into a separate class we can avoid code duplication, because the same Downloader implementation can be reused by different Parsers.

Should there be a class for BlogPosts? It seems to me that blog-posts are objects (the equivalent to pages of a book, perhaps).

If they are nothing but strings - sheer text - it might not be necessary, but the cost of creating a BlogPost class isn't all that high and at the very least it would make it explicit throughout your code that such and such variable represents a blog post and nothing else!

A good rule of thumb is to prefer domain specific types over primitive types. BlogPost means something. A piece of text could be just anything. We are only humans and using domain specific types helps us to write bug-free code, because we let the type system guard us against committing type mismatch offenses (eg. confusing a blog post's url link with blog post's content).

Disclaimer: I don't know Python, I approach the question as a universal OOD question. If there is something Python-specific that escapes me here, I'd be happy if someone points it out.

Related Topic