Options Part 2: A Success Story
In part 1, I discussed the problems that were presented by something as simple as adding an option to suppress privacy information. Now, there is actually no debate as to whether this option should be included. Everyone agrees that it does. However, stepping back away from the problem and looking at it at the higher level can help resolve the problem.
During the early development of 3.0, Benny Malengier identified many problems with privacy. After a bit of discussion, we realized that the problem was bigger than we thought.
We took a step back, and looked at the real problem: We needed a consistent and centralized way of handling private data.
Fortunately, Brian Matherly had been doing a bit of research into the problem. He developed the concept of a “ProxyDatabase”. The idea was simple. We write a wrapper around the standard database. The purpose of the wrapper is to process the data in the database.
So, we created a PrivateProxyDatabase, which wraps the standard database. Each report is passed the ProxyDatabase instead of the standard database. This proxy database does all the work of filtering out the private data. If a person is private, the report does not even know that the person exists – the person is never returned by the proxy. Similar results occur for a Family, Source, etc.
Now, each report and exporter can be written without any concern for private information. The report simply assumes that it is writing all the data in the database. If privacy is requested, the report never receives any private data from the database.
So, as in part 1, the code to write a family is the same.
write_father_info(family.get_father()) write_mother_info(family.get_mother()) for child in family.get_children(): write_child_info(child)
No changes need to be made to handle privacy. Private data never reaches the report.
Additionally, now every report and every exporter could instantly handle private information without *any* modification to the report’s or exporter’s code. All that is required is that the call to the report or exporter be changed from:
if privacy: database = ProxyDatabase(database) WriteReport(database)
One conditional check in the standard report dialog now handles privacy for all reports.
So, by stepping back and designing a solution, instead of hacking a solution, has lead to code that is much more consistent, clean, and easier to maintain.
The developers did what Brian is now currently requesting:
- Communicating to identify the problem (inconsistent privacy handling).
- Stepping back to identify the root of the problem (privacy was not being handled in a centralized manner)
- Designing a good solution (a proxy database that handles the privacy information without requiring reports and exports to be modified)
Since then, we have been able to extend this concept to provide a FilterProxy and a LivingPersonProxy. Again, this has vastly simplified code, and now reports no longer need to worry about filtering data or handling living people.
Again, I bring up these examples to point out that these issues were resolved by discussion, analysis, and design. By stepping back and actually designing, were were able to remove the problems caused by the original quick hack.
We identified the “right” solution.