The Command Pattern is Useless in Python

The Command Pattern is Useless in Python
Whenever I see design patterns being used in Python, I sigh. Why not just use the powerful language features that Python provides us with instead?

I was reading a book called Practices of the Python Pro where the author was designing the CLI interface for a CRUD app. Once I saw the Command Pattern being used, I knew that this book was no good and stopped reading.

Here’s how the pattern was implemented:

class CreateBookmarksTableCommand:
    def execute(self):
        db.create_table('bookmarks', {
            'id': 'integer primary key autoincrement',
            'title': 'text not null',
            'url': 'text not null',
            'notes': 'text',
            'date_added': 'text not null',
        })

Simple enough?

Then for every action the user takes, you create more commands:

class AddBookmarkCommand:
    def execute(self, data):
        data['date_added'] = datetime.utcnow().isoformat()
        db.add('bookmarks', data)
        return 'Bookmark added!'


class ListBookmarksCommand:
    def __init__(self, order_by='date_added'):                            1
        self.order_by = order_by

    def execute(self):
        return db.select('bookmarks', order_by=self.order_by).fetchall()

And so on.

A noob looking at this code will start to believe that this is clean and professional. Then he will start writing this kind of code daily.

To use a command you first need to instantiate it:

create_bookmarks_table_command = CreateBookmarksTableCommand()

create_bookmarks_table_command.execute()

Clever right?

But Python isn’t Java. Instead of the jokes called CreateBookmarksTableCommand, AddBookmarkCommand, and ListBookmarksCommand, simply create a commands.py module and inside that module enter:

def create_bookmarks_table():
    db.create_table('bookmarks', {
        'id': 'integer primary key autoincrement',
        'title': 'text not null',
        'url': 'text not null',
        'notes': 'text',
        'date_added': 'text not null',
    })

def add_bookmark(data):
    data['date_added'] = datetime.utcnow().isoformat()
    db.add('bookmarks', data)
    return 'Bookmark added!'

def list_bookmarks(order_by='date_added'):
    return db.select('bookmarks', order_by=order_by).fetchall()

Use your commands easily:

import commands

commands.create_bookmarks_table()

No need to instantiate a CreateBookmarksTableCommand. Simply import and execute. Simple is better than complex.

Why pretend to be smart and use design patterns when there’s no use for them?

If you really want to use patterns, then use Java.