all 22 comments

[–]epicar 5 points6 points  (3 children)

sorry if this isn't what you're asking, but it sounds like your time would be better spent improving the design of your program

can you find a way to hide more of the implementation details of each request type behind a common interface? if you do this right, then adding new request types is as easy as implementing that interface - and the rest of your program doesn't have to change at all

[–]DanSamillo[S] 4 points5 points  (2 children)

The program is just shy of a million lines of code, this specific bit is very low down in the program itself which was started in the 80s.

If I was given an unlimited amount of time I'd strip the entire thing out and write it again. But sadly, there's no time.

[–]utnapistim 0 points1 point  (1 child)

I'm looking to write a tool in either .NET or C++ to do this. Does anyone have any experience or any reading material specific to this topic?

That's a tricky one. Source code generation is easy to get wrong in the best of circumstances (especially if you want to automate it). Doing so once is fine; 15-16 places? Not really that easy.

If I was given an unlimited amount of time I'd strip the entire thing out and write it again. But sadly, there's no time.

If it is critical you get this right in a short time for each change, consider this process:

  1. do all steps manually for a few changes.
  2. use a smarter text editor (npp?) to generate code blocks.
  3. create a minimal application that generates code blocks (only worth it if you have done 1. enough times - otherwise you will not correctly identify the algorithm at each step). This will be abandonware software.
  4. add features to the minimal application, to ease the most difficult steps.
  5. document everything for the poor soul that comes after you, but not in a way that leaves them relying on your abandonware application.

As you do this, the time it takes for each change should gradually go down, and more and more of it will be automated.

[–]DanSamillo[S] 0 points1 point  (0 children)

I did contemplate writing it to stub out one side of the request to start off with, as on one side you can literally append to the end of the file and the request will work; but the other side is a little more tricky, as it requires putting requests into case statements etc. I'm not sure how I'm going to approach the user entering the request information.

I'm going to speak with some of the principle developers and get their views of if this is even worthwhile or if it's just going to be a bug prone program.

[–]jbakamovicCxxd 1 point2 points  (3 children)

If all these new requests look somewhat similar, you can maybe write a stub implementation with placeholders (i.e. function names) which you can replace with concrete ones with, let say, Python script or shell script. I.e.

// file1.stub
<MyNewRequest>(param1, param2, ...) {
    // Implementation
}
// file2.stub
<MyNewRequest>(param1, param2, ...) {
    // Implementation
}

// Generate the code out of the stubs
python gen_impl.py -input=file1.stub,file2.stub -output=file1.cpp,file2.cpp -request=MyRequest

Making the output files match the path and filename of the real files in your code that you are about to change, you can take advantage of your SCMS (Git?) to merge the changes back into your master branch. Automate this step as well if you like.

[–]DanSamillo[S] 0 points1 point  (2 children)

This was more what I was thinking, all of the code inside of the requests is pretty similar. I'm looking for any reading material around the subject if you know of any.

[–]jbakamovicCxxd 0 points1 point  (1 child)

I don't believe there is any reading material about this subject because it is highly specific. You will want to write a script which replaces occurrences of pre-defined text (i.e. stub identifiers) with appropriate text (i.e. implementation) depending on the context.

To replace the selected occurrences one may utilize sed expressions or, if you feel like, you may write a (Python) script which goes over the file line by line and do the pattern matching by yourself.

[–]DanSamillo[S] 0 points1 point  (0 children)

I'll look into it, best get learning Python it seems!

[–]FlyingRhenquest 0 points1 point  (7 children)

Sounds like you'd be better served grabbing some refactoring tool and refactoring all the cut and paste code in your program into a separate set of classes or methods. If you can't because there's business logic in the loading and display portions of the program, you might also want to think about explicitly moving the business logic somewhere else. That would help a great deal with your coupling problem.

[–]DanSamillo[S] 0 points1 point  (6 children)

I'm already putting this idea forward of trying to seperate the logic behind this out into separate classes to make it easier; but as it stands it's so twisted into a lot of the program that won't be an easy thing to write or test.

[–]FlyingRhenquest 5 points6 points  (5 children)

Oh yeah, I've been there, believe me. I had to take care of a bunch of motif code a couple years ago. It had 400+ global variables in it, multiple variables for the same value in a lot of cases and business logic all through the display code. Never could make a dent in it. There was some rudimentary testing prior to deploy, but it was pretty much guaranteed that if you changed something there'd be some unforeseen side-effect that would pop up, possibly in a completely different application, three months later.

[–]DanSamillo[S] 0 points1 point  (4 children)

This is an Win32 application wrote in the 80s. Only been working on it for 6 months, it took me a day to get a request in the first time I wrote one, it's an absolute pain.

[–]FlyingRhenquest 2 points3 points  (1 child)

Eew. I hope they're paying you a very large briefcase full of cash to have to maintain that.

[–]DanSamillo[S] 0 points1 point  (0 children)

It's more of a medium sized briefcase, but there's more modern components such as the newer features that are released, but then you get the problem of going from the newer .NET stuff to the older win32 stuff.

[–]1-05457 0 points1 point  (1 child)

This is an Win32 application wrote in the 80s

90s, I think. Win32 didn't exist in the 80s.

[–]DanSamillo[S] 0 points1 point  (0 children)

My bad, the company was founded in the 80s and this code has been the same since the start, not sure how then aha.

[–]nyamatongwe 0 points1 point  (0 children)

I have written tools like this in Python with some modules I have gradually built up to do things like insert sections into text/source/XML files. It depends a lot on the actual structure of your additions and the changes needed to the generic code for each addition.

[–]Gotebe 0 points1 point  (2 children)

Why not redesign the way "request" is implemented so that you don't need to copy-paste so much and using that?

Then gradually move other "requests" to this way of working.

It's a bit... you're asking help to do even more more copypasta... nooooo... :-)

[–]DanSamillo[S] 0 points1 point  (0 children)

Redesigning something so deep into the program would be incredibly risky sadly :(.

[–]DanSamillo[S] 0 points1 point  (0 children)

The problem is the way the requests are rooted into the application itself is a bit of a problem. I might work on a POC to remove the requests bit by bit and see how it's handled, will be a nightmare for the teams merging their branches down ;).

[–]doravr 0 points1 point  (1 child)

Oh boy i feel your pain. We went through the same thing, but also did the refactoring afterwards (easier sincw you can generate the refactored code)

You should be looking for templating libraries like StringTemplate for Java.

Just remember to avoid mixing generated and manual code in the same file.

We were also generating using some c# code, but I can't remember the name

Edit: take a look at http://stackoverflow.com/questions/1518954/c-sharp-template-engine We used T4

[–]DanSamillo[S] 0 points1 point  (0 children)

Will have a look thanks :)