Hack for HHVM Converting Facebook Julien Verlaguet Software Engineer
Facebook ▪ A large PHP codebase (> 10M lines) ▪ Thousands of engineers ▪ Performance matters! (HipHop, HHVM) ▪ The development cycle is fast: we push twice a day! ▪ PHP is a good technical choice to iterate quickly
PHP: how it all started! FAS T
Hack ▪ A statically typed language for HHVM ▪ Compatible with PHP: ▪ Interoperates with no overhead ▪ Same representation at runtime ▪ Instantaneous type-checking ▪ Designed for incremental adoption: ▪ Gradual typing ▪ Allows different “modes” (strict, partial, decl)
A simple example
Hack Types ▪ All PHP types: int, MyClassName, array ▪ Nullable: ?int, ?MyClassName ▪ Mixed: anything (careful) ▪ Tuples: (int, bool, X) ▪ Closures: (function(int): int) ▪ Collections: Vector, Map ▪ Generics: A, foo (T $x): T ▪ Constraints: foo (T $x): T
Hack ▪ We knew we wanted an IDE from day one: ▪ Usually, the IDE and the type-checker are distinct entities ▪ Hack is both a type-checker and an IDE ▪ The type-checker is a server (hh_server): ▪ The server type-checks all the files ▪ Keeps track of the dependencies ▪ Recomputes types when something changed
Question Can we convert millions of lines?
Prerequisites for conversion ▪ Address concerns regarding static-typing ▪ Have a backup plan ▪ Zero friction for developers (they can always bail out) ▪ Automated conversion
The concerns ▪ Too slow! ▪ Too verbose! ▪ Bad error messages! ▪ Not flexible enough!
Hack: you have nothing to lose! ▪ Too slow! ▪ Response time < 200ms ▪ Too verbose! ▪ Types are inferred ▪ Bad error messages! ▪ Error messages tell you how to solve the problem ▪ Not flexible enough! ▪ It’s gradually typed
When things go wrong? ▪ We are always strictly MORE restrictive ▪ In the type-checker: ▪ Removing a type-annotation never introduces an error ▪ Removing a type-annotation never changes the behavior at runtime ▪ At runtime: ▪ We introduce new constructions distinct from the old ones ▪ We make old constructions more warn or fail
Different modes ▪ <?hh // strict ▪ If all the code is strict then it’s sound ▪ <?hh ▪ Dynamic code is assumed to be correct ▪ <?hh // decl ▪ Don’t check the code, only consider definitions ▪ // UNSAFE ▪ Trust me: I am an engineer!
Gradual typing
Error messages You can try it online:
The rules ▪ If the entire code is strict, the code is type-safe ▪ Adding an annotation should never force you to add another ▪ Removing an annotation should never introduce an error ▪ Simple mental model ▪ Be “dumb” by default ▪ Scale
Conversion strategy: tighten the belt ▪ Convert everything to <?hh ▪ Add annotations gradually ▪ Build awareness ▪ More coverage for tools ▪ The problems: ▪ Gives a false sense of security ▪ Refactoring tools not really usable
Tighten the belt ▪ A global type-inference system to “guess” annotations ▪ A monitoring system to detect mistakes ▪ Refactoring tools to remove (or harden) annotations
Where are we at?
Question: can we scale this? Constant refactoring for language changes became a habit!
Let’s go back to the 90s
Release day (1999)
What happened? ▪ A cultural change (release early, release often) ▪ Tools (git, mercurial etc …) ▪ More code is visible (github etc …) ▪ What use to be painful became easy ▪ Thanks to a gradual process: every morning I “git rebase”
Can we do the same with programming languages?
The Facebook conversion ▪ Large enough / Small enough ▪ Lesson learnt, programmers must be able to choose: ▪ When (find the right time to upgrade) ▪ How much? (the upgrade process must be incremental) ▪ Where? (They can leave the parts that they don’t care about) ▪ Sometimes, the opposite is true, flip a switch (return types) ▪ Keep a simple mental model ▪ Controlling the code is a HUGE unfair advantage
The future of Hack ▪ Collaborate with the open-source community ▪ Tune the experience ▪ Provide more tools (IDE) ▪ Carry-on improving the language ▪ Make our own codebase more and more strict
Questions?