Hixie's Natural Log

2021-01-14 19:55 UTC Ask for forgiveness, not permission

A colleague of mine asked me to explicitly put an LGTM on their design doc so that they could go ahead and implement it. The design doc was one I had previously reviewed and commented on, and had indicated that it seemed like a good idea, but I hadn't filled in the box saying that "my TL has said LGTM".

My answer: no. You don't need my permission.

Ask yourself: why do you want explicit permission? Is anyone asking you to get permission? What would happen if you just... did the thing?

Some people want LGTMs because that way they feel like if they make a mistake, they'll be covered. But that's flawed thinking in two ways. First of all, mistakes are fine. People make mistakes, we all make mistakes, mistakes are how we learn. If you're not making mistakes, then you're not taking enough risks to be successful. Secondly, even if making a mistake was bad, getting some people to sign off on something doesn't mean they are taking any more responsibility than if they didn't. You'd still be responsible for your decisions even if you got permission, and your leadership would still be responsible for your decisions if you didn't get permission.

I have a friend who used to work in Google Search on a tool called "Janitor". It was a tool that would garbage collect the results of processing our Web indexing — there's a lot of temporary files created in indexing the Web, and Janitor would go around deleting them when they weren't needed any more. He literally deleted petabytes of data regularly. One day, Larry Page was visiting his team and asked about this project. Larry asked, "how many files have you accidentally deleted?". My friend very proudly answered "I have never deleted a file that should not have been deleted! I have a 100% success record!".

Larry apparently responded "I think you should take more risks".

Some people want LGTMs because they feel that without them they aren't entitled to do their job. But... it's your job. That's why you were hired. You don't need additional permission to do your job. Your biweekly paycheck is all the permission you need.

Some people want LGTMs because they are not confident enough in their idea to execute it. Having leaders on the team put a stamp on their design doc gives them the confidence that the idea was good enough to execute. The thing is though, we won't know if it was a good idea or not until we try it. These stamps aren't saying "it's a good idea", they're saying "it's not an idea so terrible that I can predict its failure already based on my past experience"... and your leaders and team mates will tell you that something is a bad idea if they see it. That's why you ask for review. If they didn't arch their eyebrows and grimace when you explained your idea, then it's probably fine, and you don't need any more permission.

In conclusion: ask for forgiveness, not permission. Get reviews of your design docs, by all means. But don't wait for a stamp of approval to implement them.

2018-06-08 23:00 UTC Indexing into a string

I propose the following aphorism:

Indexing into a string type makes as much sense as indexing into an integer type.

2018-01-04 20:56 UTC Flutter: Negative margins

In Flutter, we occasionally get the question "how do you set a negative margin?". This usually comes after people find the Container widget's "margin" property, try to set it to a negative value, and find that it asserts with a message saying padding must be positive. It turns out that Container's idea of margin and padding is actually just to put a Padding widget on the outside of its DecoratedBox for the margin, and a Padding widget on the inside for the padding. Many complicated-looking widgets in Flutter tends to decompose in this way.

So how would you get a negative-margin-like effect in Flutter?

To answer this question you first have to define what "negative margins", or really "margins" in general, really are. In CSS, margins have various meanings in the various layout models, most commonly, they are one of several values that contribute to computing the offset that the block layout model uses to place subsequent children; a negative total margin in this case merely means the next child is placed above the bottom of the previous child instead of after it.

In Flutter, as in CSS, there are several layout models; however, there is currently no widget that is equivalent to the CSS block layout model (which supports margin collapsing, negative margins, skipping floats, etc). Such a layout model could certainly be implemented, it just hasn't been implemented yet, at least not in the framework itself.

To implement such a layout model, you would create a RenderBox descendant similar to RenderFlex or RenderListBody, probably providing a way to set the margins of each child using a ParentDataWidget in the same way that Flex children can have their `flex` configured using the Expanded widget.

Probably the most complicated part of designing a new layout model like this would be deciding how to handle overflow or underflow, when the children are too big or too small to fit the constraints passed to this new layout render object. The RenderFlex render object has a way to distribute the space if the children underflow, and considers it an error if they overflow (in debug mode, this is shown by a yellow-and-black striped warning area and a message logged to the console); the RenderListBody render object on the other hand takes the view that the constraints must be unbounded in the main axis, which means you can basically only use this layout model inside a list (hence the name).

If writing a new layout model is not attractive, you could use one of the existing layout widgets that allow overlapping children. Stack is the obvious choice, where you set the explicit positions of each child and they can overlap arbitrarily (this is vaguely similar to the CSS absolute position layout model). Another option is the CustomMultiChildLayout widget, which lets you layout and position each child in turn. With this, you could position each child one after the other, simulating negative margins by setting the position of the subsequent child to a value that's derived from the size and position of the previous child, but such that the subsequent child's top is above the previous child's bottom.

If there's interest in a block-like layout model, we could certainly implement it (please file a bug and describe the model you'd like implemented, or, implement it yourself and send a pull request for review). So far, though, we've not found that it has been that useful in practice, at least not useful enough to justify the complexity.

And that's why the answer we usually give to the question of "how do you do negative margins" ends up being a higher-level question in return: what effect are you really trying to achieve?

2017-08-14 22:11 UTC Flutter: So what'd I miss?

Flutter's first big app launched this past Friday, the official Hamilton app!

The app was written by an agency (goposse.com), but we (the Flutter team) helped them in the last few weeks to solve some problems they found with the framework. Mostly the big problem we ran into was around performance of rounded corner clips, but we were able to resolve those issues before launch. We also tracked down some hit testing issues. My favourite bug was with hit testing on tab bars.

We have code to make sure that when you fling a list, if you tap the list while it's scrolling, you don't actually trigger whatever's under the list, instead, you stop the list. This makes sense, because otherwise you have no way to stop the list without triggering random buttons.

Separate from this, we have code to make sure that when you change tabs, we scroll the tab you picked into view over a fixed period (about 300ms if I recall correctly).

Now, what happens when the tab is already in view? Well, we started this 300ms animation that... does nothing. It scrolled by zero pixels over 300ms. And since a scroll was happening, while that was going on you couldn't tap another tab (because the first tap was just stopping the animation). So this meant that if you tapped back and forth between two tabs, it did the first, then dropped the next tap, then did the third, then dropped the fourth, etc! Not a good user experience.

It was tricky to figure out what was going on, because when we looked at the dumps, we could see an animation was happening, but it wasn't immediately obvious that the animation was over zero distance. Luckily we were able to use some of our debug flags to narrow it down.

The fix ended up being really simple (about two lines, plus many dozens of lines of tests): just make sure that if you animateTo() a position you've already reached, do nothing!

Now that we've proved it's possible to ship a big app with flutter, our next step is to fill in the big holes: internationalization (mostly meaning localization and right-to-left support in layout), inline video, improving low-end phone performance, documentation of the animation system, that kind of thing.

Pingbacks: 1

2017-01-06 01:49 UTC Tolerance

This article is the perfect response to those who show intolerance but demand to be themselves accepted into your community.

Tolerance is not a moral precept

Pingbacks: 1