about Why you shouldn’t refactor your code blindly | by Akash Khunt | Sep, 2022 will lid the newest and most present suggestion in regards to the world. admission slowly consequently you perceive skillfully and appropriately. will buildup your data precisely and reliably
I’ve an extended historical past of refactoring code every time I see the yellow marks on the appropriate hand facet of the code editor window in Android Studio. The most effective half about having a sensible IDE is that along with displaying the issue, it additionally suggests an answer that may be straight utilized (wherever doable). As within the following screenshot, you may see Take away redundant ‘public’ modifier choice to use the correction.
I’ve used this perform fairly ceaselessly to do some minor refactoring for a few years now, however not too long ago when doing one thing comparable, I ended up capturing myself within the foot 😅.
The code refactor
Let’s begin with some background first. As you may see within the following code, now we have a watcher checklist which we’ll use to inform the lessons that implement it.
And the watcher checklist was being utilized by one other class like one thing beneath:
Trying on the code we will see that it is rather easy the place we’re creating a spread and iterating by way of it and calling the onStatusChange() perform. Once I was including some performance to the identical class, Android Studio confirmed me that this may be refactored to one thing like beneath:
The steered refactor additionally is sensible because it makes use of the till operator we’re primarily allocating some reminiscence for the index (i.e. Yo) which isn’t required along with accessing the ingredient. So I utilized the steered change and the code was modified as proven beneath:
The whole lot was positive till the refactor of the outdated code was launched within the launch construct. However after just a few days of launch once I opened Crashlytics to see if any new accidents are reported and I used to be stunned. I noticed a java.util.ConcurrentModificationException the crash was reported in the identical location the place I refactored the loop code earlier 😕.
I examined the 2 code variants by putting them facet by facet, and at first look, they appeared comparable, since in each instances we used Kotlin code. in (i.e. iterator operator) 🤔. Then, since everyone knows that the Kotlin compiler is wise and infers the article sort, I believed I might verify the iterator sort used for in each instances.
Within the first case the place in was used with Interval, IntProgressionIteratorIntProgressionIterator it will get used to doing the iteration. If we verify the code IntProgressionIteratorIntProgressionIterator we will see that there isn’t any logic to drag ConcurrentModificationExceptionConcurrentModificationExceptionConcurrentModificationException. This is sensible as as soon as the vary is created there isn’t any technique to modify it.
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.
As we all know in our case observers checklist was a MutableList (which is backed by an ArrayList internally) I opened the ArrayList. Additionally wanting on the Crashlytics stacktrace proven above, we will 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 checklist is modified by another thread when iterating. And searching on the precise code in my code base I noticed that it very properly may occur 😅.
Correction and hindsight
The answer was fairly simple. We simply wanted to make use of some synchronization mechanism to verify the checklist wasn’t modified by one other thread when it was iterating.
The fascinating facet was that it was not flagged earlier attributable to a mixture of the next issues:
- Interval ending with begin = 0 Y final = watchers.measurement earlier than the loop executes.
- There have been no occasions of deletions/removals of the observers checklist like this the opposite notorious NoSuchElementException the exception doesn’t happen both.
In instances the place I repair not-so-common bugs in my Kotlin code, I attempt to confirm the habits by wanting on the decompiled bytecode. For this, I exploit Android Studio’s built-in instrument which will be invoked by Instruments > Kotlin > Present Kotlin Bytecode. Then click on on the decompile button current on the prime left of the open window.
For the above case of ListIterator Bytecode decompiled, all the things appears positive primarily based on our understanding that we obtained earlier.
However for the case of IntProgressionIteratorIntProgressionIterator we will see that it’s not getting used in any respect and the by loop with Interval transformed to easy for loop 😲. Nonetheless, the habits that we’d have obtained by utilizing IntProgressionIterator doesn’t appear to have modified.
I want the article virtually Why you shouldn’t refactor your code blindly | by Akash Khunt | Sep, 2022 provides sharpness to you and is helpful for rely to your data
Why you should not refactor your code blindly | by Akash Khunt | Sep, 2022