Some quotes to provide context.

"I read several times that ideally I should avoid inheritance with ABCs and if I do, then from a standard class. That is, I should avoid creating a typical base and subclass construct that is used in a strategy pattern, for example."

"If I look at a principle like SOLID, where we have the Liskov Substitution Principle, the interface separation principle, and the dependency inversion principle, they all rely on a base class, which of course is created by inheriting from ABC."

"Python, on the other hand, does not have the strong need to be object-oriented, but most of the principles assume that we are working with classes."

"Working with Liskov Substitution can make it difficult to navigate through an IDE."

BLUF

Very important: Composable, Predictable, Domain-based.

These are consistent with the idea that software is knowledge capture.

Maybe less important: Unix-Philosophy and Idiomatic. While nice ideas, they feel a bit redundant.

CUPID

See https://cupid.dev/properties/

Composable

Highly desirable to have small pieces that compose into something useful. This fits with SOLID Interface Segregation Principle, and provides an answer to "but, why?" We segregate the interfaces to create something composable.

Unix-Philosophy

This also implies composability. It goes a step further to incorporate the idea of the SOLID Single Responsibility Principle. The Unix design patterns provides concrete examples of how to decompose a large problem into smaller pieces; each piece does one thing well.

Predictable

This decomposes into three distinct aspects:

  • A component behaves as expected. This is sometimes called the Principle of Least Astonishment.
  • A component's behavior is consistent and deterministic.
  • A component's behavior needs to be observable, also.

These are all critical features, especially observability.

Idiomatic

Yes, follow language idioms. Please do not boldly go where no programmer has gone before.

This seems to go without saying. It does help fill up the acronym, though. And, perhaps, it's necessary advice.

Domain-based

The solution code should mirror the problem domain. This is really important, and not present in other sets of design principles.

Indeed, I don't think it can be emphasized enough.

OO modeling and design isn't about optimization or code reuse. It's about fidelity to the problem domain.

Code reuse is nice to have. Providing common behavior among the problem domain objects that are being modelled is the point.

Conclusion

These are nice. They're very useful in conjunction with SOLID design principles.

It helps to have guideposts to help clarify an underlying "why" we design software.