I'm using php
to create a USSD page. I've done this before and it was quite the time-constrained hack-job; basically one huge file with a switch statement for all the possible states that the cellphone user can be in (which is then saved in a DB and retrieved upon the next USSD request) -- a state machine of sorts.
This time round I have a bit more time and would like to use something more professional. Are there any design patterns or best practices that I can use for this kind of scenario?
Ok, so searching for something USSD specific was a mistake. Simply replacing USSD
with state machine
gave me the answers I was looking for.
I've battled with this problem too. My approach is to use a tree where each ussd state is a node. Let me illutrate the best way I can
interface Node {
render(),
process(input)
}
The nodes are classified into Selection and Input nodes.
Selection
Selection nodes simply present users with options that the can choose from then refer the user to one its child nodes or display an error message
class Selection extends Node {
Node[] children;
string title;
render() {
// create a ussd menu here appending title to
// menu items based on this.children
}
process(input) {
// get input and select from children node
// call its render method
}
}
Input
Input nodes collect actual input from users (like names, voucher number, etc) and do processing like query a database or call a remote API, then present the user with a response.
class Input extends Node {
string title;
string instruction;
Handler handler;
render() {
// show title and/or instruction to user
}
process(input) {
// validate input and then pass to this.handler
}
}
To further decouple logic, I added a handler interface, every Input node needs to have a handler. All the processing logic resides in the Handler
interface Handler {
handle()
}
Resolver
Now with this you create a Resolver class that handlers the ussd session information, and all the http stuff (if you're receiving ussd requests via http). The Resolver also transverses the tree based on the user input to collect the responsible Node then either calls it's render or process method. Your tree with look something like this
new Selection('Main Menu (title)', [
new Selection('My account', [...]),
new Input('Recharge', 'Enter voucher number', new RechargeHandler())
]);
This is a limited solution specific to my use case, I believe it can be extended to cater for other situations. I would like to hear how everyone else is solving this problem