A Clean Anvil Architecture (?)

@owen.campbell has recommended The Clean Architecture a couple times on this forum, and I’ve been experimenting with ways to implement it in Anvil. I’m very much a beginner at this, though, so feedback is most welcome. (For other newbies, here’s an introduction to The Clean Architecture I found helpful.)

This is my attempt to demo it in Anvil by refactoring the Multi-User News Aggregator tutorial app:
https://anvil.works/build#clone:X7GIWM5O2OR6I4O6=KF4F6LOXSBZFU7LRQYFLEWGZ

With this simple of an app, there’s little need for all the added structure, but maybe you can imagine how it could be helpful for more complex apps.

Here’s an overview of the code:

  • The articles.interactor module (corresponding to “Use Cases” in the canonical diagram shown below) doesn’t import from anything else (not the database or anything related to the UI). It is meant to contain all the business logic.
  • Everything Data Tables is limited to the articles.gateways module.
  • All the UI logic is in the articles.controller module, which is used by the form code.
  • The server module functions as an input/output boundary (only). It passes the database “Gateways” to the interactor code (in a technique called “dependency injection”).
  • Ease of testing is supposed to be one of the benefits of The Clean Architecture, so I added some example tests. (Unfortunately, my server-side unittest code doesn’t run using the “Basic Python” server code version, but that’s the only part that won’t work if you look at this on the free plan.)

The code also borrows some ideas from @stefano.menci’s Test Driven Development with Anvil post, as well as building on a previous demo app of mine.

11 Likes

In this updated version, I add an “entities” layer with a portable Article class that facilitates validation both client- and server-side (but may violate The Clean Architecture rules by allowing the UI code to directly depend on the “entities” code?):

https://anvil.works/build#clone:ZW7EHRJ4XNH5YC5I=HJBDT2CWLRYD62TBK3H6OZUV

I also switched out the full dependency injection in the interactor layer with a simpler pattern that keeps the auto-complete working (and still allows easy testing via monkey patches).

2 Likes

I naively studied your Muli-users News v2 before I get to this thread.
So here’s how I interpreted it (wrongly I’m sure):

I did it because I need visual clues to follow code, even mine. I love node-red for this reason, but it’s NodeJS.
As you and other folks here, I’d like to approach any project with a clear strategy so i’m learning from you.

1 Like

Any feedback on the code structure? (I imagine it might be hard to know where to start, though. I’m pretty new at this.)

Several things are not how I would have done it from scratch. But I was trying to keep things as similar to the original Tutorial App as possible, apart from the architecture.

Other things are kludges that now strike me as a little too “clever,” like the Article error checking apparatus.

Looking at your diagram, one thing I’m noticing is that, in v2 without the full dependency injection, there’s not much reason to separate the server module from the interactor module.

Here’s a slightly updated version in which I remove some boilerplate by making the interactor module a server module:
https://anvil.works/build#clone:HFLNZXVQNUDBR2PK=3DRQTDAQZ3FNS5CB24CWPJVP

Here’s an updated version with some heavy refactoring to make better use of the cleaner architecture. I’ve also cleaned up the imports so that the dependency structure is more apparent:
https://anvil.works/build#clone:UKRF2DT2EMVCKMK5=6X3PGSYGKEYIEXIKMJEB2XVD

I appreciate your attempt of untangling typical Anvil spaghetti.

The controller does not seem to do much except calling server functions. The use of portable classes is interesting.
Not convinced by the interactor/gateways concepts. It seems to indicate the lack of a proper ORM in Anvil.

In my experience there a two areas of repetitive and messy code: keeping the DB in sync with my objects (see comment about ORM), and keeping the UI in sync with program state. Anvil could use a reactive system a la Vue.js. The current event system is not nearly adequate (I tend to use Anvil Extras messaging).

I really like Anvil, but it struggles when apps get more complicated.

1 Like

Thanks. Yeah, I’m still struggling. In my real app, the controller does more of substance (and I’ve recently switched to using Anvil Extras messaging to handle its interaction with forms for updates).

Have you tried https://github.com/anvilistas/anvil-orm at all? No one has stepped up to help with the documentation yet, so it’s difficult to use. I have recently found @owen.campbell’s example app really helpful in better understanding it, but that too takes some time to digest, sorting through the code. Want to work together on documenting this ORM (or developing an alternative)?

Anvil Labs also has something reactive-ish under development, integrated with a sort-of ORM alternative (partially demoed here).

Had a look at Anvil-ORM: indeed a lot of moving parts. It doesn’t help that the example app includes the libraries (I think) making it hard to see where the boundary between library and application is.

I think I’ll wait for all this to mature a little bit more (although Anvil Extras status would be fine for me).
Pity Anvil seems not very interested in improving the data access layer. Although, being on the outside, I might be wrong.

You might be waiting for quite some time. I work on this stuff either when a paying client needs it or when I have some free time. Neither of those is likely to apply for the near future.

It is, of course, all open source which means anyone is welcome to improve it in whatever way they need.

2 Likes

Completely understandable.

1 Like