Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

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 ?

share|improve this question
add comment

2 Answers

up vote 1 down vote accepted

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.

share|improve this answer
    
+1 this helps point me in the right direction - never really thought about creating this ... but how does the cron launch the correct process ? big if statement to decide what method of what class to execute ? –  ManseUK Nov 24 '12 at 11:07
    
@manseuk: I would have the database name the class, method, and standard information. The class implicitly names the provider API. The cron will instantiate the right class, and call the appropriate method on that class, passing in the information from the database. That method will then know the correct API to use (be it email, a web service call, whatever.) –  btilly Nov 26 '12 at 1:47
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.