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 aGetContacts
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 aContactsRequest
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 newContactUpdater
and commit the changes.Create: find any contacts from the word document that have the
NewContact
property set, construct a newContactCreator
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.