Лично я его в меру часто использую. Если исключить питонские динамические замашки, то и нормальные случаи есть.
Вот сделал я сущность Пользователь. Пользователя нужно хранить в БД. Чтобы хранить в БД, ему нужно иметь account_id. Можно и без числового идентификатора, но тогда идентификатором должен быть юзернейм, а если его захочется поменять, то будут большие проблемы. Короче, нужно число. А число можно получить только от БД.
Но с точки зрения архитектуры, создание сущности не должно зависеть от хранения сущности. В AccountRepository не должно быть метода create_user.
Т.е. я не могу создать пользователя с account_id не обращаясь к БД, причём обращение должно быть атомарным, иначе в многопоточной среде если где-то ошибиться, требование id из БД, потом добавление его в юзера, потом запись юзера в БД приведёт к проблемам - либо будут пропущенные id, либо account_id violates unique constraint или чё там с одинаковыми primary_key.
Далее я понял, что сущности Пользователь в предметной области вообще не нужен account_id, потому что account_id имитирует в реляционной парадигме то, что в других местах работает через ссылки, вложенные структуры, списки объектов и т.д.
Соответственно account_id не нужен сущности Пользователь, но нужен таблице пользователь. У сущности Пользователь на уникальность указывает уникальное имя пользователя.
Поэтому в AccountRepository я добавил словарь Dict[username_string, account_id_int].
Я вызываю AccountRepository.add_account(Account), там происходит INSERT с RETURNING account_id, потом account_id записывается в словарь. То же самое с get_account_by_***. Пользователь достаётся из БД и его id записывается в словарь. Словарь приватный для хранилища.
И так я отделил сущность от id, который нужен только БД. И когда я делаю запрос, я пишу не
select ... from post where post.account_id = (select account.account_id from account where account.username = %s), а просто достаю id из словаря и пишу нормальный запрос с where post.account_id = %s.
Короче, я сел на два стула))))