This is where CND files come in. A good way of thinking of a CND file node definition is as if it is a table in a traditional relational database.
There is a node type notation defined that provides the grammar for a CND file. This format is very compact and easy to understand.
Here's an example node definition that has two properties and specifies that the parent node will have an unstructured child node. Notice that I define my own custom namespace here.
To register this definition, the NodeTypeManager is used. This object is fetched from the workspace and a workspace comes from a session...
The above code assumes that a session has already been created. The CND file is read into a string and passed to the NodeTypeManager. That's all there is to it. Of course you would probably want to have multiple CND files.
The loading of registration of CND files is a one time operation, once it's in your repository you can keep reusing the defined node types.