Fork me on GitHub
#beginners
<
2017-09-07
>
seancorfield00:09:24

For a (publicly available) library, yes, I agree that a clear public/private separation is useful from a documentation and support point of view. Otherwise there's not much point. And even for the library API, it's a toss up between using public and private in one ns vs using a fully public ns and an "implementation" ns (clearly documented as such), in my opinion.

seancorfield00:09:58

(however, when discussing contrib library organization with Cloure/core folks, it seemed they lean heavily toward avoiding the public vs implementation ns approach)

alexmiller02:09:28

I don’t think there is consensus - there are examples of every option from clojure/core people

seancorfield02:09:32

I'll rephrase then: when I asked for feedback on java.jdbc, I got very strong feedback from the Clojure/core folks who expressed a preference back then, that a "private namespace" or "implementation namespace" was not considered "good practice". I didn't push for justification, I just took it at face value.

seancorfield02:09:18

It definitely feels like something that would be nice to get some design guidance on -- from the wizened ol' Cognitect elder statesmen 🙂

alexmiller02:09:45

well go look at core.async, designed by Rich

alexmiller02:09:59

it has a public API namespace, and a bunch of namespaces under impl

seancorfield02:09:02

Yeah, I was a bit surprised at the strength of the feedback on java.jdbc's impl namespace at the time... I didn't think there was really as much consensus as the feedback indicated.

alexmiller02:09:15

well, not sure who that was from (hopefully not me) :)

seancorfield02:09:32

It predates your Cognitect time by a long time 🙂

alexmiller02:09:33

there’s plenty of strong opinions around :) I just don’t think there’s consensus

alexmiller02:09:50

there are reasonable arguments for a variety of approaches

seancorfield02:09:57

I think it would be great if Cognitect could perhaps articulate a core of "best practices" or at least the pros/cons of common approaches -- and cover those in a conference talk, to get the community discussion going around that sort of thing.

alexmiller02:09:59

I’d say the only approach that I actively don’t like is one public api namespace, with vars imported from elsewhere via potemkin. But I understand other people do like that style and I’ll respect their opinion. :)

seancorfield02:09:22

Clojure seems to have woefully little guidance on style and code organization overall.

alexmiller02:09:45

collectively, people at Cognitect have written like a dozen books and dozens of presentations on it

alexmiller02:09:03

so, I feel like the opposite :)

seancorfield02:09:30

Code organization across namespaces? That's been covered in talks and books?

alexmiller02:09:53

well I alone have written about it in multiple books now

seancorfield02:09:55

Maybe Clojure Applied covers that (I only just bought that -- haven't started it yet).

seancorfield02:09:07

Glad I bought it then!! 🙂

alexmiller02:09:17

Stuart Sierra has done talks about this, and written blogs about it I think

alexmiller02:09:07

I’d love to see you write about it :) you have plenty of experience to do so.

seancorfield02:09:08

Hmm, not about this topic in particular, that I can remember. He's certainly done some strong opinion pieces on other topics 🙂

seancorfield02:09:42

If I worked for a company that was in the business of advising others, I'd probably write / talk more!

alexmiller02:09:27

it’s always a struggle to balance the “doing things” with the “talking about doing things”

tbaldridge01:09:19

I'm just anti-private-cars because it makes unit testing, extension, and REPL debugging harder.

tbaldridge01:09:49

Wow thanks iPhone, private vars not cars

dpsutton01:09:30

Yeah I wish there was an expressable relationship between test and regular name space letting the private vars be used explicitly

seancorfield02:09:12

When I first started writing Clojure, I used private functions a lot. Over time I stopped using them and I almost never write a private function now (except for the library case above).

seancorfield02:09:56

I've tended to find that I end up wanting to reuse functions that I initially thought should be private -- and since they're usually pure functions of their arguments, there's really no downside.

alexmiller02:09:53

I find it to be heavily context dependent and I do all of them (all public, public/private, split api/impl namespaces) depending on the situation

alexmiller02:09:12

but those are 3 useful patterns

rcustodio21:09:30

Hi... I would like to know what how do you guys manage state, use things like compose or mount, or just use a simple def atom?

bfabry21:09:58

what in-memory mutable state our apps have tends to be in an atom in a component. there's rarely more than like one of those though. mostly state is stored in external systems

rcustodio21:09:20

States like db connection, rmq connection (to use a single connection) a simple atom? That is it?

rcustodio21:09:03

I'm making a service, but I'm isolating things like db connection, and others just use it

rcustodio21:09:12

Each one in their context

rcustodio21:09:45

But... I keep asking myself how to maintain the connections

bfabry21:09:58

unless the connection requires refreshing I wouldn't think of it as state, it would just be a field on a component. if it required refreshing then it would be an atom in a field on a component

rcustodio21:09:21

Component from Stuart?

bfabry21:09:51

ya, I think his talks on that are currently the most common way to manage things like db connections in clojure apps

bfabry21:09:59

yes the library

bfabry21:09:20

there's alternatives, mount etc. but I believe component is still the most popular

rcustodio21:09:00

Hmmm, I see, I will test it

rcustodio21:09:26

I like the way erlang manages it, Passing through argument, but is automatic

rcustodio21:09:42

Component kind of does that

bfabry21:09:54

very similar yes

bfabry21:09:29

ie as in, the state is all passed through via function arguments, but initializing that big state map is somewhat taken care of for you

rcustodio21:09:55

And you isolate all of it... IE?

rcustodio21:09:36

Isolating and pure functions, that is functional and clojure

noisesmith21:09:50

components are isolated yes - you can create two of the same component with separate configs, or the same config but they each have their own state

noisesmith21:09:19

btw a big advantage is for testing - with component all you need to do to “mock” in a test is to provide a hash map with the right keys on it

noisesmith21:09:33

(as an explicit arg, no need to shadow a var or anything)

rcustodio21:09:24

I see... but I don't see much reason to write tests on clojure... hehe

rcustodio21:09:34

But I understand

noisesmith21:09:39

in my experience that leads to a lot of problems

noisesmith21:09:46

today, you use the repl and see that your code works

noisesmith21:09:14

tomorrow, when you change something, do you know without running the app (or worse yet, deploying it) what other thing it might have broken by changing its behavior?

rcustodio21:09:23

Component is really good to isolat and work with stateful services

noisesmith21:09:26

unless you memorized everything you did in the repl to verify it worked…

rcustodio21:09:39

Yah, I agree

noisesmith21:09:58

and really a test is the simple version of that 😄 - take what you did in the repl, wrap some test/is calls around it

rcustodio21:09:56

If you write small libs.. tests become pointless, but to do that you must write an excellent documentation so ppl doesn't get lost

noisesmith21:09:19

I’m unconvinced that tests are ever pointless

noisesmith21:09:30

some specific tests? sure, testing in general? no

rcustodio21:09:46

The company that I'm does that way, it really boring writing those docs... hehe

rcustodio21:09:56

I see, thanks for the tips @noisesmith

noisesmith21:09:06

on the other hand, this is mostly opinion but I agree with Rich Hickey that “test driven development” is like “guard rails driven development” - it’s good to have barriers that let you know when they are crossed and avoid certain catastrophic mistakes (or catch them sooner when it’s easier to address), but centering your dev process around those barriers seems a bit much

rcustodio21:09:40

All devs I know hate to write tests lol

seancorfield22:09:32

@rcustodio I know quite a few devs who love TDD and writing tests. And once you start using generative testing, it's amazing how much value and coverage you get from very little test code. clojure.spec is great for helping with that.