Programmers Solve Problems Like Genealogists Do - Sun, 8 Dec 2024
I’m working hard on Behold to get Version 0.99.1 Beta released. It will include GEDCOM export which I think will make it a valuable tool for many genealogists.
It has been taking longer to finish the GEDCOM export than I had hoped, partly because of opportunities to work on my own genealogy (which I don’t apologise for), but also because of a change needed to Behold to get the export to work. That change being to not repair the GEDCOM when it is input. Instead it must leave it as it is so that it can be exported back out again as input if the user desires it that way. The repair instead should take place when Behold displays the data in its Everything Report, or when the user decides to export following the GEDCOM 5.5.1 standard.
But that’s not the topic of this article. I’d like to present a typical programming mystery of the type that I often encounter, and a typical methodology I use to see my way through it.
Like a Mystery Novel
My wife loves a good mystery novel. It gets her thinking. You have to be observant to pick up the clues as some lead you in the right direction and others take you on a wild goose chase. When the novel ends, you can be self-satisfied if you figured out who-dunnit before the answer is revealed, or you can be surprised or shocked when you didn’t get it. A good mystery novel is something you will enjoy if the story was interesting, the premise of the mystery was unusual but made sense, and the solution in the end was plausible.
As a genealogist, something always creeps up that doesn’t make sense. Why is the father only 15 years older than the child. Was the family really in Ohio one year, Massachusetts the next, and back in Ohio again the year after? Why is the wife’s father’s name on their wedding license different than the father I have for her. Who is that in the picture with my grandfather?
All these genealogy puzzles are like mini-mystery novels. Each has their own solution. Some may be easy to find. Some nigh to impossible. Others may take years where a single discovery, most often from the most unexpected place, turns out to be the lead that was needed and we jump for joy for a few days afterward. As a genealogist, these puzzles provide me with all the mystery solving that I need, and I can leave the mystery novels to my wife.
As a programmer, I also often come across something in my program that doesn’t make sense. In this case, the program is simply not doing something that I was expecting it to do. It could be due to incorrect coding, unexpected and unhandled data, data structure issues, operating system issues, or a mental block that was preventing me from seeing the correct result. Solving each programming puzzle takes detective work, finding clues, logic and reasoning, testing ideas, and proving a solution. Very similar to genealogy.
One Programming Example from Yesterday
Here is a very simple example of one of my typical programming problems and my method of solution. Over the course of a 3 month period of developing my GEDCOM export, I’ve had dozens of such problems. This particular one took me about 3 hours to solve. Others can take anywhere from 5 minutes to 5 days to solve, often with my mind subconsciously working on possible solutions especially at night and in my morning shower.
I was working on handling the custom level 0 place records, which some programs use to allow additional information about a place. For example RootsMagic uses 0 _PLAC, Legacy uses 0 _PLAC_DEFN, and the GEDCOM-EL group uses 0 _LOC. These are all custom tags that most other programs don’t understand. Behold can read and display this data, and will also be able to export to GEDCOM.
One RootMagic GEDCOM that I was using for testing had this place reference:
It was saying that the Marriage License for family F299 (husband I833 and wife I940) was signed on Aug 29, 1834 in Austintown, Trumbull County, Ohio.
In addition, it had a 0 _PLAC record to further describe Austintown:
Behold Version 1.2.7 displayed this correctly in its Place Details:
Behold shows in the Place Details all references to each place, and the one reference in the GEDCOM file to Austintown is the marriage license.
Because I made some data structure changes in Version 1.99, I had to get the custom _PLAC record to work correctly. I got it working two days ago, and once I did, I expected it to look like this:
You’ll notice a few improvements in 1.99. The new version understands that the NOTE tag under a _PLAC record is simply a note and displays “Note:”. Since the references are ordered by date, the date is now on its own line with the parts of the date listed in reverse which makes scanning for the correct date easier. The event type (in this case Marriage License) now starts on the next line. The Behold reference numbers are no longer included (since the hyperlinks can take you directly there). All previous surnames are now enclosed in parenthesis rather than just the maiden name. And the person’s first surname is now shown in a bold font to make it stand out.
What was wrong and How I solved it
Unfortunately, after I got the _PLAC record working, I did not get the above result. Instead I only got this:
The marriage license reference was missing. Why was that?
The next day, I took a closer look at this problem.
The program I use for development is Delphi by Embarcadero. It started from the Pascal language and they added object-oriented components to it. Instead of just a code editor, it offers an IDE (Integrated Development Environment) that adds a visual designer and a debugger.
It’s the debugger that I like the most (including the name “debugger”) which you use to fix “bugs” in the program that are bugging you the most, thereby debugging them and getting rid of those buggers.
The debugger allows setting of breakpoints at the lines in the program that you want it to stop on. Then you can inspect to see what the values of your variables are, and advance the program, a line at a time if you want, until you have determined what it is that is happening that shouldn’t be.
So the question in this case is why is the marriage license reference missing.
Here’s what I did:
- Check the GEDCOM input of the line 2 PLAC Austintown, Trumbull Co., Ohio to ensure that Behold is creating the reference of the MARL event to the place. I put a breakpoint at line 2786 conditional on the value of tag being “MARL”. And the program stops there:
and after inspecting some of the variables and data structures, I was able to check that the reference was being added correctly.
- So what’s the next bit of code that might have caused the reference to be missing? It would be once the GEDCOM has been read and the reverse references are assigned. If a MARL event in a FAM record is referencing a place (or any other structure), then the reference from the place or structure back to the event must be created. If that is not done properly, then the link back won’t appear. The code for the reverse FAM links is:
I can follow that into my ProcessCiteRef routine, see the values of all the variables and check that everything is working. Indeed it was.
About this time, my wife saw that I had been working away on this “bug” for a couple of hours. Without ever having understood any of the programming that I do, she thoughtfully suggested to me that “It’s probably a missing ‘L’.”
- So I’m on my way to find a missing “L” in a haystack.
It is quite strange because almost all the other references are showing up fine. Here you can see the place before and two places following Austintown have references appearing:
There’s only one other place left that might be causing the reference not to be showing up. That is where the reference is being displayed. So I go to my PrintCiteRefs routine and place a breakpoint there and start to debug it line by line.
I get down to a few lines which I added last version and I see a bit of code and I immediately see what is wrong! Do you see it?
This code was working fine for reverse references originating from INDI (individual) records, but not from FAM (family) records. All INDI references were being displayed (e.g. Residence, Death, Census as shown above).
The problem was a missing set of parenthesis. The “and” line should have an extra set of parenthesis enclosing the “or” terms:
Without those parenthesis, every time a reference was from a FAM record, it would be skipped. This was an error I added in version 0.99 when I added the Living People filter.
After adding the parenthesis, the FAM reference was now displaying, as well as all other FAM references such as the two marriage events for Austin:
My wife had the right idea that it was something simple. It wasn’t a missing “L”, but it was a missing set of parenthesis that caused the problem.
Conclusion
Long story short. Programming is detective work, just like genealogy research.
You need to find that one bit of evidence that will solve your current problem.
Those of us who are programmers and/or genealogist do this because we enjoy the process. And we especially love those “eureka” moments when we fix that bug or break through that brick wall.