Adding `git log -S` to your code detective toolbox Programming often involves detective work. Properly fixing a problem often requires understanding how the problem came to be in the first place. One of the best tools for code detectives is git blame. With it, you can trace the lineage of every line of code in your codebase. Armed with
kotlin When to use Kotlin's standard functions Kotlin comes with several high-level, generic standard functions that apply to any object: let(), run(), with(), apply(), and also(). If you're new to Kotlin you may be wondering when to use them. They're fairly inscrutable; the source [https://github.com/JetBrains/kotlin/blob/master/libraries/
annual review Year in Review (2018) It's time for my annual review. This record is more for me than it is for you, but hey, if you want a one-stop shop for Dan's activities in 2018, this is it! My baby was born in March, which somewhat reduced my level of
android The Reality of Migrating to AndroidX This year, Google rebranded the support Android libraries to Android Jetpack (aka AndroidX) [https://developer.android.com/jetpack/]. Particularly pertinent to developers was how they repackaged all the libraries. Not only have their maven coordinates changed [https://developer.android.com/jetpack/androidx/migrate#artifact_mappings], but the package names for
politics Edina City Council Election (2018) Last year I moved from Minneapolis to a neighboring suburb, Edina. One of the downsides of moving was that I would no longer get local political coverage from the amazing Naomi Kritzer [https://naomikritzer.com/], who each year writes up detailed reports on twin cities-area elections. While I can
rxjava ConnectableObservable: So Hot Right Now ConnectableObservable [http://reactivex.io/RxJava/javadoc/io/reactivex/observables/ConnectableObservable.html] does not care when you subscribe to it; instead, it only begins its work when connect() is called. With that in mind, what is the output of the following? val connectableObservable = Observable.just("Hello!").publish() connectableObservable .subscribeOn(
android Exploring Spannable Performance I've been working on a new markdown handler for Trello Android. It uses commonmark-java [https://github.com/atlassian/commonmark-java] to parse an abstract syntax tree [https://en.wikipedia.org/wiki/Abstract_syntax_tree], which is then converted into a single, complex Spannable. That Spannable is constructed
remote Hear Me Talkin' To Ya: Thoughts on Remote Communication Trello is a remote-friendly company, with over 60% of the company remote. Atlassian, which acquired us last year, is mostly colocated. As I've spent more time with Atlassians from other parts of the company, I've often been asked the same question: how do Trellists manage
android How to Screw Over Your Beta Users Without Really Trying An addendum to this week's post about releasing buggy apps [https://blog.danlew.net/2018/03/13/how-to-release-a-buggy-app-and-live-to-tell-the-tale/] : a story of how everything can go wrong. Trello Android [https://play.google.com/store/apps/details?id=com.
android How to Release a Buggy App (And Live to Tell the Tale) Bugs! No matter how many times I decree that my coworkers and I must stop writing bugs, we keep on doing it anyways. Even worse, sometimes those bugs make it into production, where users run into them! The fact of the matter is, you are going to someday release a
rxjava When you don't need a map Here's a sketch of how one could listen to connectivity changes on Android via an Observable of NetworkInfo [https://developer.android.com/reference/android/net/NetworkInfo.html]: val networkInfo: Observable<NetworkInfo> = ... networkInfo .map { it.isConnected } .subscribe { onConnectivityChange(it) } While it works as expected, I would argue
android Notifications in Android 8.1 Last time I wrote about notification channels [https://blog.danlew.net/2017/09/06/working-with-android-notification-channels/] I described a complicated solution to create the best balance between automatic bundling vs. not annoying the daylights out of the user: > * Have as few channels as possible make noise
android Year in Review (2017) ICYMI (or more likely, in case I want a reference), here's all the public stuff I've done in the past year. This year, I purposefully avoided traveling to speak at conferences. Writing talks, traveling, and attending conferences takes up a huge chunk of time and I
android Working With Android Notification Channels Google has introduced notification channels [https://developer.android.com/preview/features/notification-channels.html] to Android Oreo. Each notification is now associated with a channel, and the user is granted control over how each channel presents notifications. For developers, channels are a double-edged sword. On the one hand, it
rxjava Why Not RxLifecycle? Hello. This is Dan Lew. You may or may not know me as the author of RxLifecycle [https://github.com/trello/RxLifecycle/tree/2.x]. Here’s why I’ve started pulling back from using my creation. Origins When Trello first started using RxJava [https://github.com/ReactiveX/RxJava], we
talk An Introduction to Functional Reactive Programming I gave a talk this year about functional reactive programming (FRP) that attempted to break down what gives FRP its name and why you should care. Here's a write-up of that talk. -------------------------------------------------------------------------------- Introduction Functional reactive programming has been all the rage in the past few years. But
kotlin Convincing the Kotlin compiler that code is safe One of the best features of Kotlin is its built-in null safety in the type system. Try to use a nullable type in a non-null way and the compiler will yell at you. This null safety can occasionally create some tricky situations, though. Code that you know is
kotlin Musings on Kotlin Ranges Here are a few interesting aspects of Kotlin ranges [https://kotlinlang.org/docs/reference/ranges.html], some of which I've found to be less-than-intuitive. Ranging on Empty Pop quiz: What does the following code output? (1..3).forEach(System.out::print) (3..1).forEach(System.out:
kotlin Mutable vals in Kotlin When I first learned Kotlin, the difference between val and var seemed simple: val means immutable and var means mutable. The truth is more nuanced than that: val does not mean immutable, val means read-only. That means that you're not allowed to explicitly write to a val,
kotlin Why Kotlin? I want to explain why I prefer Kotlin over Java. In short, the many myriad Kotlin features enable more concise and understandable code than Java without sacrificing performance or safety. Kotlin compiles to bytecode, so it can perform just as well as Java. It's got the same compile-
android Proper Parcelable testing Check out this Parcelable [https://developer.android.com/reference/android/os/Parcelable.html] I've just written: public class Thing implements Parcelable { public static final Parcelable.Creator<Thing> CREATOR = new Parcelable.Creator<Thing>() { public Thing createFromParcel(Parcel in) { throw new RuntimeException("Oops"); } // ...skipping
android Displaying Sync State This article is part 7 of a series (1, 2, 3, 4, 5, 6, 7) Early on, we realized that we needed some way to communicate to the user when data isn’t synced with the server yet. Otherwise, you could end up in a frustrating situation where you see
android Sync is a Two-Way Street This article is part 6 of a series (1, 2, 3, 4, 5, 6, 7) Most of what I’ve written so far has been about uploading changes from the client to the server. But we found it is equally important to download changes from the server periodically, too. What
android Kotlin Puzzler: Whose Line Is It Anyways? Here's a small Kotlin puzzler. What's wrong with the following code (when used on Android)? val map = mapOf("hello" to "goodbye") map.forEach { t, u -> Log.i("tag", t + u) } I'll give you a hint: on older
android Offline Attachments This article is part 5 of a series (1, 2, 3, 4, 5, 6, 7) When writing offline mode, attachments proved to be a uniquely difficult aspect of syncing. The nature of attachments differ from other data in Trello. Most data in Trello are simple numbers and strings. Files are