This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-09-24
Channels
- # announcements (6)
- # architecture (9)
- # aws (2)
- # babashka (49)
- # beginners (160)
- # boot (19)
- # calva (9)
- # cider (16)
- # clj-kondo (17)
- # cljfx (9)
- # clojure (143)
- # clojure-australia (5)
- # clojure-berlin (1)
- # clojure-czech (3)
- # clojure-europe (64)
- # clojure-france (1)
- # clojure-italy (12)
- # clojure-nl (4)
- # clojure-spec (6)
- # clojure-uk (47)
- # clojurescript (27)
- # code-reviews (5)
- # conjure (45)
- # cursive (47)
- # datascript (2)
- # datomic (21)
- # events (1)
- # fulcro (9)
- # graalvm (4)
- # graphql (2)
- # jackdaw (22)
- # jobs (3)
- # kaocha (6)
- # london-clojurians (1)
- # luminus (4)
- # malli (19)
- # meander (136)
- # pathom (4)
- # pedestal (2)
- # re-frame (15)
- # reitit (2)
- # remote-jobs (2)
- # rum (12)
- # sci (1)
- # shadow-cljs (100)
- # spacemacs (10)
- # sql (1)
- # tools-deps (30)
- # vrac (1)
- # xtdb (30)
Yep, I'm with @seancorfield and @mccraigmccraig.
månmån
Thanks @seancorfield @mccraigmccraig et al.
Bore da
Morning
morning
late to the party but always :as
so you have a specific namespace
except in some very particular cases
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?
rarely @U11EL3P9U, but occasionally it seems like the right thing to do
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.
I noticed this “more formal” approach starts to be required with team of 15-20 people working on mutually integrating projects
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.
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 @U054W022G 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.
defn-
and def ^:private
(after all, defn-
is built-in and shorter than defn ^:private
)
@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
@U07SQJ620 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.