This message was imported from the Ruby/Rails Modularity Slack server. Find more info in the import thread.
I’m currently pondering the question of how to differentiate public APIs from non-public APIs in call sites (i.e. when using them). Have any of you done something (e.g. a special namespace) to somehow make it obvious that something is a public package API, purely when reading the code that’s consuming it? Or is this a non-problem? (I can’t tell because we don’t enforce privacy yet anywhere.)
I was thinking it might be useful to be able to enable / disable certain packwerk checks, like privacy, via a command-line param.
You could then use the vs code plugin and enforce privacy only for the annotations of that plugin. That way people could still easily call private APIs but they would be made aware.
Once you’ve decoupled things considerably a Private:: namespace might make sense, as then you can use native Ruby to enforce privacy:
module SomePackage
module Private; end
private_constant :Private
end
# somewhere else
module SomePackage
class Something
Private::Something.new # just fine
end
end
# somewhere else
module SomeOtherPackage
SomePackage::Private::Something.new # Runtime error
end
It works great in my experience, it just is decidedly not gradual.
Haha, indeed not gradual. But very interesting, once boundaries are established.
I guess my question is for this in-between phase that - at least in theory - is just a phase: Boundaries start to be drawn, and I want to teach / evangelize the concept of public APIs and having to use them. That’s what I had in mind when coming up with this need for some demarcation in my mind.
yeah, I think you have the options of either namespaces or the vs code plugin plus a PR to packwerk. Curious what other people think - I may be missing something
If I understand your proposal correctly, the plugin thing is not really what I’m looking for, because that would require enforcing these checks in the first place, and we’re not there yet.
That’s what I meant with a modification to packwerk. Imagine you tell the VS Code plugin to, instead of just calling packwerk check, call packwerk check --enforce-privacy-everywhere, which would override your package.yml files and treat them as if they all had enforce_privacy: true. On the command line or in CI, privacy would still not be enforced.
I haven’t thought this idea all the way through but it seems that it would be useful.
That’s a great end state, but IMO an intermediate state where they don’t can make a lot of sense for a pretty long time. If boundaries are introduced retroactively, it‘s important to be able to move them easily, because iteration will be needed to place them well. Requiring names and packages to match up creates friction in that process.
Once things are stable enough that no or little movement back and forth is expected, package namespaces are a no brainer IMO; but at that point, the packages may as well be gems with separate test suites.
We’ve been doing this the other way around:
• Enable privacy checks everywhere
• Record the violations into package_todo.yml
• Run packs check --ignore-recorded-violations as your linter
<@U78EF4XFY8W> I appreciate your input, but I would politely disagree. As Philip pointed out, that’s all nice and well, but not applicable when we have / inherit software that wasn’t modularized from the start. In such a context, the gradual modularization approach is gold IMO, because it allows experimenting with / discovering the boundaries in a risk-free (and therefore more realistic) way.
That said, this is now totally unrelated to my original question. Maybe I shouldn’t have posted this as a <#C01BB5E398U|design-questions>. I would enjoy discussing this, but please in another thread.
<@U717FXJ8HWK> that has different behavior though - it will reject new unrecorded violations. So it does enforce. My understanding is that Franz is looking to not enforce any privacy violations yet.