Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I am struggling with the best way to structure a program that I am writing becau

ID: 643039 • Letter: I

Question

I am struggling with the best way to structure a program that I am writing because the method I currently have feels very clunky and each part depends a lot on the others. This is what the program needs to do:

Parse a word document to extract a list of contacts.
Get a list of contacts in a specified group from my Google account.
Compare the contacts from the word document to the Google contacts and either:
Update the contacts on Google with the details from the word document or
Create a new contact on Google if one doesn't exist or
Delete any contacts on Google that are not in the word document.
I also want

to have a GUI for this program that is responsive while all of the above is going on
the show a preview of the changes that steps 4-6 will make before actually performing them and allow the user to reject the changes (all or nothing would be fine for now)
Edit: everything from here on down is what I've currently done. I added it so that specific refactoring advice could be given if that was what was deemed necessary. If you have a way that I can structure this program then you can mostly likely skip the rest of it.

I've already made a start so allow me to explain how I've written the code so far. The program is written in C#.

The parsing of the word document to get a list of contacts is in a class called WordDocumentParser. It has a constructor which takes the path of the word document and a GetContacts method which performs all of the parsing and returns a list of contacts. For what it's worth, I'm using COM to handle the parsing.

Steps 2-6 from above all start from a new class called GoogleContactsMaintainer with a constructor that takes the list of contacts from the word document, a couple of important groups on Google and a ContactsRequest which is used to retrieve/update/save/delete contacts on Google. The first thing this class does is to get the contacts from Google and match them to the contacts from the word document. The matched Google contact is saved in a property on the word document contact.

Then I do a preview which is the next 3 steps.

I start off with updating the contacts that have been matched from the word document to the Google contacts. I create a ContactUpdater which updates the matched Google contact but doesn't commit the changes. It also adds to a list of strings any changes that have been made and sets a boolean property on the contact to say that it has been updated.

Next is creating new Google contacts for those word document contacts that haven't been matched to a Google contact. This is done in a ContactCreator class which creates a Google contact, sets it on the word document contact and sets a flag on that contact to indicate it is a new contact. The new contact is not saved.

Last is to delete any Google contacts that haven't been matched to a contact from the word document. To do this, I just find those contacts and add them to a list with a description saying that they will be deleted.

At the minute, I display these changes to the user and then immediately update them (I'll explain why the user can't stop this in a minute). This is done in the following three stages.

Update: find any contacts from the word document that have the HasBeenUpdated property set, construct a new ContactUpdater and commit the changes.

Create: find any contacts from the word document that have the NewContact property set, construct a new ContactCreator and insert the new Google contact.

Delete: find any Google contacts that haven't been matched to a contact from the word document and delete them from Google.

In an attempt to keep my GUI responsive while all of this is going on, I created a MaintainContactsWorker class which subclasses BackgroundWorker and calls all of the above 10 steps from the OnDoWork method. This is why I am unable to ask the user if they want to commit the changes or not.

To me, everything feels horribly inter-connected and completely untestable so I am hoping you can point out things that I should be doing to break the dependencies and make my code more maintainable and testable.

From writing this post, I one thing that I feel I should have is a repository which would handle the CRUD operations I am performing on the Google contacts. Does this seem like a good place to start?

Thank you for any suggestions you can offer, hopefully I've explain myself well enough.

Explanation / Answer

Your process:

Parse a word document to extract a list of contacts.
Get a list of contacts in a specified group from my Google account.
Compare the contacts from the word document to the Google contacts and either:
Update the contacts on Google with the details from the word document or
Create a new contact on Google if one doesn't exist or
Delete any contacts on Google that are not in the word document.
One possible structure:

WordDocParser docParser = new WordDocParser(path);
IList<Contact> wordContacts = docParser.ParseContacts();

GoogleContactsManager googleManager = new GoogleContactsManager(accountInfo);
IList<Contact> googleContacts = googleManager.GetContacts();

ContactComparer comparer = new ContactComparer();
IList<ContactUpdateAction> updateActions =
comparer.Compare(wordContacts, googleContacts);

//user can edit/alter update actions here

googleContacts.UpdateContacts(updateActions);
For a responsive GUI, showing what step is happening with a progress bar should suffice up to the point where the user can see/alter the update actions. You can use a background/worker thread for each step, with a button to allow the user to cancel the process. The background thread can update a flag (Mutex or similar) when it is done to signal for the launch of the next background step.

Each UpdateAction can specify whether to add, delete, or change the contact information. This information can be displayed to the user before making changes to the Google account (at least in theory!) When the user is satisfied, they can click a Commit Changes button to execute the last step, or Cancel.

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Chat Now And Get Quote