Slide 1

Slide 1 text

In the name of God Crashing is good for your app

Slide 2

Slide 2 text

I am Seyed Jafari Software Engineer @ Revolut Ltd worldsnas.com @worldsnas

Slide 3

Slide 3 text

What is a CRASH 💥 Wiki: In computing, a crash, occurs when a software application stops functioning properly and exits. Me: When a program stops working unexpectedly

Slide 4

Slide 4 text

How do they crash? 🤔 ● Hardware issues ● Galactic rays 🤯 ● Software bugs

Slide 5

Slide 5 text

Software bugs Exceptions

Slide 6

Slide 6 text

Exception Techopedia: An exception is an abnormal or unprecedented event that occurs after the execution of a software program or application. It is a runtime error of an undesired result or event affecting normal program flow.

Slide 7

Slide 7 text

Exceptions for exceptionals! When something terribly goes wrong. It’s unacceptable. No way! Does not meet the rules. Simple Example: var result = 1 / 0

Slide 8

Slide 8 text

Famous exceptions/errors we all know 1. NullPointerException 2. IOException 3. OutOfMemoryError 4. StackOverflowError Kotlin/Native InvalidMutabilityException

Slide 9

Slide 9 text

Exceptions Good Bad or

Slide 10

Slide 10 text

Exception driven vs If-Else Effective Java chapter 10, item 69 Elixir

Slide 11

Slide 11 text

Use Cases and how to deal with them

Slide 12

Slide 12 text

fun getBookNames(libraryId : String): Data> = try { Data.Success(fetchBookNames(libraryId)) }catch(e : IOException) { Data.Failed(e) } NetworkRequests AwesomeRepository.kt Catching example

Slide 13

Slide 13 text

Enum mappings Good Exceptions enum class LightSwitchState{ ON, OFF, UNKNOWN, } fun mapStateToEnum(state : String): LightSwitchState = LightSwitchState .values() .find { it.name == state } ?: UNKNOWN

Slide 14

Slide 14 text

Enum mappings Good Exceptions enum class LightSwitchState{ ON, OFF, } fun mapStateToEnum(state : String): LightSwitchState? = LightSwitchState .values() .find { it.name == state }

Slide 15

Slide 15 text

Enum mappings Good Exceptions enum class LightSwitchState{ ON, OFF, } fun mapStateToEnum(state : String): LightSwitchState = LightSwitchState .values() .first { it.name == state }

Slide 16

Slide 16 text

var binding: FragmentAwesomeBinding? = null ViewBinding vs Fragments AwesomeFragment.kt Good Exceptions fun setTitle(txt : String) { binding?.title.text = txt }

Slide 17

Slide 17 text

var _binding: FragmentAwesomeBinding? = null val binding get() = _binding!! fun onViewCreated(view: View) { _binding = FragmentAwesomeBinding.bind(view) } fun onViewDestroyed(view: View){ _binding = null } fun setTitle(txt : String) { binding.title.text = txt } ViewBinding vs Fragments AwesomeFragment.kt Good Exceptions

Slide 18

Slide 18 text

Good Exceptions var _binding: FragmentAwesomeBinding? = null val binding get() = _binding!! fun onViewCreated(view: View) { _binding = FragmentAwesomeBinding.bind(view) } fun onViewDestroyed(view: View){ _binding = null } fun setTitle(txt : String) { binding.title.text = txt } ViewBinding vs Fragments AwesomeFragment.kt

Slide 19

Slide 19 text

var _binding: FragmentAwesomeBinding? = null val binding get() = _binding!! fun onViewCreated(view: View) { _binding = FragmentAwesomeBinding.bind(view) } fun onViewDestroyed(view: View){ _binding = null } fun setTitle(txt : String) { binding.title.text = txt } ViewBinding vs Fragments AwesomeFragment.kt Good Exceptions

Slide 20

Slide 20 text

Good Exceptions Business logics and specs fun packThreeBooks(books : List): BookPack { require(books.size == 3){ "we need exactly three books to pack" } return packageBooks(books) }

Slide 21

Slide 21 text

Catching exceptions Safe layering the good exceptions fun getBooksAndPackThem(library : Library) : BookPack? { val books = library.getBooks() return try{ packThreeBooks(books) }catch(e: Exception){ null } }

Slide 22

Slide 22 text

Try-catch Let them pass vs

Slide 23

Slide 23 text

BUT

Slide 24

Slide 24 text

Exception vs UX

Slide 25

Slide 25 text

Exception is bad for UX, Let’s Fix it 1. Try-Catch everything 2. Add Safe Layers 3. Set Thread Uncaught Exception handlers We are safe now!

Slide 26

Slide 26 text

Are we really “safe“ now?

Slide 27

Slide 27 text

UX in “Safe” mode fun enablePayBtn() { binding?.payBtn.isEnabled = true } Users: Still not fixed

Slide 28

Slide 28 text

Let it crash fun enablePayBtn() { binding.payBtn.isEnabled = true } Users: Fixed immediately

Slide 29

Slide 29 text

Still not convinced? 😲 Another example...

Slide 30

Slide 30 text

I hear you, skepticals! Logging

Slide 31

Slide 31 text

Exception Logging vs

Slide 32

Slide 32 text

I/Fitness: OnPackageChangedOperation got intent: Intent... I/Icing: Indexing com.google.android.gms-apps from com.google.android.gms [CONTEXT service_id=21 ] I/Icing: Indexing done com.google.android.gms-apps [CONTEXT service_id=21 ] I/Telecom: DefaultDialerCache: Refreshing default dialer for user 0: now com.android.dialer: DDC.oR@AI8 I/system_server: Background young concurrent copying GC freed 80900(4601KB) AllocSpace objects, 11(1124KB) LOS objects, 11% free, 31MB/35MB, paused 458us total 142.940ms I/CarrierSvcBindHelper: No carrier app for: 0 I/Fitness: FitCleanupIntentOperation received Intent android.intent.action.PACKAGE_CHANGED I/Fitness: OnPackageChangedOperation got intent: Intent... I/Icing: Indexing com.google.android.gms-apps from com.google.android.gms [CONTEXT service_id=21 ] I/Icing: Indexing done com.google.android.gms-apps [CONTEXT service_id=21 ] I/Fitness: FitCleanupIntentOperation received Intent android.intent.action.PACKAGE_CHANGED Logging issues Dear Logcat indistinct

Slide 33

Slide 33 text

I/Fitness: OnPackageChangedOperation got intent: Intent... I/Icing: Indexing com.google.android.gms-apps from com.google.android.gms [CONTEXT service_id=21 ] I/Icing: Indexing done com.google.android.gms-apps [CONTEXT service_id=21 ] I/Telecom: DefaultDialerCache: Refreshing default dialer for user 0: now com.android.dialer: DDC.oR@AI8 I/system_server: Background young concurrent copying GC freed 80900(4601KB) AllocSpace objects, 11(1124KB) LOS objects, 11% free, 31MB/35MB, paused 458us total 142.940ms I/CarrierSvcBindHelper: No carrier app for: 0 I/Fitness: FitCleanupIntentOperation received Intent android.intent.action.PACKAGE_CHANGED I/Fitness: OnPackageChangedOperation got intent: Intent... I/Icing: Indexing com.google.android.gms-apps from com.google.android.gms [CONTEXT service_id=21 ] I/Icing: Indexing done com.google.android.gms-apps [CONTEXT service_id=21 ] I/Fitness: FitCleanupIntentOperation received Intent android.intent.action.PACKAGE_CHANGED Logging issues Dear Logcat indistinct

Slide 34

Slide 34 text

java.lang.OutOfMemoryError at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:683) at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:513) at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:889) at android.content.res.Resources.loadDrawable(Resources.java:3436) at android.content.res.Resources.getDrawable(Resources.java:1909) at android.view.View.setBackgroundResource(View.java:16251) at com.autkusoytas.bilbakalim.SoruEkrani.cevapSecimi(SoruEkrani.java:666) at com.autkusoytas.bilbakalim.SoruEkrani$9$1.run(SoruEkrani.java:862) at android.os.Handler.handleCallback(Handler.java:733) ….. Exceptions advantage Dear Logcat Easily distinguishable

Slide 35

Slide 35 text

● V: Verbose. ● D: Debug. ● I: Info. ● W: Warning. ● E: Error. ● A: Assert. Logging issues Android SDK Hard to choose

Slide 36

Slide 36 text

Exceptions advantage Java std throwables Clear types ● java.lang.NullPointerException ● java.io.IOException ● java.lang.IllegalStateException ● java.lang.IllegalArgumentException ● java.lang.OutOfMemoryError ● java.lang.StackOverflowError

Slide 37

Slide 37 text

tag= MainActivity::class.simpleName, msg= "some f… thing went wrong", tr= null Logging issues Logcat.d Manual INFO gathering ) Log.d(

Slide 38

Slide 38 text

Exceptions advantage IllegalArgumentException() Automatic Info attaching ● No tags needed ● StackTrace ● Name is a good enough message

Slide 39

Slide 39 text

● Checking logs regularly (usually ignored) ● Finding the right one (find a needle in a haystack) ● Setting severity level ● Assigning to the right team ● Velocity Alerts Logging issues Slow & Hard Addersing

Slide 40

Slide 40 text

Exceptions advantage Fast & Easy Addersing ● They are highly prioritised (fixed even during weekends! 󰣻) ● Usually delivered to devs inbox ● They can be assigned automatically ● Types can be used as Severity ● Alerts already set (Crashlytics)

Slide 41

Slide 41 text

● Firebase Events Logging issues Custom vs Paid options Reporting tool

Slide 42

Slide 42 text

Exceptions advantage Exception reporting services Most of the services are free ● Crashlytics ● Sentry ● Yandex ● Bugsnag

Slide 43

Slide 43 text

Logs Are good and useful Not a replacement for Exceptions

Slide 44

Slide 44 text

Exceptions Good Bad or It depends

Slide 45

Slide 45 text

💥 Happy Crashing 💥 @worldsnas Reach out to me about your crashes 🤗 Thanks We are actively hiring in wide range of positions. make sure to checkout our openings on: https://www.revolut.com/careers