@foo did you have a certain project structure in mind i.e. where do you think a business logic module would belong in biff? Or is a clean separation of concerns actually not supposed to be in the scope of biff? (Not that that would stop me , I can easily achieve what I want by just creating a logic namespace and requiring that in e g. App.clj or something, the question is more out of curiosity)
Was just skimming through yakread and got really intrigued by the macros defget / defpost. That looks like these automatically create routes with the functionality defined in the body - is that correct?
Although they still need to be registered in the module map, so I am not entirely sure what these are supposed to do
yeah, they're intended to make defining routes a little more ergonomic without being magical. they basically just expand into a thing like (def my-route ["/my-route" (fn ...)]). besides that they also integrate at experimental effects-handling approach that I described in https://biffweb.com/p/removing-effects/ (I.e. so instead of calling impure functions, you return data that describes the effect you want to happen, like a database transaction). and finally, defpost does a nifty thing where it auto-generates as endpoint url based on the symbol. it's meant for internal routes that the user won't see in their address bar. E.g. given (defpost foo ...), you'll end up with an endpoint like "/_biff/api/com.example/foo".
FYI I've recently done a new iteration on all that stuff which I'm migrating Yakread to while I do the XTDB migration: https://github.com/jacobobryant/yakread/blob/migrate/src/com/yakread/lib/fx.clj
I've started putting code like that under com.example.lib.*, then your Biff modules would remain under com.example.app.* and other places as needed. I have some notes about my approach to code organization in the yakread readme: https://github.com/jacobobryant/yakread (e.g. see the bullet points). Some of that is specific to Pathom, and I haven't figured out yet if I'll ever try to bring Pathom into Biff by default, so the Biff starter project may or may not follow the same file layout in the future.
At work since we're dealing with a large codebase, we also follow the convention of treating the first layer of namespaces under com.example.lib.* as public APIs and any nested namespaces as private implementation namespaces. so you would define a bunch of functions in e.g. com.example.lib.foo.impl.a and com.example.lib.foo.impl.b, and then in com.example.lib.foo we expose some of those functions via com.taoensso/defalias
Ah cool, I totally forgot to check the yakread code out, that will probably answer my question way more precisely
it's a good codebase to peruse 🙂 the idea is to have that be a good example of a non-trivial biff project, precisely for questions etc like this.
I'm in the middle of migrating it to xtdb2 and am also changing a few other things along the way, but the overall structure is the same. that work is on the migrate branch for now: https://github.com/jacobobryant/yakread/tree/migrate
Pathom also sounds interesting, though I haven't fully grasped what exactly it is:sweat_smile:
heh I probably should write a blog post about it sometime. I was skeptical at first, but after I "got it" I've become a huge fan.
mostly helpful for projects once you get in the 10k+ LOC range IMO