Small Improvements conducts Hackathons every few months which usually involves two days of hacking on an experimental project. Hacking doesn’t imply that it’s a “developers-only” affair either; other departments at Small Improvements like Customer Success and Marketing also get a chance to get experimental too. Hackathons usually give us a chance to really get creative about novel concepts and ideas for the product and company. It is about coming together as people to grow as a team – something that we at Small Improvements value as an important part of internal culture.
I like to think of myself as a coder of convenience. I often tell myself this work is just a means to an end – I am only coding till I can afford to spend the rest of my days lying in a hammock, drinking out of a coconut. But that’s not really true. If it were, I would be pursuing elite consulting gigs, or jumping from start-up to start-up on the hunt for unicorn stock options. Instead, after 15 years in the industry, I am working at a small, customer-focused company that turns a respectable profit building unpretentious B2B software.
The other day the owner, Per, asked me why I chose to apply for a job at Small Improvements. There were several reasons – not least of which was actually being able to talk about this sort of thing with my CEO – but I think my main motivation was because I wanted to help people again.
After a significant project involving making Small Improvements responsive, we came up with some UI ‘rules’ that we in the design team or (‘UI Taskforce’) agreed upon. The longer we worked on this refactoring and ‘cleaning up’ of the app’s style, the more we realised the importance of (finally) having a Style Guide.
At Small Improvements, we often have the front end developers implementing UIs faster than we (the design team) can keep up, so it’s important that they can access this guide.
A guide, a bible or documentation?
Given that we’re still a small team with plenty of feature-related projects on the go, I had a few concerns about taking on a project of this magnitude. There was fear of it becoming ‘half-finished’ project, something that gets outdated quickly, or even something that gets lost in technical implementation details. Out-of-date documentation is almost worse than no documentation. In considering the scope of this project (at least for the first iteration), I had to draw the line somewhere; Was this going to be simply a ‘guide’, or a definitive ‘UI bible’ with all the rules? How far would I take it and should we be creating Bootstrap-style documentation, complete with code snippets and workable examples? I also came across Lonely Planet’s awesome ‘Rizzo’ style guide, and felt very jealous they had the time (and resources) to do this, but hey… we’ll get there
I decided to start with focusing on making a ‘User Interface Element Usage Guidelines‘ page, as these were the most important rules to communicate to the Front End developers. We still called it a Style Guide, as it rolls off the tongue a bit better – and that’s where we’re hoping to end up!
As is the case for most projects at Small Improvements, we took an iterative approach and started with a small MVP and plan to progressively improve it.
Gathering content, creating a skeleton
Before worrying about any implementation details, I wanted to focus on the content and structure of the Style Guide, so we would know the general direction in which it could grow. Starting with a Google doc, I wrote some basic sections and headings to create the ‘skeleton’ that we would later ‘flesh out’. For the first iteration, we’d only focus on a few certain areas of the skeleton.
What guided the decision process of choosing which areas to focus on was generally this question: “What new rules have we decided on, and are they implemented consistently across the app?”. Sadly, there have not been a whole lot of style aspects that fit into this category, but it’s also a good thing because it meant this skeleton only had a few parts that needed to be fleshed out right now.
The First Iteration (MVP)
- A one-page Style Guide with content flowing down the page
- Focused on
- User Interface Element Usage Guidelines
- Code Style and Concepts
- We won’t paste sample markup, we’ll focus on referencing the Angular and React component names.
- We wanted the Style Guide to live as close to the app as possible – to be a ‘Living Style Guide’ and use real components. Thus, we implemented it as part of the Angular app. Longer-term, we might move it to the React world (which is where we’re heading) and experiment a bit with React Storybook too. But for now we’d keep it close to the Angular world.
- The Style Guide uses the same visual style as the app. Although in the app itself we don’t often lay out content in the same way (ie. long documents with multiple heading levels and sections), so there may be a few style-guide specific styles needed.
- We won’t really put code snippets in the Style Guide. Until we have a viable solution to render an actual component’s markup directly, we’ll just point the devs to the name of the component. After all, we all have access to the codebase.
- We’ll create Angular components for each section of the Style Guide and prefix them with sg- in order to follow the DRY principle as much as possible to keep it maintainable
- We started a Slack channel called #style-guide-feedback in which we can discuss new rules and how these would be added to the style guide
Conclusion and “Where it’s at”
Currently we’ve got the MVP done – and it’s being added to ongoing. There’s still plenty to improve with the layout, but the ‘skeleton’ is up there and able to be fleshed out as we go.
As a ‘UI Guy’, I’m really excited to have the Style Guide started and have a central place where we can really solidify our UI rules. I think the actual process of writing and documenting the Small Improvements style will help with creating a more consistent, sleek and polished UI.
Small Improvements and React!?
At Small Improvements we decided in early 2016 to shift towards React instead of working to migrate to Angular 2. Internally a lot of our developers had had great experiences with React and its ecosystem in their side projects. We wanted to keep up with evolving technologies rather than being stuck with Angular 1. Even though we already have a large frontend codebase in Angular, in the past 6 months we’ve also been able to implement new components and pages in React. We are confident that it was the right choice for the future. We also experimented with Relay + GraphQL, but it felt too premature to use these technologies at this point.
Development is hard. But communication is even harder – especially across departments and continents. Our SI Process Hacks series will highlight a few simple hacks we wish we had known right from the start!
We deploy many times a day – bugfixes, feature improvements, new options, changes in user flows etc. As a developer, you know when you committed, and you can see your commit go live in real-time:
But as the developer on another subteam, or especially as a non-developer, git-hashes are not really your preferred way of looking at things. It’s tricky to know when what change goes live on what day. Knowledge of changes is crucial, you don’t want to demo the product to a potential client and get caught off guard by that new button on a core screen.
We tried using Slack to keep people in the loop, we considered using a special Trello board, or including even tiny changes into our Release Notes. But everything was just complicated and never quite flexible either.
The challenge: Scaling
Our dev team has reached a quite impressive size these days! Unfortunately I just don’t scale to this size. I can’t possibly conduct 1:1s, listen to feedback, give feedback and help people grow in a flat team of 12 people. While I don’t code anymore these days, and have assigned most project management tasks to Feature Coordinators, lots of new responsibilities of a growing company are now on my plate. I just have to lean on others so that every dev team member gets the attention they deserve.
That’s why we introduced the concept of Team Lead two weeks ago.
I recently participated in Softwareskills’ Liar’s Dice competition, and since people have expressed interest to hear about how I managed to win, I decided to summarize the process and results.
As I prize I got 500SEK at Teknikmagasinet (Swedish store), a USB memory and this nice piece of paper🙂
Liar’s Dice and the Competition
Liar’s dice is a game where each player starts with six dice. One player starts by announcing a bet. A bet consists of a number and a face, for instance four fives. The next player can then either challenge the bet or raise the bet. You can read about the details at https://en.wikipedia.org/wiki/Liar%27s_dice. Softwareskills’ made a competition about writing the best AI. I noticed that it is not clear to everyone what an AI is in this context, and how to get started writing one. So let’s discuss that briefly.
Simplified View of an AI
An AI (actually Intelligent Agent [IA], but I’ll continue to call it AI) in its simplest form can be seen as a program that given a state responds with a valid action. A good AI must, in addition to producing valid actions, produce the best valid action given a state. What best means is the real challenge which typically requires mathematical analysis and creativity to figure out. In some cases you might calculate what the best action is, but it might not be easy given that you don’t know how your opponents behave. In the case of Liar’s dice you don’t know your opponents’ dice and they might behave differently depending on what dice they have. Let’s have a look at how I approached this challenge.
The Development of My AI
First off, I’m not developing AIs on a day to day basis. I had some experience from before, but not much. I started by drawing the “Simplified View of an AI” on a piece of paper, this made it easier for me to break the problem down into the main components:
- Generate all valid actions given a state
- Put a score on all valid actions
- Pick the valid action with the highest score
Let’s look at each problem separately, starting with how to generate valid actions.
To generate actions you need to create a function that given the current state and the rules of the game can produce all valid actions. This is pretty boring work that I wanted to get through as quickly as possible to move on to what could actually get me a good place on the top list. Softwareskills’ provided a model with a track that has 27 positions. A die on a position corresponds to a specific bet with the face of the die (some positions require the bet to be a star, where star = six). Now, either the bet can be challenged or raised. A raise can either be of a “higher” face on the same position or any face at a later position. So to generate valid actions I separated the problem into the following sub problems:
- Find the position of the current bet on the “track”
- Given the position and face:
- Get all bets with a higher face on the same position
- For all subsequent positions, generate bets with all possible faces
This allowed me to quite quickly generate all possible actions. Now, to value all the possible bets, provide them with a score, I needed to revisit some basic statistics.
When I first saw the competition I thought it was just a matter of calculating the optimal action using statistics. I asked myself whether I was more likely to win if I challenged the previous bet or if I raised the bet, and if I raise, how much should I raise the bet. Based on these questions I created new questions which I could directly “solve”, namely:
- Given my known dice, and the number of unknown dice in game, what is the probability of the previous bet to be true?
- Given my known dice, and the number of unknown dice in game, what is the probability of my raised bet to be true?
Simple was my first thought before I actually got started. I was easy to come up with a solution, and it could even work decently. The only problem was that it was wrong. And to reach the top of the toplist the number of afforded mistakes is pretty low. It was not easy to figure out whether the statistics was properly calculated or not. When I was stuck at a score far from the best, I challenged my code by doing static analysis, which in this case meant verifying the mathematics. I realized, by reasoning, that it was wrong. This led me to reach for my old book from school (Introduction to Probability and Statistics: Principles and Applications for Engineering and the Computing Sciences by J. Susan Milton, Jesse Arnold) as well as to look at a couple of lectures at Khan Academy (https://www.khanacademy.org/math/probability). After a couple of hours studying combinations, permutations and the good old “number of favorable events / number of total outcomes” as well as experimenting with simple examples, I managed to get it right. I jumped to the top but not to the first place. Something was still missing.
I wanted to go for a clean solution based on simple mathematics. But analysing the games made it clear that my AI was often put into bad situations, where no action was particularly good, and that it challenged the bet too often. It was not really playing the game, it was still just following the rules but a bit more intelligently. I started to add a lot of knobs now. For instance weighted averages and factors and terms of various kinds. I created an massive amount of mathematical functions whose graphs looked approximately as I wanted. Many linear (y=kx+m) as well as some polynomials of a higher degree. I experimented by taking into account everything I could think of, such as if I have a larger or smaller part of the game than the previous player or next player, if the game just started, the previous bets of other players and many other things. The factors could influence the score of an action. But I didn’t know how much they should do so. So I created knobs, factors that I could adjust to make the impact higher or lower. Then I tried to find the optimal values for the knobs.
I basically created a big optimization problem which I only could try to solve empirically. I did this in iterations. I created a lot of knobs, and realized that I couldn’t grasp what I actually did. Then I removed all of them and tried to create a new set of knobs. Repeated this a couple of times until I finally overtook the throne, meaning I finally conquered first place on the toplist. Even if I wouldn’t have won, I feel that this kind of competition is very valuable. To share why I think so I will briefly mention some things I learned from participating.
When I started the competition I didn’t even know there was a prize. This was just a nice bonus. I entered the competition for the challenge. I was sure that I would learn something. Afterwards I think my biggest gain is refreshing statistics skills. It’s quite fascinating how easy it was to do so despite not having worked with it for a long time. I also learnt that it is important to carefully measure the results when you have knobs, or parameters, that you can adjust. With the risk of using too big words, I would say that it taught me to be a slightly better scientist by clearly showing the necessity of careful measurements when empirically looking for optimal parameters. From a software engineering point of view it made it even clearer that correctness of the core is very important, and just because something seems correct it might still have bugs in it. Proper testing of the basic units (function in this case) is very valuable. And just because your solution is based on mathematics it doesn’t mean it will be right or wrong. It might still be slightly wrong.
Furthermore, I learnt the value of keeping the code in a at least decent state at all time, to not hinder oneself from experimenting due to the effort being too high. And finally, I learnt the value of to kill your darlings over and over. Even if you are at second place, when you’re stuck, start over and just keep the generic core which lets you build working solutions quickly. Don’t stick to your good solution just because you feel that you invested so much time in it. Challenge it! You managed to come up with it once, and probably learnt from it, so the next time you might come up with something even better.