Design of my project

Cameron Simpson cs at cskk.id.au
Wed Jun 13 18:35:13 EDT 2018


On 13Jun2018 15:23, Fabien LUCE <fabienluce at gmail.com> wrote:
>Here is a small picture of my project.
>I'd like to fetch several datas from a website representing races results.
>Each line of the result contains rank, runner's name and other attributes
>of the runner (like club etc...).
>For now I have created 2 classes (Race and Runner).
>Methods of Race allow me to fetch datas on the www thanks to beautifulsoup
>module.I instanciate a race at the beginning of the scan and for each line
>I instanciate a Runner.
>I want to store all those information in a database (for both Race and
>Runner), but here is the point, I have the feeling, on a programming
>elegance point of view, that I have to separate methods that fetch from
>method that store and also have a kind of superior object that controls
>those 2 features.
>Moreover fetching will interact with storage: if race is already in
>database, no need to fetch again.
>How should I "design" this? Should I have only (despite my first
>impression) one class and all the methods in it? Should I create a parent
>class along with 2 childrens that manage the two kind of methods?
>Is there a design pattern for this?

My inclination would be to start by providing a class which "wraps" your Race 
database table, and presents it as a mapping.

Something along the lines of:

  class RaceTable:
    def __init__(self, database_connection, table_name):
      self.conn = database_connection
      self.table_name = table_name
    def __contains__(self, race_id):
      ... do SQL to see if the race_id is already present, return True or False
    def __getitem__(self, race_id):
      ... do SQL to fetch a Race row from the table and return it ...
    def __setitem__(self, race_id, race_info):
      ... do SQL to store race_info in the table ...

The special __foo__ methods (called "dunder" methods in the Puython world 
because of the "double underscore") are what make the class look like a Python 
"dict" from outside: when you perform a mapping method like "value in x" or 
"x[key] = value", Python calls x.__contains__ or x.__setitem__ for you.

Look up "Emulating Container Types" here:

  https://docs.python.org/3/reference/datamodel.html#emulating-container-types

That will show you how to write a class like the above example to implement a 
"maping" interface. You don't need to implement everything, just what you need.  
The example above only implements 3 methods.

Then your outer code can look a bit like:

  race_store = RaceTable(database_connection, 'race_table_name_here')
  ...
  if race_id in race_store:
    ... mention that this race_id is already stored ...
  else:
    race_store[race_id] = race_info

So the objective here is a simple class that makes it easy to talk about where 
your information is stored in nice Pythonic terms, and which hides the details 
of database access - that lets you talk about the data in a sensbile and clear 
way outside the storage class, and also leaves scrope for changing the storage 
mechanism later without changing the main code (eg from a conventional SQL 
database to some other service).

Cheers,
Cameron Simpson <cs at cskk.id.au>



More information about the Python-list mailing list