Legacy C++ in web, server-side: keeping it simple



  • I need to produce a web interface for a physical model with lots of parameters. No bells and whistles needed, just gather the user's input from a giant form (all 26 parameters are important; most can retain their default values), draw a plot and allow TSV export.

    Unfortunately, there's an external requirement to write it in C++, specifically, the kind of C++ understood by MSVC 10 (so no auto, unique_ptr or lambdas... perhaps that's a blessing). Also, CGI. There is no clear idea what kind of machine it is going to run on; probably the old lab server with Windows Server 2008 and Apache installed on it. I may get the C++ requirement dropped if noone except me would ever have to look at or touch the non-C++ part and the runtime would be easy to install and manage on Windows Server 2008. (There's a copy of PHP5 for Dummies lying around in the lab. I don't want to disturb it.)

    This is doable in a simple way: have the binary parse and validate the parameters (cgic provides very convenient functions for that and is still maintained), calculate the model data and output JSON; perform the plotting and TSV export on the client side via JavaScript (using excellent dygraphs and URL.createObjectURL(new Blob(data_as_text)), respectively).

    Unfortunately, I would personally like it to also work without JavaScript (and since I'm just a PhD student, I can get away with adding to the requirements as long as the job eventually gets done) and on a POSIX system. Plotting is a solved problem (I have a 200-line class that outputs enough of an SVG plot for my needs), but now I need to generate HTML. This probably means a templating library, lest I go crazy.

    Existing template libraries require C++ >= 11 or Qt, are complicated to build on Windows or dead. So it goes.

    But wait, even if I don't want to render stuff server-side, DRY principle requires me to store things like form parameter names in one place only to guarantee one-to-one matching between POST parameters and model variables. (It is too easy to make a typo in one of the 26 parameter names, and we might add more. I want to catch them at compile time or, better, make them impossible to happen.) I can imagine the generation being done statically (same code generates form.html and parse_form.cpp from a single description), but dynamic generation seems less crazy. Something like CGI::FormBuilder but not for Perl?

    Now I feel the onset of not-invented-here syndrome; it tells me I might as well avoid having dependencies and just write myself a simple string substitution function and another simple function that would parse form parameters, store them by given references and maybe output HTML (with the help from substitution function above) if it is needed. But that never goes well, does it? I am surely not Sean T. Barrett, Roberto Ierusalimschy or D. Richard Hipp to pull off implementing such a thick layer in the stack of dependencies myself. Either way, the result with its layers of processing and lots of code written by fallible humans would compare very unfavourably to the original idea of thin JSON-spewing executable in terms of keeping it simple.

    Or perhaps I should embed Lua and do as much logic and string-wrestling as possible in it, leaving C++ only for the model, but that brings the DRY problem back, since then I'd have to match table elements on Lua side to struct elements on C++ side, and there would be no way to prevent typos at compile time, as it usually happens in dynamic languages. Also, this would still feel like over-engineering. Perhaps static HTML/code generation is the way to go: I could do it once in the language of my choice and check in the results. No, someone would want to change them and easy re-generation would be impossible.

    I'm probably overthinking everything. Opinions?


  • Discourse touched me in a no-no place

    @aitap said in Legacy C++ in web, server-side: keeping it simple:

    I need to produce a web interface for a physical model with lots of parameters. No bells and whistles needed, just gather the user's input from a giant form (all 26 parameters are important; most can retain their default values), draw a plot and allow TSV export.

    Do you want any validation prior to submission? If not, you can use a plain form (plus some CSS) and things will be fairly easy. If you also don't mind replacing the webpage completely, you can totally avoid client-side JS and that's then simple. In that case, hosting the whole thing as CGI makes it pretty easy to code. If you know the parameters must be numeric, you can use really easy service-side validation code since you can ignore all the complexities of encoding (if the raw value doesn't parse as a number, reject; job done).

    You could put a lot of work into trying to unify the variable definitions into one place, but for a one-off job of this size then just cut-n-pasting them from somewhere will do well enough. Or using a single common .h file with all the bits you need in one array of structures, but generating the HTML is probably going to suck too (and auto-generating the layout of the form itself will be really annoying) so why bother? But do give errors if there's an unexpected parameter, and do say what the unexpected parameter is in the error message (while listing what parameters are expected). That will save you a whole load of debugging time.


  • Discourse touched me in a no-no place

    Also, why the fuck do you need to do this in C++? It's not the worst choice for this sort of thing, but it's pretty awful still. And without support libraries/frameworks too…


  • And then the murders began.

    @aitap said in Legacy C++ in web, server-side: keeping it simple:

    But wait, even if I don't want to render stuff server-side, DRY principle requires me to store things like form parameter names in one place only to guarantee one-to-one matching between POST parameters and model variables.

    I don't suppose your model is exposed via COM? If it is... well, like @dkf said, C++ is a pretty awful choice for a web server. You could make a simple ASP.NET MVC website (without JavaScript even!) that accesses the model via COM interop, and reflects over the field list to generate the form.

    I also think that's taking DRY too far, but it would be doable.


  • Banned

    Are you going to maintain it for more than two months? If not, doing things the right way might not be worth it.

    If you can run external programs that aren't in C++, then the CGI part might be done as a thin wrapper only and you can do actual work in whatever you want, passing data between programs as JSON to stdin or whatever else you want.


  • Discourse touched me in a no-no place

    @Gąska Good idea, especially as it allows you to test things separately. With a non-trivial model, that's a huge boon.



  • @dkf said in Legacy C++ in web, server-side: keeping it simple:

    Do you want any validation prior to submission? If not, you can use a plain form (plus some CSS) and things will be fairly easy.

    I forgot to tell that a zoomable and pannable plot (when possible) is also a requirement, so JavaScript is unavoidable. This part is even already complete, but now I have to think about the backend (which, for now, just prints a constant JSON string if you run it). I even used <input pattern="..."> and some really ugly regexps to do validation without scripting.

    But do give errors if there's an unexpected parameter, and do say what the unexpected parameter is in the error message (while listing what parameters are expected).

    And it's much easier to implement than total DRY. Thanks for the idea.

    @dkf said in Legacy C++ in web, server-side: keeping it simple:

    Also, why the fuck do you need to do this in C++?

    "So that everyone involved understands the code." I may be able to make this requirement go away.

    @Unperverted-Vixen said in Legacy C++ in web, server-side: keeping it simple:

    I don't suppose your model is exposed via COM?

    Unfortunately, no, it's just a DLL with a C++ header file that is almost syntactically correct C (it uses class in forward declarations for opaque pointers).

    COM + reflection could be a cool idea to consider, though.

    @dkf said in Legacy C++ in web, server-side: keeping it simple:

    You could put a lot of work into trying to unify the variable definitions into one place, but for a one-off job of this size then just cut-n-pasting them from somewhere will do well enough.

    @Gąska said in Legacy C++ in web, server-side: keeping it simple:

    Are you going to maintain it for more than two months? If not, doing things the right way might not be worth it.

    Thanks. It is possible that everyone is going to forget about the project after we get it running once.

    If you can run external programs that aren't in C++, then the CGI part might be done as a thin wrapper only and you can do actual work in whatever you want, passing data between programs as JSON to stdin or whatever else you want.

    @dkf had a similar suggestion back when I brought this up in WTF Bites. This also has the advantage of the address space belonging to potentially buggy model being short-lived. Alas, DRY goes out of the window - the form, the wrapper and the back-end would all have to agree about parameter/JSON field names - but, as you said, doint it right might not be as important as I think it is.

    Now I am leaning towards writing most of the code in a higher-level language with a template engine and form validation already written by someone else and running the model as a subprocess, with JSON over stdin/stdout as IPC mechanism.

    Filed under: Visit TDWTF to procrastinate every day. Ask a serious question once and find oneself procrastinating instead of visiting TDWTF to read the answers...


  • Discourse touched me in a no-no place

    @aitap said in Legacy C++ in web, server-side: keeping it simple:

    "So that everyone involved understands the code." I may be able to make this requirement go away.

    “What are you doing with that crowbar? Ow!”


Log in to reply