Yep, I'm with @seancorfield and @mccraigmccraig.
Morning!
đź‘Ť or (subject under test) more generally
Morning
mĂĄnmĂĄn
Morning!
Thanks @seancorfield @mccraigmccraig et al.
đź‘‹
Bore da :welsh_flag:
Morning
Morning
morning
late to the party but always :as
so you have a specific namespace
except in some very particular cases
there's always room for one more at the party
the continuous never-ending, no-need-to-be-socially-distant-or-wear-a-face-mask clojure party 🙂
I have another good practice question, do you mark functions as private (in their namespace) or just don't bother?
@seancorfield, it’s a fair assumption, but in the past I’ve found lower-level functions I cannot use because they’re scoped private, presumably because the author didn’t think they’d be useful. It’s not always possible to anticipate the API that library users will need – often they don’t know until they start digging, or hit on a problem which means they can’t use the API as intended. OS maintainers are free to put out whatever they want of course, and there’s always a way round – please don’t take this as criticism of all the great work you’ve done! But for the sake of convenience I would eschew private in my libs unless I thought the vars were unquestionably off limits.
I feel like this conversation is potentially across purposes. I private functions because I have no intention of retaining or supporting them. Both answers given are potentially correct, so there's actually an additional distinguishing dimension.
It's a weird thing to think about, I think most people's intention is actually to try and tell you the functions they expect you to use, but when you see a private function it often won't explicitly tell you what function you should be using Maybe it'd be better to think about a mechanism for promoting functions rather than demoting functions
@lsnape As an OSS maintainer, if someone decides to start using a private var and doesn't create an issue asking for it to be made public, I'm not going to be very sympathetic if I refactor the function away or change its signature (or even its behavior) and break their code 🙂
OTOH, I am perfectly happy to consider an issue requesting a private var be "promoted" to part of the API.
I think the question is why the structure of the API even makes it a problem. There's usually a mismatch in either design or problem being solved.
Definitely. If I "made a mistake" and made something private that left the API lacking, I'm happy to fix it. If the private function is truly an implementation detail then I need to figure out what the API should so that functionality is exposed officially, in a supportable manner.
moin moin
rarely @dharrigan, but occasionally it seems like the right thing to do
I'm feeling the same 🙂 Currently, nothing of mine is "private"
e.g. i marked a fn which implements an extend
protocol method fn private yesterday... but i think that's the only private fn in the whole project
As the project grows in size, I find marking fns as private essential. That tells me if I should expect clients of the fn outside the ns but in the same project. I use another practice to mark fn that are also used outside the project. I create a wrapper for them in a specific ns meant as public facing API (for example core
). If the function is there, it’s used by external dependencies and should be treated accordingly to allow graceful upgrade.
that's an interesting approach 🙂
I noticed this “more formal” approach starts to be required with team of 15-20 people working on mutually integrating projects
when doing private, do you prefer (defn-...)
or (defn ^:private ....)
?
If that’s not your case… don’t bother, all public! :)
Normally defn-
which is shorter
I tend to mark things as private a fair bit, but often find that I eventually end up unmarking a lot of them cos they need to be used
Other good scaling projects conventions: put docstrings in namespaces, kill utils.clj ruthlessly, don’t mark fn public because you want to test them ;)
all very interesting 🙂 I like to ponder on what people do and see if I can use/adapt/ignore 🙂
again… formality/conventions bring value when scaling, it has a price in the small. As always, tradeoffs.
I bet this varies a lot on how you structure your code. If it's more like a series of libraries which are being composed together, then there's a lot more private vars.
The 15-20 heuristic as a point when libraries start happening is a good link.
Morn'
In the past I've tried to use functions in libraries, only to find the author made them private. Very frustrating! However for non-library projects i have found them useful
I started off obsessively marking everything private (with defn-
) because of my OO background. Then I gradually shifted to having everything public so client code could call anything and it was all easier to test. Like @reborg as our project at work has grown, I've gone back to making everything private unless it is a documented part of the API because my linter can tell me if a private Var is unused which helps with maintenance in a large codebase. I also have clj-kondo
set to flag missing docstrings on public Vars -- again, a nod to the API-ness of such things.
In my OSS libraries in particular, keeping things private unless they're part of the documented API makes life a lot easier -- for me as maintainer and for my users since they can stick to reading the API docs in general and not have to go grubbing around in the code.
that's very interesting too. Do you still favour (favor? 🙂 ) defn-
over ^:private
?
defn-
and def ^:private
(after all, defn-
is built-in and shorter than defn ^:private
)
🙂