Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

PHP to Hack at Slack

94 views

Published on

Discussion of the Hack programming language, and Slack's transition from PHP to Hack.

Published in: Technology
  • Be the first to comment

  • Be the first to like this

PHP to Hack at Slack

  1. 1. Scott Sandler - June 2019
  2. 2. Scott Sandler Senior Staff Engineer @ Slack 2015 - Present
  3. 3. ● Static type checker, hh_client ● Language Server Protocol ● VSCode, VIM, Emacs, and more ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  4. 4. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  5. 5. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  6. 6. “Generic programming is a style of computer programming in which algorithms are written in terms of types to-be-specified-later that are then instantiated when needed for specific types provided as parameters.” - Wikipedia Type Parameters like <T> allow classes, functions, and data structures to act on multiple types ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  7. 7. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  8. 8. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  9. 9. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  10. 10. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  11. 11. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  12. 12. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  13. 13. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  14. 14. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  15. 15. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  16. 16. ● Represent an array with known structure ● Named keys with known data types ○ Keys can be optional ● Structural subtyping ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  17. 17. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  18. 18. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  19. 19. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  20. 20. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  21. 21. ● Inconsistent Argument Order ○ array_map($callback, $array); ○ array_filter($array, $callback); ● Misleading return types ○ strpos() returns int OR false ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  22. 22. Read from inside out… or split into multiple lines and name each intermediate value? ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  23. 23. ● Consistent Argument Order ● Consistent Return Types ○ null instead of false ● Namespaces: ○ Container Functions: Vec*, Dict*, Keyset*, C* ○ Basics: Str*, Regex*, Math* ○ More: IO*, PseudoRandom*, SecureRandom* ● |> Pipeline operator for chaining function calls ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  24. 24. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  25. 25. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  26. 26. ● Overview ● Static Type Checking ● Generics ○ Arrays ○ Hack Arrays ○ Shapes ● Standard Library ○ Pipeline ○ Typed Regex ● XHP
  27. 27. ● async/await cooperative multi-tasking ● is/as keywords for type assertion ● lambdas ● enums ● <<__Memoize>> caching ● hackfmt ● Function Autoloading ● VSCode debugging
  28. 28. Migrating Slack
  29. 29. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  30. 30. Fix hh_client errors ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  31. 31. ● Hundreds of bugs ● Convince typechecker ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  32. 32. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  33. 33. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  34. 34. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  35. 35. New Linter: HHAST ● Hack Abstract Syntax Tree ● More rigorous linters ● Migrations as well Old Linter: PHP_CodeSniffer ● Stream of tokens ● Each linter is a mini-PHP parser ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  36. 36. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  37. 37. Foundational Types
  38. 38. After: AsyncMysqlClient ● Shapes for each table ● Async queries Before: mysqli ● Untyped arrays of strings ● Synchronous queries ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  39. 39. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  40. 40. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  41. 41. ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  42. 42. Untyped code ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  43. 43. Untyped code ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  44. 44. Type Coverage
  45. 45. Colorized Type Coverage ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  46. 46. Coverage Numbers ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  47. 47. Track it and pipe it to Slack ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  48. 48. <?hh // strict 1. All functions and arguments must be typed 2. No top-level code 3. Other dynamicism like $GLOBALS banned ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  49. 49. Eliminate PHP Dependencies 1. Smarty to XHP migration ○ Smarty Parser -> hack-codegen 2. Other dependencies: ○ Convert to Hack ○ Remove dependency ○ Run as PHP7 web service ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  50. 50. HHVM 4.0 Upgrade ● <?php to <?hh ● Fix hh_client errors ● Blocking CI tests ○ hh_client ○ Linter ● Move code into functions ● Foundational Types ○ DB Shapes ○ Inferred returns ○ Untyped code ● Coverage Competition ● <?hh // strict ● Eliminate PHP deps ● HHVM 4.0 upgrade
  51. 51. ● Thousands of bugs found and fixed ● Entire classes of problems eliminated ○ Call to undefined function ○ Missing include/require ○ Missing array keys ○ Missing null checks
  52. 52. ● Developer Surveys ● Increased confidence ● Increased productivity ● “When the type checker passes, my code usually works on the first try”
  53. 53. UI Integration Unit
  54. 54. UI Integration Unit Types
  55. 55. ● Types are the cheapest unit test ○ ...but only when you have a lot of them ● Types are the cheapest documentation ○ Especially complex types like shapes ● Typing is best done as part of feature work Lessons Learned
  56. 56. Yes, this is possible ● Generics RFC ● Arrow functions in 7.4 ● Property type hints ● JIT in PHP8 ● Static analysis: ○ phan: https://github.com/phan/phan ○ phpstan: https://github.com/phpstan/phpstan ○ psalm: https://github.com/vimeo/psalm
  57. 57. ● eval(), create_function(), extract(), compact() ● $GLOBAL variables ● $$variable variables ● call_user_func() ● &$references Avoid PHP’s most dangerous features

×