-1

tldr: I have consumer-like classes that require a number of pieces of information to do their job. It's an "all or nothing" kind of thing: the "producers" providing them with data need to provide all necessary pieces of information or there will be a problem. I want to provide some assertions to make sure everything is present. I know that python is normally a fan of duck-typing, but because I need to have all data present in all cases, I feel it would be easier to make a base class that the producers have to implement, and then assert via instanceof. Is this a reasonable choice or is the preference still for duck-typing?

Background

I figure some background is good to make sure I'm not falling victim to the XY problem. I'm working on a system to manage database structure via version control (a database migration system). I have some classes that compare table definitions to see if anything has changed. The table definitions themselves can come from a variety of locations: it can come from the definitions stored in text files, it can come from reading the actual database, etc... So I have some classes responsible for loading up the database structure from various sources (producers), and then other classes who take those definitions and look for differences (consumers).

I briefly considered having a third entity involved to store the actual table definition, and which would be built by the producers and passed to the consumers. However, I don't think there would actually need to be any behavior associated with such a class: it would just operate as a dumb data carrier between the two which would just have a few properties on it. As a result, I think I would rather skip it, since it has no real responsibilities.

Instead (in the lingo of other programming languages), my thought was to have a simple interface that defines that table definition. The producer classes would implement the interface, read their respective sources, and populate the data accordingly. The consumers would then simply accept any object that implements the table definition interface. Obviously though, this is not the python way.

Having done some reading on the topic, it seems like duck typing is the preferred go-to solution for this problem. In my case though, I feel like it may not be the best fit. The biggest reason is because I don't foresee any need for flexibility in the required data parameters. If I always need the same half-dozen or so properties, I feel like it would violate DRY to check that all parameters are present everytime I need them.

Rather, my thought is to let the table definition be a base class which the producers then add to their inheritance chain, and which defines the properties which must be provided. The consumers will then just do a simple instanceof assertion before doing their thing.

Is that a reasonable approach to this problem in python, or are there preferred ways?

  • 1
    Which approach works best for your specific situation, pythonicity notwithstanding? – Robert Harvey Jul 31 '17 at 14:47
  • @RobertHarvey I would say having a base class. I'm mainly curious though if python has different ways of solving this same problem. – Conor Mancone Jul 31 '17 at 15:07
  • As a multi-paradigm interpreted langage, it indeed offers lots of ways to do the "same" thing. I've done something similar and went for simple dicts of strings to carry the data (not unlike a JSON datastore). Django went for something much more structured, but the immense flexibility (as you point out) required for these kinds of tasks make the classes very complex, with lots of "magical" properties. Also, don't forget that a whole langage has been designed to describe the sort of data you are working with: SQL. – Tibo Jul 31 '17 at 16:09
  • 1
    Like many modern languages, there are lots of ways to do things. Which is fine of course. It's just ironic coming from a language that has a founding principle (PEP 20) that includes "There should be one-- and preferably only one --obvious way to do it." – Conor Mancone Jul 31 '17 at 17:21
  • 1
    "The consumers would then simply accept any object that implements the table definition interface. Obviously though, this is not the python way." Do not understand your assertion. This sounds like the very essence of duck typing. If you are stuck on the formalism of "implements X interface," don't be. "Implements X interface," "supports the X protocol," and "is X-like" are overlapping & consistent concepts. Don't be so concerned about being Pythonic. You're in the lane. – Jonathan Eunice Aug 4 '17 at 10:19
1

Your logic seems reasonable. This of it this way: as a user, I don't want to have to read through your entire code to figure out what interface you are expecting. It's better to just provide a base class or Abstract Base Class that I can inherit from and fill in the blanks (plus, you can communicate the semantics of the interface from the base class definition).

This seems like a simpler way to communicate requirements. I don't know if duck-typing is still so popular now that we have Python 3 (it even introduced types!) so don't let language conventions/philosophy drive you too much.

In a language like Java, I'd just say something like

void function(Somethingable x){
   do something that requries x to be Somethingable
}

It's really the same idea. I'd look up "somethingable" in the Javadocs and implement/subclass accordingly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.