In 2007, right before the first iPhone launched, Marc Andreessen asked Steve Jobs the obvious question: The design of the iPhone was based on discarding every physical interface element except for a touchscreen. Would users be willing to give up the then-dominant physical keypads for a soft keyboard? His answer was brusque: "They’ll learn." Steve turned out to be right.
A great deal of product development is based on the assumption that products must adapt to unchanging human needs or risk being rejected. Yet, time and again, people adapt in unpredictable ways to get the most out of new tech.
People change, then forget that they changed, and act as though they always behaved a certain way and could never change again. Because of this, unexpected changes in human behavior are often dismissed as regressive rather than as potentially intelligent adaptations.
But change happens anyway. "Software is eating the world" is the most recent historic transformation of this sort.
Creative people tinker to figure out the most interesting applications, others build on those, and entire industries are reshaped.
This incremental approach is the very nature of startups and is examined in Breaking Smart, quoted throughout this lecture.
We have begun operating a transition to software-first computing. Ride-sharing is a great illustration.
To traditionalists, particularly in the United States, the car is a motif for an entire way of life, and the smartphone just an accessory. To early adopters who have integrated ridesharing deeply into their lives, the smartphone is the lifestyle motif, and the car is the accessory. To generations of Americans, owning a car represented freedom. To the next generation, not owning a car will represent freedom.
And this dramatic reversal in our relationships to two important technologies – cars and smartphones – is being catalyzed by what was initially dismissed as "yet another trivial app."
Today we are almost able to put a chip into every single object on earth at a minimal cost and interconnect these chips. Making this useful and changing our world by doing so is going to be done with software. We're only at the beginning of this transformation where software is eating the world.
A typical startup begins by selecting a domain, formulating a hypothesis, iterating within this domain and only then, maybe, discovering a business where customers are willing to pay for a product. Thus, many startups are 100% software. It's a medium in virtually infinite supply with incredible potential where a "trivial" app can change our world.
How do we approach building a technology company? What does this all mean in the context of Software Engineering?
At its simplest, a technology company enabled by software has many possible outcomes (or futures). A startup may pick one such future and attempt to iterate towards it. Often, after making a few steps it will learn something new, make a turn or abandon the entire path and pivot. Therefore, the Software Engineering practice in a startup has two almost conflicting responsibilities.
- Deliver working software to achieve the outcome currently chosen.
- Enable all possible outcomes.
One could deliver working software to achieve the outcome currently chosen by carefully planning the entire path, dividing the deliverables into milestones, then implementing these deliverables. The question asked by the waterfall model is What are all the steps I need to make to achieve my outcome?
However, many of possible outcomes are yet to be discovered. This model doesn't easily allow to ensure all possible outcomes, or at least carries the risk of going too far in the wrong direction.
Instead of considering the entire path towards a future outcome, consider just the next step, implement it and reexamine the situation. This is sometimes called an agile, but more generally is an iterative model. The question asked by this model is What do I need to do next to achieve this and possibly other outcomes? Iterative or agile comes with various ways of practicing it, from Extreme Programming (only focus on what you need to do next), to Scrum (plan an iteration that lasts a few weeks) or Kanban (use a control system).
To achieve any outcome, an Engineering practice must create a repeatable system in which what we are trying to make may change rapidly, but how we make can be an increasingly solid foundation that makes more of everything possible as time goes by. From a purely software engineering perspective we begin by creating a development workflow that, in turn, contributes to establishing a development culture.
We need a bare minimum of process in which a group of committed individuals is iterating with software. This group includes pigs and does not include chickens from the business fable of The Chicken and the Pig. This can take a form of a get-together in which individuals propose tasks that can be accomplished by them (eg. setup source control) and the next meeting (eg. a quick check-in tomorrow at 11am) is decided.
It's equally important to maintain a strong working relationship with the chickens, though. One possible way of doing it may be to collaborate on a domain wiki (see below).
The number of tasks is going to grow rapidly, so we need a place to track them and to provide visibility into them.
We need a place to put ideas, next workitems, items being worked on now, and done items. The focus should be on simplicity, systems like Trello or Waffle.io work well. It's the responsibility of each team member to create and move their tasks around.
Most projects model some elements of the real world, so it's important that all team members use the same language and that the same words have the same meanings in everybody's minds and code. Phil Karlton (at Netscape Communications, Phil held the title of Principal Curmudgeon), once said: There are only two hard things in Computer Science: cache invalidation and naming things. One good way to understand the domain is to create a written taxonomy and to discuss terms between team members. Working on a domain wiki is a great way to engage non-engineers in regular conversations with engineers, an essential collaboration.
Source Control, also known as Version Control or Revision Control lets you track files, particularly code, over time and to effectively collaborate between multiple engineers. It also provides history, so you can experiment with a safety net.
We're going to learn Git. Git is a fast, open source, distributed version control system. It's unlike CVS, SourceSafe, ClearCase, Subversion or Perforce, and is somewhat like Mercurial (Hg). Distributed means it works offline. Git is an essential enabler of the open-source ecosystem as the fork and pull model is the default open-source workflow.
A development environment is a set of tools and settings that you are often familiar with. An interesting way of creating a repeatable environment across multiple computes is dotfiles, enabling you to backup, restore and sync preferences and settings for your toolbox, share yours and learn from others.
An editor is one of those essential tools in your toolbox. These days most developers use a range of text editors to integrated developer environments. Most popular editors are Sublime Text, Vim and Emacs. There're some more specialized editors, such as Eclipse for Java and some newcomers like Atom.
When you start a project, write a Getting Started guide that explains how to setup the project. Often it's just a README.md document. When a new developer starts working on a project they typically begin by reading this guide and updating it with any changes that have not been made as the project evolved. Those changes are often their first commit.
The quality of the onboarding documentation usually speaks volumes about the project.
Every major project has its own style guide: a set of conventions (sometimes arbitrary) about how to write code for that project. It is much easier to understand a large codebase when all the code in it is in a consistent style. There're style guides published by companies like Google and style guides enforced by software, such as RuboCop. Generally the purpose of a style guide is to make code look as if it were written by one person.
Continuous Delivery is a software engineering approach in which teams keep producing valuable software in short cycles and ensure that the software can be reliably released at any time.
A good system can be setup locally, setup for testing by 1 developer, setup for testing by a group of people (often called a staging environment) and, finally, setup for production that looks identical to the staging environment. The process of taking code to production as soon as something valuable is ready is called continuous deployment. It's an important part of continuous delivery. This notable means that deployment can happen at any time, so you must write code in a way that doesn't break existing features and try to add small value as often as possible, as opposed to a lot of value at once. Continuous deployment trives to reduce the amount of changes going to production at once, therefore minimizing risk.
The cost of fixing bugs grows exponentially as broken software goes to production. Continuous delivery has an emphasis on catching issues early, sometimes even before any code is written. This is called Test Driven Development, where tests are written first. There're unit tests, integration tests, etc. Good tests allow new developers to feel confident in a project or provide explanation about how something is supposed to work and sometimes even explain why.
Tests are a great way to write good working code. First, you create a unit test that fails. Then you write production code that makes the test pass. Then you run all the tests and cleanup the mess you just made (refactor) until you're satisfied with the quality of your code. This is called a red, green, refactor cycle.
Every time code leaves your personal computer you run all tests. Every time code is merged into a repository from which it goes to a staging environment the same tests (and possibly more) are run. The process of running more and more tests during these integration points is called continuous integration.
Code review is systematic examination of code. It is intended to find and fix mistakes overlooked in the initial development phase, often simply by adding a pair of eyes to look over the new code. Open-source workflow with Github pull requests is the most popular code review system today.
Pair programming is a technique where two programmers work as a pair together on one workstation. One is the doer and types code and the other is the thinker giving instructions. It's another form of code review. The two programmers switch roles frequently.
See this link for homework and your startup project for deliverables for next week - a startup project pitch.