I am in the planning process for a new application, the application will be written in PHP (using the Symfony 2 framework) but I’m not sure how relevant that is. The application will be browser based, although there will eventually be API access for other systems to interact with the data stored within the application, again probably not relavent at this point.
The application manages SIM cards for lots of different providers – each SIM card belongs to a single provider but a single customer might have many SIM cards across many providers. The application allows the user to perform actions against the SIM card – for example Activate it, Barr it, Check on its status etc
Some of the providers provide an API for doing this – so a single access point with multiple methods eg activateSIM
, getStatus
, barrSIM
etc. The method names differ for each provider and some providers offer methods for extra functions that others don’t. Some providers don’t have APIs but do offer these methods by sending emails with attachments – the attachments are normally a CSV file that contains the SIM reference and action required – the email is processed by the provider and replied to once the action has been complete.
To give you an example – the front end of my application will provide a customer with a list of SIM cards they own and give them access to the actions that are provided by the provider of each specific SIM card – some methods may require extra data which will either be stored in the backend or collected from the user frontend. Once the user has selected their action and added any required data I will handle the process in the backend and provide either instant feedback, in the case of the providers with APIs, or start the process off by sending an email and waiting for its reply before processing it and updating the backend so that next time the user checks the SIM card its status is correct (ie updated by a backend process).
My reason for creating this question is because I’m stuck !! I’m confused about how to approach the actual workflow logic. I was thinking about creating a Provider Interface with the most common methods getStatus
, activateSIM
and barrSIM
and then implementing that interface for each provider. So class Provider1 implements Provider
– Then use a Factory to create the required class depending on user selected SIM card and invoking the method selected. This would work fine if all providers offered the same methods but they don’t – there are a subset which are common but some providers offer extra methods – how can I implement that flexibly ? How can I deal with the processes where the workflow is different – ie some methods require and API call and value returned and some require an email to be sent and the next stage of the process doesn’t start until the email reply is recieved …
Please help !
(I hope this is a readable question and that this is the correct place to be asking)
Update
I guess what I’m trying to avoid is a big if
or switch
/ case
statement – some design pattern that gives me a flexible approach to implementing this kind of fluid workflow .. anyone ?
I would start by defining a core API that you think that you can support across all of your providers. Later you can extend with optional methods, and checks to let you know which actions particular providers support. But that is definitely a stage 2.
That core API needs to be asynchronous because some of the providers do not respond to their methods in a reasonable time. For instance you can launchSomeRequest
which will enter data in a table saying that the request is made (so you can handle double clicks), and then offer checkSomeRequest
that checks the table to say whether it is done.
Behind the scenes each request that is stored will record the provider, and information allowing the actual request to be made. You can then have a cron job that regularly wakes up, looks for requests, and does the actual action.
(Note, my experience with push vs pull architectures strongly inclines me to prefer pull systems like this. They are slower and less efficient, but their failure modes are much better.)
If you use this strategy your first step is to think through that initial lowest common denominator, and to figure out what information needs to be stored in your back end to make it work (which I’m assuming is some kind of database). Code that up. Code up at least two very different back ends. (This is a good way to smoke out assumptions that you might have made.) Then you can work on your front end and slowly start adding in other back ends.
Only then start thinking about adding optional parts of the API.
2
I recommend to think in use cases. A use case for example is “Activate SIM Card”. Create a interface like ActivateSimCardController or ActivteSimCardInteractor. Implementations of this interface are specific for every SIM card provider. To create the right implementation you need an identification for the provider, so you need an implementation in front of the controller to choose the right one or you can save all possible actions together with the provider. The client will choose the provider specific service in the second case.
All Service should return nothing, because you have this email back-end. The client has to call a GetStatusOfActivateSimCardController to get the result. In this way you can implement the same mechanism for all providers.