The module system is still fairly confusing to me, but I'm pretty sure I can get it. Mainly .mli files and writing signatures / interfaces confuses me. Still, at an abstracted level, I think:
Module: Encryption --> This will replace the large encryption functions. Hopefully inside of this I can break the larger encryption functions down into multiple, very specific functions. This module will then have a very simple interface: Take text, return encrypted text. Take encrypted text, return decrypted text. Or possibly, a separate encryption and decryption module, to reduce coupling. I don't want to have to reuse code for each module, though. But that's how it is already so idk what the best design here is. Could just have an all encompassing encryption / decryption module. The idea is to have independent modules testable independently. If something in this (these?) module absolutely requires another module to be tested, I've fucked up again. Plus modules shouldn't depend on the internals of another module, which I would need to do for this, so probably I'll just have one module for "encryption/decryption". I could use includes and functors for this, though, and seperate them. That'd be smart, I think.
Module: UI module --> User I/O, basically program flow. While loop to keep the thing running, takes user input, passes to other modules and gets the shit back from those modules, then displays it.
I'm not sure how the fuck I'd use modules to do file I/O and regex without them being hopelessly intertwined with the rest of the modules.
Module: Configuration --> Essentially stores / generates session keys and takes the password.
Agh, I don't even know how to design this shit well. It's tough and I have no examples to look at.
This is a classic design problem. In OOP languages, it is hard to resolve this elegantly because a class encapsulates both a type definition and methods related to that type. Thus, as soon as you have a function such as a_of_b, which regards two types to an equal extent, there is no clear place for it.
OCaml correctly provides distinct language mechanisms for these distinct needs: type definitions are introduced with the keyword type, and related methods are collected together in a module. This gives you greater flexibility in designing your API, but does not solve the problem automatically.
One possibility is to define modules A and B, both with their respective types and compare functions. Then, the question remaining is where to put a_of_b and b_of_a. You could arbitrarily give preference to module A, and define the functions A.to_b and A.of_b. This is what the Standard Library did when it put to_list and of_list in Array. This lacks symmetry; there is no reason not to have put these functions in B instead.
Instead you could standardize on using of_ functions vs to_ functions. Let's say you prefer to_. Then you would define the functions A.to_b and B.to_a. The problem now is modules A and B are mutually dependent, which is only possible if you define them in the same file.
If you will have lots of functions that deal with values of type A.t and B.t, then it may be worth defining a module AB, and putting all these functions in there. If you will only need two, then an extra module is perhaps overkill.
On the other hand, if the total number of functions regarding A's and B's is small, you could create only the module AB, with type a, type b, and all related methods. However, this does not follow the OCaml community's convention of naming a type t within its own module, and it will be harder to apply the Set and Map functors to these types.
Fuckin design gets hard.
Edit: Not this is broken. What it should have, is a few modules such as encryption/decryption, maybe configuration, and parsing, then have a "core" which may or not be a module, which handles the actual "main" program execution and shit. The modules are useful for abstracting certain specific higher level actions with good interfaces, then the "core" module (or even just code not in a module) uses the modules to implement the rest of the actual program. So it'd look something like this: