Live data from Hacker News

Architecture Patterns with Python

cosmicpython.com

101–110 of 143 posts

Re: Architecture Patterns with Python

#101
post #88
post #77

Earlier quoted context omitted.

>So far off from what actually happens I disagree strongly, based on 20 years of using Python without annotations and ~5 years of seeing people ask questions about how to do advanced things with types. And based on reading Python code, and comparing that to how I feel when reading code in any manifest-typed language. >Reading Python functions in isolation, you might not even know what data/structure you’re getting as…

> using the wrong language IMO this is the source of much of the demand for type hints in Python. People don't want to write idiomatic Python, they want to write Java - but they're stuck using Python because of library availability or an existing Python codebase. So, they write Java-style code in Python. Most of the time this means heavy use of type hints and an overuse of class hierarchies (e.g. introducing abstract…

This is totally not how I used typed Python. I eschew classes almost entirely, save for immutable dataclasses. I don't use inheritance at all. Most of the code is freestanding pure functions.

Re: Architecture Patterns with Python

#103
post #79

Wow this book is a goldmine for architecture patterns. I love how easy it is to get into a topic and quickly grasp it. Having said that, from a practical and experience standpoint, using some of these patterns can really spiral out into an increased complexity and performance issues in Python, specially when you use already opinionated frameworks like Django which already uses the ActiveRecord pattern. I’ve been in c…

> Turns out all the big ones with strict architectural (n=3) pattern usage, although “clean”, the code is waaaay to complex and unnecessarily slow in tasks that at first glance should had been simple. My last job had a Python codebase just like this. Lots of patterns, implemented by people who wanted to do things "right," and it was a big slow mess. You can't get away with nearly as much in Python (pre-JIT, anyway) a…

+100.

Patterns and Abstractions have a HUGE cost in python. They can be zero cost in C++ due to compiler, or very low cost due to JVM JIT, but in Python the cost is very significant, especially once you start adding I/O ops or network calls

Re: Architecture Patterns with Python

#104

Earlier quoted context omitted.

> for each entity have a separate class to provide the database access Let me correct you: for each entity that needs database access . This is why I'm talking about layers here: sometimes entities are never persisted directly, but only as "parts" or "relations" of other entities; in other cases you might have a very complex persistence implementation (e.g. some entities are stored in a RDB, while others in a filesys…

Naturally, Repository is a pattern for data(base) access, so it should have nothing to do with objects that are not persisted. I used "entity" as meaning a persisted object. That was not very clear, sorry.

Well, again, that is not completely straightforward - what exactly is a "persisted object"? We have two things here that are usually called entities:

1. The domain entities, which are normally represented as native objects in our codebase. They have no idea whether they need to be persisted and how.

2. The database entities, which are - in RDBs at least - represented by tables.

It is not uncommon that our entities of the first type can easily be mapped 1:1 to our entities of the second type - but that is far from guaranteed. Even if this is the case, the entities will be different because of the differences between the two "worlds": for example, Python's integer type doesn't have a direct equivalent in, say, PostgreSQL (it has to be converted into smallint, integer, bigint or numeric).

In my "correction" above I was talking about the domain entities, and my phrasing that they "need database access" is not fully correct; it should have been "need to be persisted", to be pedantic.

Re: Architecture Patterns with Python

#105
post #88
post #77

Earlier quoted context omitted.

>So far off from what actually happens I disagree strongly, based on 20 years of using Python without annotations and ~5 years of seeing people ask questions about how to do advanced things with types. And based on reading Python code, and comparing that to how I feel when reading code in any manifest-typed language. >Reading Python functions in isolation, you might not even know what data/structure you’re getting as…

> using the wrong language IMO this is the source of much of the demand for type hints in Python. People don't want to write idiomatic Python, they want to write Java - but they're stuck using Python because of library availability or an existing Python codebase. So, they write Java-style code in Python. Most of the time this means heavy use of type hints and an overuse of class hierarchies (e.g. introducing abstract…

I can remember in the mid-00s especially, Python gurus were really fond of saying "Python is not Java". But `unittest` was "inspired by" JUnit and `logging` looks an awful lot like my mental image of Log4J of the time.

> But recently I heard more extreme advice - someone recommended "write every function as a member of a class" and "put every class in its own file".

Good heavens.

Re: Architecture Patterns with Python

#106
post #100
post #77

Earlier quoted context omitted.

>So far off from what actually happens I disagree strongly, based on 20 years of using Python without annotations and ~5 years of seeing people ask questions about how to do advanced things with types. And based on reading Python code, and comparing that to how I feel when reading code in any manifest-typed language. >Reading Python functions in isolation, you might not even know what data/structure you’re getting as…

>I'm concerned with what capabilities the input offers, not the name given to one particular implementation of that set of capabilities. If I have to think about it in any more detail than "`ducks` is an iterable of Ducklike" (n.b.: a code definition for an ABC need not actually exist; it would be dead code that just complicates method resolution) I'm trying to do too much in that function. If I have to care about wh…

I understand that. The point is that I gain no information from it, and would need more complex typing to gain information.

I keep seeing people trying to wrap their heads around various tricky covariance-vs-contravariance things (I personally can never remember which is which), or trying to make the types check for things that just seem blatantly unreasonable to me. And it takes up a lot of discussion space in my circles, because two or more people will try to figure it out together.

Re: Architecture Patterns with Python

#107
post #88

Earlier quoted context omitted.

> using the wrong language IMO this is the source of much of the demand for type hints in Python. People don't want to write idiomatic Python, they want to write Java - but they're stuck using Python because of library availability or an existing Python codebase. So, they write Java-style code in Python. Most of the time this means heavy use of type hints and an overuse of class hierarchies (e.g. introducing abstract…

I can remember in the mid-00s especially, Python gurus were really fond of saying "Python is not Java". But `unittest` was "inspired by" JUnit and `logging` looks an awful lot like my mental image of Log4J of the time. > But recently I heard more extreme advice - someone recommended "write every function as a member of a class" and "put every class in its own file". Good heavens.

Not coincidentally, these are two of my least favorite parts of the standard library. Logging especially makes me grumpy, with its hidden global state and weird action at a distance. It’s far too easy to use logging wrong. And unittest just feels like every other unit testing framework from that era, which is to say, vastly overcomplicated for what it does.

Re: Architecture Patterns with Python

#108
post #100

Earlier quoted context omitted.

>I'm concerned with what capabilities the input offers, not the name given to one particular implementation of that set of capabilities. If I have to think about it in any more detail than "`ducks` is an iterable of Ducklike" (n.b.: a code definition for an ABC need not actually exist; it would be dead code that just complicates method resolution) I'm trying to do too much in that function. If I have to care about wh…

I understand that. The point is that I gain no information from it, and would need more complex typing to gain information. I keep seeing people trying to wrap their heads around various tricky covariance-vs-contravariance things (I personally can never remember which is which), or trying to make the types check for things that just seem blatantly unreasonable to me. And it takes up a lot of discussion space in my ci…

In my experience, arguing co versus contra is a sign you are working with dubious design decisions in the first place. Mostly this is where I punch a hole in the type system and use Any. That way I can find all the bad architectural decisions in the codebase using grep.

Re: Architecture Patterns with Python

#109
Hmm let's see we're going to

- Reimplement SQLAlchemy models (we'll call it a "repository")

- Reimplement SQLAlchemy sessions ("unit of work")

- Add a "service layer" that doesn't even use the models -- we unroll all the model attributes into separate function parameters because that's less coupled somehow

- Scatter everything across a message bus to remove any hope of debugging it

- AND THIS IS JUST FOR WRITES!

- For reads, we have a separate fucking denormalized table that we query using raw SQL. (Seriously, see Chapter 12)

Hey, let's see how much traffic MADE.com serves. 500k total visits from desktop + mobile last month works out to... 12 views per MINUTE.

Gee, I wish my job was cushy enough that I could spend all day writing about "DDD" with my thumb up my ass.

Re: Architecture Patterns with Python

#110

Hmm let's see we're going to - Reimplement SQLAlchemy models (we'll call it a "repository") - Reimplement SQLAlchemy sessions ("unit of work") - Add a "service layer" that doesn't even use the models -- we unroll all the model attributes into separate function parameters because that's less coupled somehow - Scatter everything across a message bus to remove any hope of debugging it - AND THIS IS JUST FOR WRITES! - Fo…

I've made it through about 75% of the book and have never gotten the sense that they think everything discussed in the book is something you should always do. Each pattern discussed has a summary of pros and cons. While they may be a bit lacking, they clearly articulate the fact that you should be thinking whether or not the pattern matches the application's needs.

I don't think there's many applications that will require everything in the book but there are certaintly many applications that could apply one or more patterns discussed.

Post reply on HN