catalyst

pithyless 2023-08-29T13:39:37.473499Z

@pithyless has joined the channel

pithyless 2023-08-29T13:39:43.064259Z

👋

1
pithyless 2023-08-29T13:46:24.374889Z

> Project organization is killing my inexperienced brain. Where does the schema go? In project.db.schema? Where does spec go? In the files? In project.spec? Two different schools of thought: 1. Just use src/project/core.clj and test/project/core_test.clj. If you're not sure, keep everything around in one namespace (you are evaling things in the REPL, right?). That way you can avoid decision paralysis and slowly move things out to new namespaces when it becomes burdensome (and just name them by their purpose). Notice how far you can get with flat structure before even thinking about directories/hierarchies/etc. 2. You can look at something like https://github.com/polyfy/polylith which has lots of rules about structure, project organization, etc. Everything has it's place, but again - you're just trying to remove decision paralysis and move forward. In this case the tool is telling you where you should be putting things.

Chip 2023-08-31T00:06:41.659259Z

The project structure is taking shape. If I’m making a mistake, it’s taking on a project of these dimensions. It’s moot though. I didn’t choose the project. For better and worse, it chose me. In some ways, it’s my _<https://en.wikipedia.org/wiki/Illusions_(Bach_novel)|Illusions>_. This is a very data-driven system. Very. Boiled down, it is in fact an anatomy-driven system. Anatomy is very complex, particularly neurocognitive anatomy.

Chip 2023-08-29T15:42:09.899909Z

I’m deeply grateful. I imagine I’ll have more to say/ask once I metabolize what you’ve shared. Again, thank you. Please brain dump and shamelessly plug as the spirit moves. Drive-bys are so encouraging.

pithyless 2023-08-29T13:48:34.448919Z

Some more namespace thoughts: • tests and src do NOT need to mirror each other. Sometimes I will have code split across multiple namespaces (that makes sense for modeling problem), but have single namespace for tests (because my testing strategy is working multiple pieces at once; testing at a higher level).

Chip 2023-08-31T00:08:37.878089Z

I’ve been more a script writer that a developer. Test-driven thinking takes a minute to grok.

pithyless 2023-08-29T13:52:48.161419Z

• you can use namespace names as context, eg. instead of functions like new-doodad and parse-date-to-string , if you create namespaces that model system entities and give them nice prefixes:

[my.project.doodad :as doodad]
[my.project.date :as date]
Those prefixes become essential parts of name by providing context (and not just short aliases):
(let [foo (doodad/new {..})
      started-at (date/parse "2023-....")])

pithyless 2023-08-29T13:53:54.323849Z

Recommended read: https://tonsky.me/blog/readable-clojure

pithyless 2023-08-29T13:56:40.378229Z

Personally, I am a big fan of https://github.com/metosin/malli over https://clojure.org/guides/spec for modeling domain entities. I'm not trying to convince you to switch, but if you haven't heard of malli, I suggest you look into it a little before choosing one of the two flavors: if you're going to be using it a lot for modeling (which it sounds like you are), they both solve the problem, but you may prefer one over the other.

Chip 2023-08-31T00:10:22.714179Z

I’m digging into malli. It is the way. I’m just no good at it. I’m so ignorant. Onward.

Chip 2023-08-29T18:05:30.724019Z

I’m only trying to do what the Romans do at this point. I’m reading through malli. Thanks.

Chip 2023-08-29T19:59:59.479309Z

Do you ever need spec or does malli do everything you’ve needed so far?

pithyless 2023-08-29T20:16:42.311489Z

I find spec is great for speccing clojure code - eg smarter parsing and error messages in custom macros.

1
pithyless 2023-08-29T20:17:47.526689Z

But anything to do with validating user/external data - I prefer to reach for malli

pithyless 2023-08-29T20:20:36.267219Z

Rich Hickey talked about spec2 in one of his talks, where they separate schema vs select, which solves some of the problems of context-localized specs; but spec2 is yet to be released and malli is available :)

Chip 2023-08-29T20:21:08.360179Z

So helpful. Thank you.

pithyless 2023-08-29T13:59:54.353329Z

Last thing - since I see you're taking in a lot of video content - a small shameless plug: I once gave a talk on Datomic-style domain modeling. At least a few people found it helpful, so perhaps you will too :) https://www.youtube.com/watch?v=oo-7mN9WXTw

Chip 2023-08-29T18:00:50.382579Z

Gold. RDF made practical. SPARQL++. If that is your version of shamelessness, run naked. Thank you. I have an RDF vs LPG question. Sometimes I want an unreified relationship (RDF-esque via :db/ref). Sometimes I need relationship info (LPG). To boot, I know my wants/needs will flip-flop. My current thinking is I can have both using the same ref attribute. One hop is RDF, two is LPG with my properties hanging off the interstitial entity. How have you dealt with not knowing what you need of relationships ahead of time?

❤️ 1
pithyless 2023-08-29T18:14:18.677169Z

Thank you for the kind words. gratitude

pithyless 2023-08-29T18:14:55.371249Z

It's a good question... and appropriately "it depends". XD But here's some coffee thoughts:

pithyless 2023-08-29T18:15:34.347989Z

First of all, my current day job is dealing with SQL spaghetti, so take everything I say with a grain of salt, since I've been out of the trenches for a while.

pithyless 2023-08-29T18:17:56.507099Z

As you point out, you can make everything RDF/LPG by just changing the number of hops. So, the good news is, you can start with one or the other and just change your mind later. P*ick a new name* (I especially love the looks people give me when I just tack a 2 suffix onto something if I can't be more clever) and move on with your life. Don't try to reuse names (especially in Datomic, but also in your APIs) and you'll be fine.

pithyless 2023-08-29T18:19:35.269589Z

Another rule of thumb is how important this thing is to your domain. If you use it as a noun when you're talking about it out loud, or you have some notion of a platonic identity when you think about it, it's probably safer to make it an LPG (even with just one attribute).

pithyless 2023-08-29T18:22:17.335659Z

Another thing to consider is the database/storage/querying strategy. Nothing exists in a vacuum - so knowing your tooling may help steer your decision. For example, some things that I would model as a separate entity in Datomic, I may model as a property label in Neo4J, just because the querying/indexing has certain optimizations that take better advantage of one or the other.

pithyless 2023-08-29T18:26:27.395659Z

Another trick is to remember that not everything needs to be neatly denormalized; if you create a single hop :db/ref and later realize you need one more piece of info, just add a second attribute to the parent entity. Just like in SQL, 3NF is what you learn in school, but not what you use in production. 😂

pithyless 2023-08-29T18:30:14.657919Z

Last thing I would mention is to be open to ideas. People become fixated on what they know best. I once listened to a complicated schema model in Neo4J that had lots of labels hanging off the edges and suggested that perhaps they can just create an actual node that represents the <thing> in the domain. You could see their eyes light up when they realized it could simplify their lives (and they were in a local maxima fixated on LPGs). Same could be said for RDF style modeling (where we don't have labels, so obviously we will fight anyone that says that they are kind of useful in certain situations).

Chip 2023-08-29T18:30:31.481289Z

Helpful thinking. Thank you. I’m tempted to do two hops for now, even when I’m just traversing. Therefore, the intermediate entity will always have a ref. If only space and time didn’t matter. My first-pass thinking was :<domain-object>/<relationship> (RDF) and :<domain-object>/reified/<relationship> (LPG). The trouble I see there is I’m duplicating data and need a reification of the unreified and reified edges. Yikes. We’re back to your quite-accurate “it depends”. I need more experience with my model. Maybe I’ll double-hop my way to the understanding I need. edit: removed “always”

pithyless 2023-08-29T18:32:44.825119Z

You may end up in a place where you realize you've got lots of "meta" attached to the relationships and perhaps a DB that more accurately helps you work with that structure is actually more convenient. That's OK, especially if you're open to recognizing it... Datomic is not a panacea.

Chip 2023-08-29T18:34:30.186549Z

Indeed, nothing is a panacea. Me thinks it’s flexibility I need most right now. Datomic seems like the place to start anyway.

pithyless 2023-08-29T18:34:48.850059Z

My first gut reaction, given no other context, is to create explicit entities if I can visualize that <thing> is some kind of <essence> in my domain (that I can try to point to, try to name, etc). That <essence> can even just be a reified "relationship" or "verb" instead of a noun. But for some reason I find it may be important in the domain

pithyless 2023-08-29T18:35:54.867159Z

Actually, the exercise of trying to give the thing a name is often useful in and of itself, even if I end up scratching the idea.

pithyless 2023-08-29T18:39:04.192529Z

^ The corollary of the above is that if the thing I'm thinking of is a piece of data (in the Clojure sense of a persistent data structure) and doesn't have it's own identity, it may be best as a value attribute. Even if it's a nested/complicated piece of data, you can just serialize some EDN to a string and store it like a blob. EDIT: Not :db/ref but regular value attribute.

Chip 2023-08-29T18:39:16.402749Z

Very helpful thoughts. Risking that I’ve missed a subtlety in your words, I’m starting with two hops (LPG). It leaves things more flexible. I’ll optimize when experience shows I don’t need the extra structure.

👍 1
Chip 2023-08-29T18:40:57.472519Z

You are so generous. Whether I pay back when I can or pay forward, I’m so grateful for the connection.

pithyless 2023-08-29T18:40:58.386459Z

If you build indirections in your code between your logic and your DB storage, you'll find it easier to change your mind and consider alternatives when you hit a wall.

pithyless 2023-08-29T18:41:29.185379Z

Reminds me of a book which you may enjoy - https://elementsofclojure.com/

pithyless 2023-08-29T18:41:53.545559Z

Zach is really good at waxing poetic about thinking about indirection, abstraction, etc.

Chip 2023-08-29T18:42:30.051359Z

I’m not smart enough yet to understand what “indirections in my code” look like. Sounds like the book is what I need. Thank you.

pithyless 2023-08-29T18:43:42.477219Z

> Whether I pay back when I can or pay forward, I’m so grateful for the connection. The pleasure is all mine. Looking forward to future threads. :)

Chip 2023-08-29T18:43:53.338959Z

I will benefit from this conversation for a long time.

pithyless 2023-08-29T18:44:15.564899Z

Another book I'm always quick to recommend is https://grokkingsimplicity.com/

1
pithyless 2023-08-29T18:45:20.323639Z

It may feel a little "too easy", because Eric wrote the book for "beginners", but he has some really good insights on software development and FP. Alternatively, you can try to gleam the insights e.g. from his blog / podcast / etc.

pithyless 2023-08-29T18:49:37.448119Z

Alright, I'm off to get some work done. It's been a real pleasure and looking forward to hearing more about the project. And remember - Clojurians Slack has a LOT of smart and caring people around, so I'm in the same boat as you - just here to learn and take part in this fine community. :)

Chip 2023-08-29T19:38:06.466719Z

You are a gem. I can’t thank you enough.

pithyless 2023-08-29T14:00:52.511829Z

Good luck on your project and hope you don't mind me doing a drive-by brain dump :)

Chip 2023-08-29T19:31:48.318969Z

I’m going to share a question here just to get it off my mind — though I may need to decide sooner than I’m imagining. Central to my project are natural language statements. I’ll need to embed them at some point. Though I have zero experience with them so far, I’ve heard about • Pinecone • PGVector (PostgreSQL on AWS) • Weaviate • Elasticsearch • Qdrant • Chroma • txtai (Python - though others may be too) I’d much rather use Datomic if I can get away with it. If that’s not possible, some AWS-based service seems the next-most reasonable (a la pgVector). Off-AWS-planet connections (what I understand Pinecone to be) would be my third (very uneducated) choice at this point. I’ll eventually have to use the statements for fine-tuning, though I’ll drain that swamp after I deal with embedding.

pithyless 2023-09-03T10:51:38.940679Z

For prompt engineering and chat bot advice, you may want to hang around #ai and #clojurellm - it’s not exactly a 1:1 correspondence, but I bet people there can help you with at least the broad strokes.

logbot 2023-08-29T23:38:18.209049Z

@logbot has joined the channel

Chip 2023-08-29T03:06:59.781739Z

https://clojurians.slack.com/archives/C053AK3F9/p1693277155999439 about the structure asking for feeback.

teodorlu 2023-08-29T06:42:12.211479Z

@teodorlu has joined the channel

teodorlu 2023-08-29T06:42:23.020879Z

👋

Chip 2023-08-29T13:07:06.460709Z

Thanks for joining. I’m honored.

teodorlu 2023-08-29T19:14:52.835289Z

I support every initiative to learn in public! ❤️

Chip 2023-08-29T19:36:36.849479Z

Thank you. If you are an American like me, you’re an unusual one. It’s so American to say “You’re already supposed to know that!!” Appearing informed is a cultural norm that deeply undermines education — and bores me. edit for clarity

teodorlu 2023-08-29T21:31:13.268789Z

I dislike that attitude too. I don't think it's helpful for learning. It's very important to be able to say "i don't know how this works" without punishment. Otherwise we can't talk about the things we don't know yet! It's also hard to get help from others if they don't know what you don't understand. I've learned a lot about this from @borkdude in #babashka and other channels. I'm Norwegian! Though I'm not sure I'm a typical Norwegian either 😄

Chip 2023-08-29T21:39:45.742269Z

I can’t wait to visit Norway. Takk.

❤️ 1