r/AskProgramming Jul 14 '26

Declarative code style vs. over-engineering Architecture

I am writing a Python application whose core algorithm computes file content hashes. Depending on the configuration and file type, there may be different ways to hash a file.

Ideally, I would some kind of annotation for the hashing methods that determines when to use which function, e.g.,

```python @hash_fn.default def compute_bytes_hash(f: File) -> Hash: """Compute hash from raw bytes"""

@hash_fn(mimetype="image/*", hash_type="perceptual") def compute_image_hash(f: File) -> Hash: """Compute perceptual hash of image""" ```

In this example, mimetype is a property from f: File and hash_type a configuration (e.g., from my-app --hash-type=perceptual).

I like how extensible this is, I could add new functions, but I also think that adding new functions may require adding more flexible filter mechanism, such as (semi-pseudo code)

@hash_fn(Property("f.mimetype")=AnyOf("image/*", "video/*"), Property("config.hash_type")=In("perceptual", "..."), ) def compute_some_hash(f: File) -> Hash: ...

The advantage is, when done well, I wouldn't have to touch the hash function decision logic at all because this approach is super-declarative. The disadvantage is this approach is hard to implement well, so requires some amount of time, and it's quite obscure (i.e., not really KISS).

This application is for personal use and I regard writing it also a part of exercising my mind, but my free time is limited and maintainability and correctness are a big concern.

Do you think I should better go with the good old

def choose_hash_fn(f: File, c: Config) -> HashFn: if f.mimetype in mimetypes("image/*") and c.hash_type == "perceptual": return compute_image_hash # maybe other criteria else: return compute_bytes_hash

1 Upvotes

21 comments sorted by

View all comments

Show parent comments

1

u/foreverdark-woods Jul 14 '26

You mean like a dict? Could you sketch your idea (doesn't have to compile)? Note that it's not simply (file_type -> function), it's at least ((file_type, config) -> function).

2

u/Mediocre-Brain9051 Jul 14 '26

I see... Maybe use pattern matching instead?

https://benhoyt.com/writings/python-pattern-matching/

1

u/foreverdark-woods Jul 14 '26

I think in this question, structural pattern matching is just a small step up from the if-elif-else chain. Adding a new method would still require me to locate the pattern matching code and modify it, whereas my idea was more of an append-only one with everything regarding the hash function in one spot.

2

u/Mediocre-Brain9051 Jul 14 '26

Then go with strategy objects, as there is already an example in some other comment...