Study with me for Code Refactoring ( Story3 — Long Method of Bloaters)
Bloaters are already explained in the previous article Story 2. I want to explain the details of the symptoms and treatments of the Long Method.
Long Method
Symptoms
In clean code, Robert martin was already told that a method line of codes must not be greater than 10. In reality, splitting the use case of the function is a more effective and nice way to readability
# Long Method
fun longMethod() {
# Do first thing
# Do second thing
# Do third thing
# Do fourth thing
}
Treatment
- Too complex and too difficult to read in one method — use Extract Method.
Problem
# Extract Method
fun printOwing() {
var outstanding: Double = 0.0
// print banner
println("********************************")
println("******** Customer Owes *********")
println("********************************")
// calculate outstanding
for (orderLine in orderLines) {
outstanding += orderLine.amount
}
// print details
println("Name: $name")
println("Amount: $outstanding")
}
Solution
fun printOwing() {
var amount: Double = 0.0
printBanner()
outstanding = getOutstanding(amount)
printDetails(outstanding)
}
private fun getOutstanding(amount: Double): Double {
var outstanding = previousAmount
for (orderLine in orderLines) {
outstanding += orderLine.amount
}
return outstanding
}
Benefits
- Less code coupling
- More readable code
- More Maintainability
- More independent parts of the code
2. If local variables and parameters interfere with extracting a method, use Replace Temp with Query, Introduce Parameter Object and Preserve Whole Object
*Replace Temp with Query
Problem
class Order {
var quantity: Int = 0
var itemPrice: Double = 0.0
}
fun proceedOrder(order: Order): Double {
var basePrice = order.quantity * order.itemPrice
var discount = 0.0
if (basePrice > 1000) {
discount = basePrice * 0.05
}
return basePrice - discount
}
Treatment
fun proceedOrder(order: Order): Double {
return order.basePrice() - order.discount()
}
fun Order.basePrice(): Double {
return this.quantity * this.itemPrice
}
fun Order.discount(): Double {
return if (basePrice() > 1000) basePrice() * 0.05 else 0.0
}
Benefits
- Code readability & maintainability
- Less Line
*Introduce Paramter method
Problem
fun doStuff(count: Int,items: List<Item>,name: String,isGood: Boolean)
fun doItemUpdate(count: Int,items: List<Item>,name: String,moreItems: Collection)
Treatment
data class DotaGame(
var count: Int,
var items: List<Item>,
var name: String
)
fun doStuff(game: DotaGame,isGood: Boolean)
fun doItemUpdate(game: DotaGame,moreItems: Collection)
Benefit
- More readable code
- Identical groups of parameter
*Preserve the Whole Object
Problem
val low = daysTempRange.getLow()
val high = daysTempRange.getHigh()
val withinTemp = plan.withinRange(low, high)
Treatment
val withinTemp = plan.withinRange(daysTempRange)
Benefit
- no more rewriting when data is more needed in withinRange
- single object and more readable
3. So many variables in this method — Replace method With Method Object
Problem
fun proceedBlurImage(): BlurImage {
val blurAlpha = 0.5
val greyColor = Color.Grey
val compress = true
val greyImage = Image()
# long calculation
}
Treatment
Class BlurImage {
val blurAlpha = 0.5
val greyColor = Color.Grey
val compress = true
val greyImage = Image()
fun execute(): BlurImage
}
fun proceedBlurImage = BlurImage.execute()
Benefit
- Independent Code
- Can Apply Dependency Injection
4. Too many Conditional operators and loops — Decompose Conditional
Problem
if (date.before(WINTER_START) || date.after(WINTER_END)) {
charge = quantity * summerRate
}
else if (date.before(RAINNY_START) || date.after(RAINNY_END)) {
charge = quantity * rainnyRate
}
else {
charge = quantity * winterRate
}
Treatment
enum class Seanson {
SUMMER,
RAINNY,
WINTER
}
fun priceForSummer() = quantity * summerRate
fun priceForRainny() = quantity * rainnyRate
fun priceForWinter() = quantity * winterRate
when(season) {
is Season.SUMMER -> priceForSummer()
is Season.RAINNY -> priceForRainny()
is Season.WINTER -> priceForWinter()
}
Benefit
- More readable and maintainability
Note: Sometimes so many code extracts or queries the method tends to be more complex and hard to read. So, please keep it simple as much as you can.
This is the end of Story 3.
See you next time, bye-bye 👋