Developer UX, Tools & Errors for Humans
A Talk About Type Theory
Just Kidding
This is not a Type Theory Talk
Gradual Learning
When do you become productive?
Evan Czaplicki claims that you can pick up Elm cold and lean on the tools to become productive early on the learning curve. I decided to put that to the test, and see if developer UX improves learning. At least for n(1)
The Elm Compiler
-
If it compiles it (generally) works™
- Errors focus on Expected vs Actual
typesthings ;) - Beginner Hints
- Tries to catch logic errors
A simple counter
main =
beginnerProgram { model = 0, view = view, update = update }
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (toString model) ]
, button [ onClick Increment ] [ text "+" ]
]
type Msg = Increment | Decrement
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
Try to add a new button
Sad compiler
type Msg = Increment | Decrement
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
Reset ->
model - 1
Detected errors in 1 module.
-- NAMING ERROR -------------------------
Cannot find pattern `Reset`
30| Reset ->
^^^^^
1 more time
Still sad compiler
type Msg = Increment | Decrement | Reset
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
Reset ->
model = 0
Detected errors in 1 module.
-- SYNTAX PROBLEM --------------------------------------------------------------
I ran into something unexpected when parsing your code!
31| model = 0
^
I am looking for one of the following things:
end of input
whitespace
Finally
main =
beginnerProgram { model = 0, view = view, update = update }
view model =
div []
[ button [ onClick Decrement ] [ text "-" ]
, div [] [ text (toString model) ]
, button [ onClick Increment ] [ text "+" ]
, button [ onClick Reset ] [ text "reset" ]
]
type Msg = Increment | Decrement | Reset
update msg model =
case msg of
Increment ->
model + 1
Decrement ->
model - 1
Reset ->
0
A thing that works!
Now For The Demos!
Awesome!
So Elm is the new hotness and I should use it right?
Do you like functional programing
or want to learn more about it?
Great, maybe try Elm
I also kind of like Bucklescript
Do you hate functional programming
or perhaps just prefer OO?
Then don't use Elm, it is very much a functional language
But...
Elm has really nice tools and you should at least check it out so that when you write tools or libraries, you can pass some of these great ideas to your users!
Focus on a good user experience
- Provide clear error messages
- Don't assume your users are experts
- Make the documentation correct
- Make the documentation good
- Focus on the principle of least surprise
- Enable exploration/discovery
I love Elixir,
it has really great tools, most of the time
But not always
iex(5)> url = "https://auth.drxwebservices.com/v1/auth/token?format=json"
"https://auth.drxwebservices.com/v1/auth/token?format=json"
iex(6)> body = "grant_type=client_credentials"
"grant_type=client_credentials"
iex(7)> headers = ["Content-Type": "application/x-www-form-urlencoded"]
["Content-Type": "application/x-www-form-urlencoded"]
iex(8)> options = [hackney: [
...(8)> basic_auth: {"my key", "my secret"}]]
[hackney: [basic_auth: {"my key",
"my secret"}]]
iex(9)> HTTPoison.post(url, body, headers, options)
{:error, %HTTPoison.Error{id: nil, reason: :closed}}
WTF does that even mean?
So we updated the docs
Ruby's Pry makes it easy to explore, and tries not to surprise you
[27] pry(main)> cd String
[28] pry(String):1> ls
constants: BLANK_RE
Object.methods: JSON yaml_tag
JSON::Ext::Generator::GeneratorMethods::String::Extend#methods: json_create
String.methods: try_convert
String#methods:
% capitalize! each_codepoint indent purple squish to_r
* casecmp each_line indent! purpleish squish! to_s
+ center empty? index red start_with? to_str
+@ chars encode inquiry redish starts_with? to_sym
-@ chomp encode! insert remove strip to_time
# omitted because there are like 1,000,000 more
[1] pry(main)> cd String
[2] pry(String):1> show-method capitalize!
From: string.c (C Method):
Owner: String
Visibility: public
Number of lines: 33
static VALUE
rb_str_capitalize_bang(VALUE str)
{
rb_encoding *enc;
char *s, *send;
int modify = 0;
unsigned int c;
int n;
...
So Why Does This Matter?
Bad error messages make debugging more difficult
- Now it takes longer to squash user bugs
- We have finite time, and slow debugging means we get to do fewer things we may otherwise want to do
- Developers will abandon your tool/lib/language if its harder to use than it is valuable
Your Users Aren't "Experts"
- They may be, but that doesn't mean they are experts in your library, and they shouldn't have to be
- Do you want people to use your code?
Incorrect documentation is worse than no documentation!
Once the Docs are right, they need to be good
- This helps users find new functionality
- Good docs make your code easier to contribute to
- It reduces "how does x work" issues
Surprising Behavior is Awful
- Surprising behavior might mean your code doesn't have cohesive internal logic
- If a function behaves in an unexpected way, it will cause bugs
- Do you want people to use your code?
Enable exploration/discovery
- If users can discover functionality they'll naturally learn about your project
- A help function is great
- Writing readable code is even better
Thanks for Listening!
Chase Gilliam
@chasegilliam
Avhana Health
Dev UX
By Chase Gilliam
Dev UX
- 105