Why you shouldn’t refactor your code blindly | by Akash Khunt | Sep, 2022 | Operator Tech

about Why you shouldn’t refactor your code blindly | by Akash Khunt | Sep, 2022 will cowl the newest and most present info as regards the world. acquire entry to slowly in view of that you simply perceive capably and accurately. will deposit your information skillfully and reliably

DALL E generated picture (cyberpunk artwork of blindfolded monkey with laptop)

I’ve a protracted historical past of refactoring code every time I see the yellow marks on the fitting hand facet of the code editor window in Android Studio. The perfect half about having a wise IDE is that along with displaying the issue, it additionally suggests an answer that may be instantly utilized (wherever potential). As within the following screenshot, you may see Take away redundant ‘public’ modifier possibility to use the correction.

Android Studio (must be the identical for intelligence IDE) displaying and suggesting a repair for the warning

I’ve used this perform fairly steadily to do some minor refactoring for a few years now, however lately when doing one thing related, I ended up taking pictures myself within the foot 😅.

The code refactor

Let’s begin with some background first. As you may see within the following code, we’ve got a watcher listing which we’ll use to inform the lessons that implement it.

Redacted code for Observer loop blocking

And the watcher listing was being utilized by one other class like one thing under:

Wanting on the code we are able to see that it is rather easy the place we’re creating a variety and iterating by way of it and calling the onStatusChange() perform. After I was including some performance to the identical class, Android Studio confirmed me that this may be refactored to one thing like under:

Android Studio suggests an answer for a extra optimized for loop

The steered refactor additionally is sensible because it makes use of the till operator we’re basically allocating some reminiscence for the index (i.e. Yo) which isn’t required along with accessing the factor. So I utilized the steered change and the code was modified as proven under:

After Observer loop lock

The crash

The whole lot was tremendous till the refactor of the previous code was launched within the launch construct. However after a couple of days of launch after I opened Crashlytics to see if any new accidents are reported and I used to be shocked. I noticed a java.util.ConcurrentModificationException the crash was reported in the identical location the place I refactored the loop code earlier 😕.

ConcurrentModificationExceptionConcurrentModificationExceptionConcurrentModificationException Exception

I examined the 2 code variants by inserting them facet by facet, and at first look, they appeared related, since in each circumstances we used Kotlin code. in (i.e. iterator operator) 🤔. Then, since everyone knows that the Kotlin compiler is sensible and infers the thing kind, I assumed I would examine the iterator kind used for in each circumstances.

the rca

Within the first case the place in was used with Interval, IntProgressionIteratorIntProgressionIterator it will get used to doing the iteration. If we examine the code IntProgressionIteratorIntProgressionIterator we are able to see that there isn’t a logic to tug ConcurrentModificationExceptionConcurrentModificationExceptionConcurrentModificationException. This is sensible as as soon as the vary is created there isn’t a strategy to modify it.

in interactor operator solves IntProgression.iterator() (i.e. IntProgressionIterator) by intervals
IntProgressionIteratorIntProgressionIterator supply code

Now let us take a look at the second case the place in is used with a Prepared. On this case we find yourself utilizing the iterator.

in interactor operator solves listing.iterator() by Listing/ArrayList
ListIterator code with ConcurrentModificationException thrown on line 860

As we all know in our case observers listing was a MutableList (which is backed by an ArrayList internally) I opened the ArrayList. Additionally trying on the Crashlytics stacktrace proven above, we are able to see that the lock is triggered on ArrayList.java:860. So I navigated on to that line and noticed that ConcurrentModificationException was thrown in case modCount != anticipated modnumber, which may occur in case your mutable listing is modified by another thread when iterating. And looking out on the precise code in my code base I noticed that it very nicely may occur 😅.

Correction and hindsight

The answer was fairly simple. We simply wanted to make use of some synchronization mechanism to verify the listing wasn’t modified by one other thread when it was iterating.

The attention-grabbing side was that it was not flagged earlier on account of a mix of the next issues:

  1. Interval ending with begin = 0 Y final = watchers.dimension earlier than the loop executes.
  2. There have been no occasions of deletions/removals of the observers listing like this the opposite notorious NoSuchElementException the exception doesn’t happen both.

In circumstances the place I repair not-so-common bugs in my Kotlin code, I attempt to confirm the conduct by trying on the decompiled bytecode. For this, I take advantage of Android Studio’s built-in device which may be invoked by Instruments > Kotlin > Present Kotlin Bytecode. Then click on on the decompile button current on the prime left of the open window.

decompiled byte code for ListIterator

For the above case of ListIterator Bytecode decompiled, the whole lot appears tremendous based mostly on our understanding that we bought earlier.

decompiled byte code for IntProgressionIteratorIntProgressionIterator

However for the case of IntProgressionIteratorIntProgressionIterator we are able to see that it’s not getting used in any respect and the by loop with Interval transformed to easy for loop 😲. Nevertheless, the conduct that we’d have obtained by utilizing IntProgressionIterator doesn’t appear to have modified.

I hope the article practically Why you shouldn’t refactor your code blindly | by Akash Khunt | Sep, 2022 provides sharpness to you and is helpful for adjunct to your information

Why you should not refactor your code blindly | by Akash Khunt | Sep, 2022