I'm from a Java background as well, along with quite a bit of Ruby and a little Go. Here's what I'm doing at the moment, about a month into Clojure:
- I'm thinking of a namespace as a semantic unit, it's code that goes together for a particular purpose, like a datatype and the operations on it.
I have two conventions for namespaces vs files:
- For smallish units that fit comfortably in one file (I'm using ~1000 lines as the limit where a file should be split) I have one namespace per file, with the directory path plus file name the same as the namespace. This is a good thing in Java, I think, it makes finding the namespace from the file or vice versa a breeze.
- For larger units that need several files, I'm using the Go convention: The namespace matches the directory path, and all the files in the directory share the same namespace. In these cases I normally assign a primary file with a fixed name ('main') that loads and interacts with the others.
As a namespace example, I have a parser that reads a format and converts it to HTML. I have a single namespace for the parser (the semantic unit) and several files in the directory split on sub-functionality: Lexer, parser, HTML conversion and a main file that contains the primary public API for using the parser.
I wouldn't automatically use one namespace per datatype, it depends on the scope of the datatype. If it's a big one, perhaps. But for a datatype like Point, with two fields and a couple of functions, I'd rather subsume it into a more general namespace like Geometry.
Require vs. use:
- Require with a suitably short alias almost everywhere.
- This also allows reuse of core names: My special-purpose tree datatype has the operation "get" to fit with maps; using require there is no conflict: "get" is the Clojure core get, "tree/get" is the one for my datatype.
- I'm using "use" only for what I consider "core extensions", like when I make my own "map-if" which is map and filter rolled into one.