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.

Wednesday, February 1, 2017

Fix Your Coding Style Cause it Causes Errors!


This enthralling academic paper http://web.stanford.edu/~engler/p401-xie.pdf titled "Using Redundancies to Find Errors", came out of Stanford in 2002. It shows that analysis of redundancies in code "seemed to flag confused or poor programmers who were prone to other error types."


Some examples of the kinds of redundancies mentioned in the paper include: unused variables, reassignment of variables for no purpose, mathematical redundancies such as x/x, x|x, etc., logical branch and case statements which either always eval to true or false or are never reached, dead code - statements that are never reached due to an early break or continue in a loop.


Most of the examples given in the paper are the result just plain sloppy and/or lazy programming style. You see it too many times - copy-paste code, terse conditionals, disconnected variable names, poor structure and flow. My advice to anyone seeking to get better at programming is to reread your code before you commit. Write it three times - once to make it work, a second time so you can read it and a third time so everyone else can read it. When your done with it, you should be able to show one of your QA engineers the code and they'll know what it does! Then you know what you should do? Rewrite it again - this time to make it more concise, you could be missing out on something important like an opportunity to reduce the size of the code base, crate some reusability, or remove some diabolical nested if statements (one of the worst sins of programmerkind).


Look, if you were writing a book, would you be allowed to write the first draft and sell it as soon as you've written the last word? Hell NO! No one would want to read it anyways. It would contain several grammatical errors as well as redundancies, illogic, contradictions, and shit that just plain don't make any sense! Why would you abuse any language in such a manner? Languages are made to communicate. Programming languages are no different.

Tuesday, January 31, 2017

Database Development The Iterative Way

As I recently became more involved in developing a data layer (including database) I've been learning a new style of database migration. Previously, I've written plain SQL for database migrations for each deployment. Those were handed off to a DBA to run in each environment.


These days, I've entered the realm of Liquibase. Liquibase is my first experience with this sort of tool that allows for source controlled, database versioning. It's written in declarative style and translates the declarations into the underlying SQL. It's cross-platform and supports multiple declarative languages (JSON, XML).


Here's how it's changed my development process: In the old days, I used to write the SQL and run each file or put it all in one file and run as a batch. Then write some queries to validate, interrogate the schema etc. I would do mostly up-front design of the database components. Most of the queries and commands were generated by EF or in code. Other factors have changed that as well.


Nowadays, I'm writing a lot more stored procedures with none of the sql in code or generated by code. I'm writing tests first. Then I'm writing stored Procs, then creating/modifying tables declaratively via Liquibase. Sometimes I don't care about the table of the column until it's really needed. Sometimes the name of a column morphs during an iteration (a short cycle of failing test-code-passing test on the order of minutes). Nowadays, no problem! It's relatively simple to change a column name.


The big trick/advantage is that everyone else can pull in those source controlled changes and have their local databases updated by running a batch file or using a git hook. It only applies changes that are new on the target database, so if they haven't updated in awhile it'll apply all those changes until they are up to date.


It's all good! I never really had a chance to dig into EF code-first migrations to this degree. If its the same or similar in efficiency, I would recommend it for sure! Or any tool that enabled rapid changes to the backing store which has acceptable trade-offs (here's looking at you noSQL).

Wednesday, January 18, 2017

Names

I've been hearing this phrase a lot lately "words have meanings". I've also been reading more of Domain Driven Design by Eric Evans, in which he stresses the importance of Ubiquitous Language. When we communicate about our work, when we collaborate as social human beings (even the most antisocial rely on social networks for survival - see the NatGeo show Mick Dodge) we use language. It's what makes us human, its what makes us powerful. Our very fabric and existence is a product of our ability to communicate, coordinate, and work together.


So when we communicate, we are more effective when we do so effectively. We do so partially through word selection. Words do have meaning. And, they have meaning in context. In the past, I've been exposed to the usage of Unit Testing used where the word Functional Testing was more appropriate in my context. To me (and I assumed the rest of the world), Unit Testing is when a developer writes automated tests at the lowest level of code she owns. To the other person, it meant manually testing each functional unit as exposed to the user - which I know as Functional Testing.


Here was a case where we were working at cross purposes whenever we were talking about Unit Testing. She pulled rank and had the term redefined in her world so that context switching had to happen...for all developers on the team. When she uttered the phrase "do Unit Testing" our minds immediately went to thoughts about writing code with test doubles, scenarios, and defining test cases for each string parser and logical branch. But we had to go against what we know and live in this other reality for a bit - fighting our neurological pathways which were forged over the years.


Every conversation in which more than one term is used to describe the same thing and especially where one term requires special domain knowledge is going to see a reduction in effectiveness. Words have meaning in context. What do we do about this? Especially when the same word has meaning in different contexts...


I propose the following: Combine context with the subject so that ambiguous terms become less ambiguous. Instead of Employee say Payroll Employee. Instead of User say Blog User. Say Functional Unit Testing, Ad Campaign, War Campaign, Political Campaign, Shipping Container, Bank Account, User Account, User Role, etc. Use contexts as containers for the concepts in which the words have meaning.


One term came up recently...owner. Owner is such an abstract concept that it must be used with some subject to show context or there will be wholesale confusion, particularly when there is more than one owner context involved. Home Owner and Business Owner have very different connotations...think of how many just in terms of taxes. So what if taxes was the context? Might we say the Tax Homeowner or the Tax Business Owner? Or is it enough to imply tax is the context - depends.

Thursday, January 5, 2017

Best...Estimation...Method...Ever!!!

Alright, so estimates suck and we all know it. Plenty of reasons why and models to try to get it right. But hey, were human and we're subject to all kinds of flaws. Well, here's a method that a colleague and I came up with as a joke at first. But now that I think more about it...it seems to be just as good (maybe better than) as any other method.


What you'll need:


1 sheet of paper, whatever size.
1 writing device (pen, pencil, marker, crayon, go crazy
1 coin with 2 different sides (heads/tails)


What to do:


Step 1: Prepare by drawing a circle on the paper and place paper on flat horizontal surface (desk or floor).


Step 2: Pick a number for the task as a starting point. esty := n;


Step 3: Flip the coin at the paper.


Step 4: If coin lands in circle, return esty.


Step 5: If coin is heads, increase esty and loop back to Step 3.


Step 6: Decrease esty and loop back to Step 3.


Why is this method awesome? Because first of all you use your gut to produce the original estimate - always go with your gut.


Second of all, if you really feel strongly about your number, then you'll hit the circle. Else, the randomness of the coin introduces some real-world randomness that you'll encounter in the real-world...for real!


Some models call this a Monte-Carlo factor and use some pseudo-random number generator to add pseudo-reality to the equation...that's weak compared to the good old trusty randomness of a Wheat-Back Penny!


Be sire to break down those tasks a bit. You wouldn't want a single coin toss to determine the fate of the whole project - you want more samples to produce the desired results!


Oh, and generally I'd use a scale for the numbers like: .5, 1, 2, 4, 8, 16, 32,... In hours. If you throw bigger than 32 (that's more than full week if you really get down to it) maybe you better break it down a bit more.


Ok, there you have it! Make those circles and start tossing your way to successful estimation!

Tuesday, November 29, 2016

Making the Most of Memory


Always so much to learn. For example, did you know that the time it takes to access your computers memory is MANY times slower than the time to access the CPU caches? What does this mean for how we structure our programs and architectures? We'd want to take full advantage of the CPU Cache (L1) and the L2 cache if we are concerned at all with application performance. What this means is structuring components and code so that caches can be used.


Even if we go only to the DRAM (and not disk cache), it only holds the data for ms before having to be refreshed...this means you have under 100ms (as of the article in 2008) to process everything in memory before it cycles and has to be refreshed.


All of this has implications on the design of your objects, structs, etc. SRAM in the L2 cache is limited in memory space due to power consumption and costs. Given this, it seems logical that keeping your data bags as small in size as possible would be of great advantage to performance. Additionally, limiting loops and batches could also help to improve performance.


Architecturally speaking, since operations are also cached in the L1, you'd want to keep the same operations (looking at you data access) on the same CPU/L1. So much to learn...


Read about it in depth at https://lwn.net/Articles/250967/