I feel weird writing about React. I’m not a contributor or upstanding community member. I’m not even an early adopter – we only started working React into Crashlytics about six months ago.

I’m a fan, though. A huge fan. And even though I thought I was the last person to this party, I keep running into frontend developer pals who haven’t given React a try.

Let’s change that!

The models who couldn’t save themselves

My React fervor was sparked by a bug I wrote. I work on Beta by Crashlytics, and much of our web frontend is written in Backbone. Late last summer, our dialog for managing groups of testers regressed: every so often, it would stop working. Any attempt to edit the group’s name, or add or remove testers, would be met with the same error in the JavaScript console: A “url” property or function must be specified.

How could this be? I had a Group model object, a whole collection of them in fact. You can see them right there in the sidebar. They each had their IDs, and their collection was very clear about how to turn those IDs into URLs. And yet, somehow “save” was broken. Why wasn’t it making its URL?

Let’s be clear, this is my bug. And –  full disclosure  –  I wrote it when converting some other parts of the UI to React. I was finding the Backbone Collection’s “set” method to be too chatty announcing change events, so, for the code that updated our global Group collection in response to a periodic server poll, I changed over to “reset” instead. It even seemed more correct, in my mind: make the groups list exactly like the latest state from the server.

Unfortunately, “reset” works by first emptying the collection of its existing models, then re-populating it. That emptying carries the consequence that those previous occupants — such as the Group object that the editing UI had a reference to — would be orphaned, no longer a member of anything. No parent collection meant no “url” method, and that meant no way to save.

I felt a bit stupid for having caused such a regression, but that was eclipsed by my frustration that such a bug was even possible. Model objects that are capable of saving themselves had already been a pet peeve of mine due to how they hindered testability, but now I found model objects that could arbitrarily lose their ability to save themselves in the middle of my program!

This was a mutation bug on steroids: an object’s functionality changing not even due to local state modifications, but by whether or not another object was holding a reference to it. How could I reason about behavior if this possibility was lurking in my code? What automated test would have even exercised this?

I was determined. I was vengeful. It was now time to, as they say, React all the things.

The DOM Doctors

Doubling down on a new UI rendering library might seem a strange way to solve a model logic problem, but React has the remarkable power to send ripples of correctness through your codebase. Consciously or not, libraries like Backbone end up encoding assumptions about how views work in their data classes. If we fundamentally changed how rendering happens, why wouldn’t that affect how we managed data?

If you’ve heard anything about React, it’s probably that it has a “virtual DOM” that makes its HTML fast using an efficient tree diff algorithm. If you’re like me, the first time you heard that you may have dismissed it. My HTML isn’t slow.

And maybe it’s not that slow, but only because we frontend developers learned not to push it. We joined together our template strings for one big innerHTML splat at the outset and then just modified individual elements going forward. We couldn’t conceive of being so callous as to re-render an entire dialog just because a group’s name changed. We were good programmers, we were precise. We were surgeons, jQuery was our scalpel, and when the “name changed” event came in we made only the tiniest incision in the page to bring it up-to-date.

There’s another reason for why we stepped lightly in the tree: DOM elements are stateful beyond how we created them. They have focus, or scroll positions, or in-progress edits. Some cavalier re-rendering wouldn’t just be slow, it would stomp user data at the same time. And that, at least, was unacceptable.

These constraints had a profound effect on our code. We couldn’t just write the state of what our UI should look like (“the button is disabled because a network request is in progress”). Instead, we were condemned to write the state transitions between those UIs. On network request start? Add class “disabled.” On complete? Remove class “disabled.” If we were lucky, we found all the ways that state tended to linger on our pages. On showing a form? Remove any error messages from the last time we showed this form.

Testing this style of code is both painful and approximate. On top of exercising your initial rendering, you need to test your transitions. They need plausible prior states just to run, but to have good coverage you need to test them against each important variation of prior state that your application is capable of getting itself into. A “finite” state machine perhaps, but only in theory.

Spared from Change

Enter React. The real benefit of that O(n) tree-diffing algorithm isn’t performance per se. It’s that it frees us from having to hand-write every state transition in our UI. Besides reducing drudgery, that actually eliminates the entire class of leaky-state bugs mentioned above. If you declare that your UI is a dialog with an active button and no error message, React will transition to exactly that, performing DOM manipulations that ensure that your button is active and no error message is seen. Any vestiges of previous state are cleansed with no extra effort on your part.

Fundamentally, your old state transition code was a function over your application data, but also over the previous state of the UI. That’s why you needed to consider varied “prior states” when testing. In contrast, your React rendering code is a function over just the application data. You can imagine how much more pleasant that makes your tests.

The real answer to how “just” a view library can affect your data handling is that React is a view library because that’s all that it needs to be. When I talked about the Backbone data classes having assumptions about the way you displayed your UI, I was thinking of mutation handling and attribute-level change events. If you’re writing minimal state transitions, that kind of information is important for doing precise DOM surgery. If you’re writing a React component, though, where declaring UI state is cheap and getting to it is fast, the only notification you really need is “something has changed, probably.”

Since all you need are coarse-grained change notifications, your data objects can be correspondingly simpler. One could argue that React even works best on just plain hashes and arrays. All you need is for a data source to hand your component hierarchy the latest values, and everything flows efficiently from there. No mutation-tracking, self-saving, collection-inhabiting model objects necessary.

Efficient coarse updating also enables what may be my favorite part of React: props and state.

In a correctly-written React component, the only inputs to the UI rendering method are its “props” and its “state.” These are exposed as a pair of hashes on the component object, and changes to either of them cause the component to re-render. (Something has changed, probably.)

The difference between the two is how they change. “props” can be thought of as the input from the outside world. It’s set from the parameters your component is called with, and its values should be treated as immutable. “State,” on the other hand, is the data that’s owned by your component. You update it via the “setState” method, and no one else should be changing it on you.

To give a concrete example, consider a component for editing a group. The props would include the group’s name, while the state might be whether it’s showing a “delete” link or the “confirm” / “cancel” buttons that appear instead when that link is clicked.

This may seem like just a helpful little pattern, but by calling out this distinction between props and state, React has bestowed an enormous understandability boon on your code. Gone is the catch-all “options” hash that contains everything, internal and external. Your data is going to naturally fall into one hash or the other, so there’s one fewer choice to make when structuring your component, and, more importantly, one more signal of your intent when your team comes back to your code months later to extend it.

In practice, the state of one component actually ends up trickling into its child components as props, and establishing your intention is even more valuable. When the same data is “state” here and “props” there it’s perfectly clear what level of your component hierarchy is responsible for coordinating its changes.

Finally, when you consider testability, you can, in almost every case, proceed in ignorance of changes to your component’s props. So, while you and I both know that group names can change, all the component that renders the list of groups in the sidebar needs to do is render the names it’s given. If they change, it’ll be given new names, and it’ll render them just the same. No need to waste time in your tests verifying that case.

Path to salvation

React is fascinating because it takes this rather clever little algorithm for fast tree diffing and follows it to its logical extreme, introducing an incredibly effective paradigm to web developers: If we can diff in O(n) time we can quickly convert one DOM tree to another. That means it’s efficient even if the difference is small. It also means we can keep that partially-filled <input> around. That means we can do coarse-grained updates for any change. That means that re-rendering can be triggered automatically by the framework. That means we can have a simple, standard pattern for state management. And so on.

As a library, React doesn’t really let you build anything that you couldn’t do before with any other UI framework. Maybe some things will be more performant out-of-the-box, but functionality-wise your product will be very much the same. What React gives you instead is much less, better code, sooner. Declarative UIs are faster to write, simpler to test, and far far far easier to reason about.

It feels like nothing short of giving you frontend engineering superpowers.

Hopefully this has whet your appetite for React. Maybe it will be as revelatory for you as it has been for me. Soon, I’ll follow this post up with some more specifics about how we’re using React on Crashlytics, why you don’t need JSX, and our take on a unidirectional data flow pattern :)

We’re helping our customers build the best apps in the world. Want to be a part of the Crashlytics team and build awesome stuff? Ping us @ jointheflock@twitter.com. We look forward to chatting with you!

(Big thanks to Kevin Robinson, Sam Neubardt and Sam Phillips for contributing to this post.)


View More

 

Crashlytics_February_2015_Update

Roses are red, violets are blue..and we are thrilled to ship new upgrades to you! Last month, we launched two brand new integrations with GitLab and OpsGenie to help you stay on top of crashes and collaborate with your team to fix the most critical issues. In February, despite having Valentine’s day, the Super Bowl and the endless New England blizzards, we still worked around the clock to bring you even more feature enhancements and new functionality :)

Finally, Dark Mode Support

For those of you building on Yosemite, we recognized that some of you have customized your desktop’s look and feel with its new “dark mode“. This month we’ve solved the hardest computer science problem yet: Crashlytics now supports Yosemite dark mode! Your Mac App now automatically detects the mode and displays the Crashlytics icon in its light or dark version accordingly, ensuring that the icon is always visible within the OS X toolbar. All jokes aside, we’ve actually been heads down building lots of other great stuff in the past few months which you’ll be seeing in the near future — so stay tuned!

A More Robust Foundation

We’ve been fortunate to power many of the world’s top apps and be trusted by thousands of companies since building Crashlytics three years ago. Like all services of this scale, we’ve accumulated some technical debt, so we spent this month performing some massive internal refactoring on our infrastructure. We started by segmenting large classes into smaller parts and re-organizing our code to make writing unit tests easier. We also brought up a new cluster, implemented sampling and migrated data from old cluster to scale our session service. Now, we can deploy feature enhancements and bug fixes for you faster and safer than ever before, while laying the foundation for more stability and better performance in the future.

Latest Toys from Crashlytics Labs

Many of you who are building awesome apps with the NDK on Android have requested support from Crashlytics. Since opening access to our beta program in October, our Labs team has continued building this out and enhancing its functionalities every day. We’re now working with top companies who have already shipped their apps with our beta — so if you haven’t test out our NDK beta yet, request early access here :)

Here’s our internal changelog:

Crash Reporting

  • iOS SDK
    • Improved crash reporting latency when devices have no network access.
    • Fixed an issue with NSUserDefaults access while an app is in the background.
  • Mac App
    • Implemented icon support for Yosemite in dark mode.
  • Infrastructure
    • Performed large scale internal refactoring.
    • Segmented large classes into smaller parts.
    • Re-organized code structure to make writing unit tests easier.
    • Enabled enhancements and bug fixes to be deployed faster and safer for customers in the future.
  • Web
    • Fixed minor bug for Crashlytics and Fabric related accounts.

Beta Distribution

  • Build Tools
    • Fixed minor bugs within Gradle integration to make distribution uploading more robust with flavor dimensions.

View More

 

It was exactly two years ago that we joined forces with Twitter. Since the acquisition, not only have we continued to make Crashlytics even more powerful, we also released several major products in 2014 — Beta by Crashlytics, Answers, and most recently, Fabric. What an incredible journey it has been!

In December, we were busy crafting a dozen new gifts for you just before the holidays: more upgrades for Beta by Crashlytics, new app installs tracking with Answers, and more. Even though we were stuffed from all the holiday feasts, we are kicking off the new year strong with two new integrations and a ton of feature enhancements :)

Brand New Integrations

Just two months ago, we launched our integrations with Slack and FogBugz to help you strengthen team collaboration and manage your projects. Now, we’re excited to unveil two more integrations: GitLab and OpsGenie.

We understand the importance of staying on top of crashes and collaborating with your team to fix the most critical issues as they occur. Based on overwhelming demand from many of you, Jeremy Durham built the Crashlytics integration with GitLab. With this integration, crashes are automatically delivered to your issues management dashboard on GitLab so you can track all issues and bug fixes in one central place. On the other hand, our OpsGenie integration, built by Halit Okumuş, automatically alerts you if an issue changes status or a new issue occurs. Now, you can sit back and focus on the fun stuff, like coding the next coolest app!

Digits: Login for Web

For those of you building mobile-first services, the best signup experience is likely to be through the native app. But you may also want your users to continue to engage with your apps on the web. This month, we launched Digits login for web which allows you to implement a simple and secure login on your app’s website with just a few lines of code. To help you preserve the mobile-first experience of your service, your users still sign up first through your mobile app, as they normally would, before they can log in to your site. But now, not only can Digits help you drive more downloads for your app, it also enables you to bring your mobile service onto the web — giving you a consistent identity experience across platforms.

Here’s our internal changelog:

Fabric Platform

  • Android Studio
    • Tweaked the plugin so it does not appear on top of other application windows.
    • Added support for multiple monitors.
  • IntelliJ
    • Tweaked the plugin so it does not appear on top of other application windows.
    • Added support for multiple monitors.
  • Eclipse
    • Improved kit refreshing functionality by adding ‘Refresh Kits’ option from ‘kits.properties’.
    • Enhanced support for multiple monitors.

Crashlytics Kit

  • Crashlytics
    • Integrated crash reporting functionality with GitLab issues management.
    • Integrated crash reporting functionality with OpsGenie issues alert service.

Twitter Kit

  • Digits
    • Web
      • Launched Login for Web functionality to make it easy for mobile-first-apps to to use phone number identity across the web.
    • Android
      • Removed Twitter login from fallback screen.
      • Fixed Resources$NotFoundException on Gingerbread devices.
      • Fixed theme detection when building with Eclipse.
      • Fixed functionality to update old guest authentication token.
      • Improved handling of different target SDKs.
  • TwitterCore
    • Android
      • Added logInGuest method to enable guest access to statuses endpoints user_timeline, show, and lookup, search/tweets, and favorites/list.

View More

 

Just like the best holiday cards are written from the heart, every line of code we’ve written since the birth of Crashlytics came from our passion of building tools that developers love. In November, we were heads down coding up new 3rd party integrations, a more powerful Swift Support and an upgraded Beta by Crashlytics — all while continuing to build out our NDK support at Crashlytics Labs. This month, we’ve been busy crafting a dozen new gifts for you: more upgrades for Beta by Crashlytics, new app installs tracking with Answers, and more. We’re excited to share these gifts with you before the year draws to a close!

Beta by Crashlytics: Share Your Builds Anywhere

Many of you have requested the ability to share your builds through other channels beyond email. Now, with share links for Beta, you can create direct links to specific builds while having complete control over who can access those builds — whether it’s external press or internal employees for dogfooding. To help you fix crashes even faster, we now identify the exact tester who experienced the particular issue right within your crash report — so you can contact that tester and gather feedback immediately.

Answers: Free App Installs Tracking

Running marketing campaigns to grow and monetize your apps can be difficult, especially when it’s expensive to measure installs. Together with teams at Twitter, we’ve integrated Answers with Twitter’s advertising platform to make tracking installs incredibly simple. Now, within seconds, you can have total visibility into the installs driven by your paid and organic campaigns on Twitter — completely free, with no additional code! Also, our solution is now self-serves so you can easily manage your campaigns. Learn more about app installs tracking with Answers here.

Digits: Now Themed to Your App

Your app’s sign-in experience is crucial to growing and retaining your user base. When Digits was first released back in October, you could already launch the Digits sign-in flow from any button anywhere within your app. This month, the Digits team launched theming support to help you further optimize your onboarding experience on both iOS and Android. With the new support, you can match Digits exactly to your app’s ambience so your Digits sign-in flow looks indistinguishable from your app. Theming requires just a few lines of code, and Digits will do the rest!

Here’s our internal changelog:

Fabric Platform

  • iOS SDK
    • Fixed minor bug that occurred for users with multiple accounts.
  • Android SDK
    • Shipped multiple bugfixes.
    • Updated Android tests to make them compatible with Level 21.
    • Updated SDK version from 7 to 8.
    • Fixed kit initialization error that affected a small amount of developers.
  • Mac App
    • Released updated Kits and enabled update by customers through the app.
  • Android Studio Plugin
    • Released updated Kits and enabled update by customers through the plugin.
  • IntelliJ Plugin
    • Released updated Kits and enabled update by customers through the plugin.
  • Eclipse Plugin
    • Released updated Kits and enabled update by customers through the plugin.

Crashlytics Kit

  • Crashlytics
    • Web
      • Shipped crash-to-tester feature to identify the tester who experienced a specific crash.
      • Implemented auto-tagging of all crashes of beta builds with testers’ names and email addresses.
  • Beta by Crashlytics
    • iOS SDK
      • Shipped upgrades to allow for future Beta and Answers integrations.
    • Android SDK
      • Shipped upgrades to allow for future Beta and Answers integrations.
    • Web
      • Increased tester limit on groups to 500.
      • Implemented share links for sending specific builds.
      • Shipped domain restriction functionality for share links.
      • Deployed dashboards for managing share links and tester access.
      • Shipped functionality to automatically point internal share links to the latest build.
      • Implemented auto-tagging of all crashes of beta builds with testers’ names and email addresses.
  • Answers
    • iOS SDK
      • Implemented functionality to enable Twitter conversion tracking.
      • Shipped upgrades to allow for future Beta and Answers integrations.
    • Android SDK
      • Implemented functionality to enable Twitter conversion tracking.
      • Shipped upgrades to allow for future Beta and Answers integrations.
    • Web
      • Shipped ability for customers to select Answers on ads.twitter.com and analytics.twitter.com UI.
      • Implemented functionality to enable app install tracking via self-service.

Twitter Kit

  • Base
    • Improved proguard configuration by bundling Consumer Proguard Config file with AAR.
  • Digits
    • iOS
      • Shipped custom theming support.
    • Android
      • Shipped custom theming support.
  • Twitter Sign In
    • Improved stability of Twitter login on devices that do not have the Twitter for Android App.
    • Ensured Login with Twitter and Share Tweet button text doesn’t show in all caps on API 21.

MoPub Kit

  • iOS
    • Shipped MRAID 2.0 support.
    • Shipped specification to enable rich media ads in banners and interstitial ad units.
    • Shipped automatic geolocation updates for apps that already have location permissions.
    • Implemented functionality to automatically attempt to acquire location data for ad requests (permission-based).
    • Added support for AdColony SDK 2.4.12.
  • Android
    • Shipped MRAID 2.0 support.
    • Shipped specification to enable rich media ads in banners and interstitial ad units.
    • Shipped geolocation polling updates.
    • Updated the ChartboostInterstitial custom event to support Chartboost SDK 5.0.4.

This year has been full of fun and excitement and we can’t wait to continue to celebrate with you into next year. Happy holidays from our Crashlytics family to yours :-)


View More

 

beta-share-links-header-v2

It’s been just seven months since we launched Beta by Crashlytics. We’ve been thrilled by the response from developers looking for a seamless way to distribute beta builds of their apps to testers. In August, we released groups support, the first of many product additions, and in October, we re-released Beta as part of Fabric. Today, we’re excited to share the next evolution of Beta.

We heard you loud and clear that you need an even lighter-weight way of sending out builds – without email – and be able to control who gets access. Another challenge: how to efficiently get detailed, actionable feedback from testers about your crashes. Now we think we’ve got you covered with share links, the most convenient way to onboard testers to your builds, and crash-to-tester Identification, which combines the power of Crashlytics and Beta to help you quickly get to the bottom of your builds’ crashes.

Total Flexibility for Onboarding Testers

Many of you want to share your builds through channels beyond email. Now, with share links, you can seamlessly create onboarding links for each build and invite testers through any medium you choose – without needing to know their email addresses. Whichever channel you prefer, you have the flexibility to tailor your message to testers.

 beta-share-link-v2

Within your share link dashboard, you can manage all your links in one place — with complete control over who can access your builds. Share a public link with the press or your investors, or create a private link for internal dogfooding by setting domain restrictions. We also automatically point your internal links to the latest build so your testers can always access the latest from one reliable place.

No need to worry about manually adding new testers either! With share links, you can automatically assign new testers to a group when they sign up via your link. This ensures that everyone will receive your updates in the future, as soon as you send them out. On top of that, you can now create specific groups ahead of time based on where you plan to post your links. Organizing testers have never been easier.

Deep, Actionable Testers Feedback

One of the most powerful features of Beta is its deep integration with Crashlytics’ crash reporting, which empowers you to fix the most critical issues with the least effort before your app goes into the wild. With our new crash-to-tester functionality, you can instantly identify the individual tester who experienced a specific crash right within your crash reports.

crash-to-tester-v3

We automatically tag all crashes of your beta builds with your testers’ names and email addresses. Now, you can immediately contact your testers for feedback and even work with them to reproduce an issue. Coupled with your crash reports and custom meta data, you’ll be able to trace the exact steps and situation your testers were in when they encountered the issue.

From our friends at Lyft:

Using the direct share links has made distribution simple and easy. I can now use one link to ensure our testers always have the latest builds by sharing the link across multiple channels, including email, SMS, and social. In addition, the crash-to-tester feature has reduced time spent investigating issues by connecting users to specific crashes, tracing their actions leading up to them, and including relevant contact information for easy follow-up.

Will Farino,

Let us know what you think. Our roadmap is full of exciting features which we’ll continue to roll out in the coming months. Stay tuned!

try-beta-share-links-crash

 


View More