This week I read Adim’s post on the new things he tried this year.
While I haven’t learned a new language or embraced a new framework, I’ve tackled old problems in new ways.
A small app I built recently presents the opportunity to showcase these ideas and why they’re valuable from a practical context, rather than theoretical.
I built an app that tracks the sale of a promotional product from manufacturer to consumer, assigning tokens along the way based on a configurable product-to-token ratio.
Did I mention I had less than 72 hours to deliver the whole thing?
Front-end and back-end needed to be ready for hand-off in three days. I had a previous engagement on the first day so I lost 24 hours right off the bat. Still made the deadline and here’s how it happened.
The bit I was least interested in writing was the user management aspect, even though it was a super critical aspect to the project.
The manufacturer needed to add a customer to sell to. This could a consumer or a retailer. That scenario repeats itself down the value chain: resellers selling to other resellers or consumers ad infinitum.
This singular issue guided my decision on what platform to build the whole application on. I chose WordPress.
WordPress as a Framework
I don’t know if there are much better user management tools out there, but WordPress is my “something old” for this particular problem.
I figured the two real roles for the application were staff of the manufacturer and people who buy the product. The main differences are staff having access to promo-specific settings like item-to-token ratio or how many overall promotional products were manufactured, and treating multiple staff accounts like one cohesive entity.
I set up staff as admins and buyers as subscribers: the highest and lowest user roles in the system. Easy peasy lemon squeezy.
While the app was powered by WordPress, I needed a much more lightweight interface for admins and buyers. Not that WordPress is overly complicated, but the manufacturer produces construction material, so I needed something usable with no technology background. Using the standard (or customized) WordPress backend was not an option.
My solution was simple. All logged out users were redirected to the login page. Logging in redirects you to a page with 3 buttons; 4 in you’re an admin. These buttons have affordances. They dip in slightly on hover and even more on click. There’s no mistaking these links when you see them. Just in case, there’s a big block containing a sentence or two on what the app is for. It’s responsive and designed mobile first, so it’s relatively cruft-free.
The low page count and and interface simplicity mask just how complicated the inner workings are, so I’ll skip the relatively mundane basics of simple interfaces to highlight the more interesting bits.
The core purpose of the app is to track transactions flowing from the manufacturer all the way to the end user. In most cases, the seller is going to be on the app before the buyer is.
This presents an interesting problem. I don’t want users to have to wait for the buyer to join the platform before the seller can register a sale.
Which Came First: The Customer or The Sale?
The solution was pretty simple: let the seller record a sale before a buyer joins. To make a sale, the seller adds a customer to their list with name and an email address. The seller can now register sales against new customer even before they finalize their account. The account is created by the seller and access is emailed to the buyer.
What happens under the hood is the seller creates a subscriber account in WordPress with the email address of their client. WordPress sends the new account a password reset link. They set their password and they’re in!
What happens if the buyer is already in the system? It simply adds that account to your seller list. Nothing magical.
It was an interesting new way (to me) to handle account creation and I really like how it turned out. Turns out it wasn’t the most interesting strategy I built into the app.
Make Logs Not Edits
Remember the whole purpose of the app is tracking transactions and tokens? The obvious strategy would be transactional updates to a database table when a sale happens. Reduce one user’s quantity, increment the other user’s by the same amount. I tried something new here instead.
Instead of calculating the values of a transaction and storing the result in the database, I stored the actual transaction instead and calculated the resulting values every time it needed to be displayed. Sounds like a minor difference but this was by far my favorite “something new” to try.
Typically our applications calculate the difference a transaction brings and generates a query to update the database state. While this is sufficient because the database tells us what the state is, we can see how, when and why the application got into the state it did by storing transactions instead.
These may be esoteric concerns to you, so here’s a practical benefit.
In a traditional storage strategy, you calculate the difference and apply the change. An error in calculation code results in your data in a corrupted state. Remember you only have the state, not a record of how it came to be that way. Fixing this mistake is going to be very difficult.
An error in calculation in a transaction storage system results in the wrong data being displayed, but the truth is right there in the database. Update your calculation code and the right data immediately shows.
This was important because I made a calculation mistake and it resulted in wrong seller quantities being displayed. A quick code change and the right numbers showed up instantly.
To implement transaction storage in WordPress, I created a custom post type. Every sale was a new post. The author was the initiator of the sale. Post publish time is when the transaction went through. The post metadata contains the quantity and the recipient. Absolutely simple.
One more “something new” from this project: end-to-end version control with automatic deployment.
Git is nothing new to me, but its primary purpose has been to keep my working code version controlled. I’d previously used it for deployment via Beanstalk (thanks Adim!) but it wasn’t until I used Heroku that it became a requirement.
Push So Many Commits Collaborators Call Me Narco (or Pablo)
I hacked together a script that sat at an endpoint. When run, it pulled the latest commits and deployed it to the WordPress theme directory.
Next, I set up the origin in the repo to hit the endpoint when the master branch updates.
Deployment instantly became as simple as git push from my development area. Within seconds the changes were live. It became trivial to roll back or push changes.
Something Borrowed, Something Blue
All things considered, it was a pretty interesting year for me, as exemplified by the app. While I didn’t voluntarily add new bits of technology to my toolkit, I learned a lot by borrowing ideas from different places and applying them in new ways and connecting them together to create more interesting systems.
The idea of storing logs wasn’t mine. I read a really interesting piece on the idea but didn’t occur to me that I don’t need a special database to try it. Not til this app. My deployment setup is inspired by Heroku.
No individual piece was new but the end results are vastly different from what I started out with.
My year’s been about hacking at red-hot pain points like writing user management systems til I have a solution that brings me to the deep blue sea of tranquil.
No flashy headlines like new frameworks or languages but best believe it’s been an interesting year and I can’t wait to see what next one holds for my toolkit 🙂