Framework design, initialization and framework usage

Adam D. Ruppe destructionator at gmail.com
Mon May 6 18:21:27 UTC 2019


On Monday, 6 May 2019 at 18:03:18 UTC, Robert M. Münch wrote:
> Any reason why makeing things private?

Just the constructor. It is so they don't try to skip a step 
calling the constructor themselves.

But, of course, it doesn't have to be private.

> What I want to avoid is that explicit init line in main().

I did things that way with cgi.d and regretted it later (and the 
vibe.d authors, as I understand it, also did something like you 
are describing and regretted it later too).

It is actually really useful to have the user write their own 
main. It makes the flow clear with a familiar starting point. 
Even if all it does is actually call a framework function to do 
all the real work, having that main gives people unfamiliar with 
your framework an idea of where to start in understanding this 
code.

And besides, you are going to need some kind of user-customized 
code to select which class they want to use. You could create a 
global variable with some predefined name... but how will it know 
which class to put in there? Is it going to be static?

extern(C) __gshared MyFramework _framework = new MyApp;


like you could do that... but it will be a weird error if the 
user does it wrong, or does it twice, or whatever. Or if their 
MyApp constructor can't be run at compile time, that is also an 
error here.


You could create a factory function with a magic name that 
returns the new object:

extern(C)
MyFramework frameworkFactory() { return MyApp; }


but again, the errors are going to be weird and this really just 
obfuscates the code.

void main() {
    useFramework!MyApp;
}


there you go, simple code, it works, and it is customizable with 
other classes.

And you, as the framework author, still get to define  all what 
useFramework does - just name it that instead of main and you are 
good to go.


If you must avoid the user calling it main, you could do what my 
cgi.d does and define main inside a mixin template.

library code:

mixin template UseFramework(Class) {
    void main() { useFramework!Class; }
}

user code:

import framework;

class MyApp : MyFramework { ..... }

mixin UseFramework!MyApp;



but like i said, i am actually moving away from that after using 
it for many years, because the main function calling another 
function works just as well and is imo simpler.


More information about the Digitalmars-d-learn mailing list