Wednesday, March 29, 2017

Talking 'bout that Functional Spec

What's a spec?

A spec is a reference for what the software should do.

Who uses the spec?

Everyone who is working on the product. Devs, QA, BAs, Managers, Marketing, etc.

How do I know it's good?

Here's a test - QA should be able to use scenarios in the test directly. They should be able to create accounts based on characters, follow through their routine activities and the non-routine activities as describes in the spec.

A sample



PizzaMeNow is an app for ordering pizza online. Users can order for pick-up or delivery. Users select how many people they're feeding and what toppings are good to go. They pay for their pies through the app (paypal, CC, maybe bitcoins or whatever else).

Scenario: Big Party.

Rick is having a party for the big game. He has 20 friends coming over and wants to serve up some great pies. He opens up PizzaMeNow and plugs in his phone number and address, fills in 20 for how many people and selects the "party varieties" toppings (which includes the usual suspects that you find at any pizza party - cheese pizzas, sausage pizzas, pepperoni pizzas, supreme). He's ordering ahead a couple hours, the party starts at 4 so he selects the 6:00 delivery time slot that same day. He sees the note that says it could get there +/- 15 mins of the selected time, he's ok with that and proceeds to checkout. He uses his PayPal account to checkout. 6:05, the party is on and the pizzas arrive - now it's time to really party hearty! 6 grande sized pizzas from the Pizza Shack, plenty to go around!

Scenario: Lonely Chad.

Chad is newly single and kind of nerdy. He is bit down and feels a bit like staying in for the weekend and watching all of the Hobbit and LOTR movies in order. It's going to take awhile and he doesn't want to have to break mid-action to make food. He logs into his favorite food app PizzaMeNow and orders pizza for lunch and dinner for both days. He places multiple orders and pays for them all at once. He wants it all fresh an hot, so he selects 1 person on each order and declines the "enough for leftovers" option. He prefers a bit of variety, so he puts in different ingredients with each order (somehow matching the theme of each movie that will be playing while he's eating each pizza). He confirms the four orders and checks out using his bitcoin account.

Scenario: Hungry Kids - "Pizza Again..."

Judy is a working mother with four kids and a hungry husband. She has the drill down for Friday nights...family game over pizza, babysitter and out. She uses PizzaMeNow regularly so she has a profile. She uses the "Reorder" option to place the same order as last Friday. She has the autopay option set up with her CC info so it just works. She is hoping one day that a simple text message from her phone will replace the bother to go into the app to place her order, but she is happy to be up and running so quickly (and get her order in while the car is stopped at a red light - maybe she is one-of-those-people or maybe she is in the passenger seat).


Each of these scenarios tells a user story that describes how the user will actually use the app. I'm using scenario here but User Story could work too, however there is app interaction involves and user stories typically involve the description of need without describing how they interact with the app...you know the type - As a mother of four plus a husband, I need to order our usual order quickly so that I can get on with my life...Ok, so these scenarios are a bit more like use cases combined. Use Case 1 : payment. Use Case 1.2 : pay with paypal. Use Case 1.2 : pay with CC. Use Case 1.3.a : pay with Visa....and so forth.

We'd really like to have scenarios for fails too ...

Scenario: Angry Dad.

Jim's wife Deborah ordered a pizza through PizzaMeNow and it's over 15 minutes past the selected time. The app said +/- 15 mins and so now it's late and Jim is hungry...hangry even. He searches the app furiously for a contact us link. There is no link to be found. He goes online immediately to the app store to give the app a terrible review...just then the phone rings. The driver is lost trying to find the place, meanwhile Deborah receives a notification that their next order will receive a discount automatically along with an apology for the delay in receiving their order.

Scenario: Can't pay.

Voldo is a bit of a scatterbrain...he put in his order, but forgot that his CC was maxed beyond maxed when he used it to pay for his pizzas he ordered through PizzaMeNow. He was is such a hurry that he didn't even wait for confirmation before exiting the app. He receives a text message saying that his order was declined and that he should supply another form of payment. He taps the link to open the order in the app and is immediately brought the order confirmation page. He proceeds to payment and uses a different payment form. This time he gets the confirmation in the app and all is well in his world.

We can see based on these scenarios the various features that we will have to develop in order to deliver to our users (pun intended). As the fictional users exercise each feature, we can begin to understand how they will be using the application. While writing these scenarios we can imagine the user experience when say they can't find their CC to pay for something, so we know we would want them to be able to come back to their order and pay later when they've found it. As we develop our scenarios further we can go into more depth of detail with each feature - perhaps create scenarios involving only one feature (requires some context usually though). This sample is not a complete spec, but only describes some possible real world uses of the application. They can get everyone in the mindset of thinking about how to design, develop and test the app. Consider, for example, how we would test the "Angry Dad." scenario...would we want to wait the whole time for the delivery plus the 15 mins to test that feature? Or would we want some control over those configurations so that we can just FF to the late state and trigger the email and phone call (btw: did the app call the driver and the customer or was that all the driver?)

Monday, March 6, 2017

Functional Programming like an OOP-er?

So, I've been learning much about Functional Programming techniques. Elm-lang is a great budding FP language that transpiles to javascript and is optimized for the browser - haven't seen much in the way of server-side packages for it...but then again, I haven't really looked.

One key feature of the FP languages I wan't to riff on is Currying - basically it's where you create a new function that does the same thing but with less parameters and you set defaults.


In javascript, for example if you had the following function...

    function saySomething(message, person){
        ...
    }

you could curry the message and create a new function to sayHello

    var sayHello = function(person) {
        return saySomething("Hello", person);
    }

Well, that's all well and fine. Our sayHello function would only be able to say "Hello" as that would basically be set in stone for this "instance" of saySomething. I said instance didn't I? Couldn't think of a better OOP way to put it. It's also called a closure isn't it? Basically we are creating a function object that has a locally scoped value of "Hello".

It could also be written like this (which is a bit more re-usable):



    var sayHello = currySaySomething("Hello");

    function currySaySomething(message) {
        return function(person){
            return saySomething(message, person);
        }
    }

//or if you like

    function currySaySomething(message) {
        return function(person){
         var _message = message;
            return saySomething(_message, person);
        }
    }

And in this way, an instance of the function object "saySomething" is returned as a closure with the locally scoped variable "message". It can be done another way...this one is straightforward OOP in javascript.


    var helloSayer = new HelloSayer();
    helloSayer.sayHello({name:"Li"});

    function HelloSayer() {
        var _message = "Hello";
        return { 
            sayHello : sayHello
        };

        function sayHello(person) {
            return saySomething(_message, person);
        }
    }

Well, that's an OOP way to do it, but it still meets the same goal of immutable state that's important to FP. But if you think about it - currying is really setting the internal "state" of a function. It's kind of like using a Factory, although in the example below it might be a bit overkill - could just use new Sayer("Hello"), but that's not the point of a Factory. If you need a Factory, there it is.


    var factory = new SayerFactory();
    var helloSayer = factory.build("Hello");
    helloSayer.sayHello({name:"Li"});

    function SayerFactory() {
        return { build : build };
        function build(message) {
            return new Sayer(message);
        }
    }

    function Sayer(message) {
        var _message = message;
        return { 
            sayHello : sayHello
        };

        function sayHello(person) {
            return saySomething(_message, person);
        }
    }

I guess what it comes down to is how you use the objects. One could have objects that hold internal immutable state. Using an OO language it's often necessary to avoid overly-complex, unreadable code.