CodeNewbie Community 🌱

Cover image for Writing cleaner Jetpack Compose code with the Twitter Compose Ruleset
Tristan
Tristan

Posted on

Writing cleaner Jetpack Compose code with the Twitter Compose Ruleset

Table of contents

  1. Introduction
  2. Code we will be refactoring
  3. Mistake 1
  4. Mistake 2
  5. Mistake 3
  6. Mistake 4
  7. Refactored code

Introduction

  • Lately I have been trying to find ways to refactor my Jetpack compose functions and thankfully I stumbled across the Twitter Compose Ruleset, which can be found HERE.
  • What the Twitter Compose Ruleset actually is, is a set of custom ktlint rules to ensure that your composables don't fall into common pitfalls, that might be easy to miss in code reviews. You can even find a tutorial on how to set it up with ktlin HERE. But for right now we are going to focus on hand refactoring some code from my latest app.

My latest app for cattle farmers in North America

The GitHub

The code we will be refactoring:

  • The code below is the code we will be refactoring by applying the rules found HERE
@Composable
fun CalendarDock(viewModel: EditCalfViewModel){
val calfDate = viewModel.uiState.value.birthDate!!
    val convertedDate = calfDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    val selectedDate = remember {
        mutableStateOf<LocalDate?>(convertedDate)
    }
    val calendarState = rememberSheetState()

    CalendarDialog(
        state = calendarState,
        config = CalendarConfig(
            monthSelection = true,
            yearSelection = true
        ),
        selection = CalendarSelection.Date(selectedDate = selectedDate.value){ newDate ->

            selectedDate.value = newDate
            viewModel.updateDate(newDate)

        }
    )
    Row(
        horizontalArrangement = Arrangement.SpaceBetween) {
        OutlinedTextField(
            //state
            enabled = false,
            value = "Date born: "+ selectedDate.value.toString(),
            onValueChange = {  },
            //style
            singleLine = true,
            placeholder = {
                Text(text = "Date", fontSize = 20.sp)
            },
            modifier = Modifier
                .fillMaxWidth(),
            textStyle = TextStyle(fontSize = 20.sp),


            )
    }


}

Enter fullscreen mode Exit fullscreen mode

Mistake 1: Passing a ViewModel as parameter

  • Notice in the signature of the compose function I am passing in a viewModel as a parameter:
fun CalendarDock(viewModel: EditCalfViewModel)
Enter fullscreen mode Exit fullscreen mode
  • As stated in the RULES, instead of passing a viewModel, we should pass in the relevant data or an optional lambda

Mistake 2: No modifier parameter

  • Notice how this code above has no modifier parameter. This is a serious red flag when writing compose code. Every composable function (yes I do mean literally every compose function) should have a modifier parameter. The main reason for this is because it promotes flexibility and code reuse but if you want a deeper understanding I recommend you read the blog post HERE

Mistake 3: Position of the modifier parameter

  • When adding the modifier parameter we should make sure to add it in the correct position. When adding parameters to compose functions, the mandatory parameters come first and then comes the modifier parameter. The modifier parameter should occupy the first optional parameter slot to set a consistent exception for other developers. This means as our project grows and we add more people to our team, they can expect a consistent programming experience.

Mistake 4: Modifiers should have default parameters

  • as the rules state:
    Composables that accept a Modifier as a parameter to be applied to the whole component represented by the composable function should name the parameter modifier and assign the parameter a default value of Modifier.

  • Long story should if you have a modifier parameter you should give it a default value of Modifier

Refactored code:

  • So with all these rules applied our refactored code now looks like this:
@Composable
fun CalendarDock2(dateBorn: Date,selectedAction:(LocalDate)->Unit,modifier: Modifier = Modifier){

    val convertedDate = dateBorn.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    val selectedDate = remember { mutableStateOf<LocalDate?>(convertedDate) }
    val calendarState = rememberSheetState()

    CalendarDialog(
        state = calendarState,
        config = CalendarConfig(
            monthSelection = true,
            yearSelection = true
        ),
        selection = CalendarSelection.Date(selectedDate = selectedDate.value){ newDate ->

            selectedDate.value = newDate
            selectedAction(newDate)

        }
    )
    Row(
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        OutlinedTextField(
            //state
            enabled = false,
            value = "Date born: "+ selectedDate.value.toString(),
            onValueChange = {  },
            //style
            singleLine = true,
            placeholder = {
                Text(text = "Date", fontSize = 20.sp)
            },
            modifier = modifier,
            textStyle = TextStyle(fontSize = 20.sp),


            )
    }


}


Enter fullscreen mode Exit fullscreen mode

Conclusion

  • Thank you for taking the time out of your day to read this blog post of mine. If you have any questions or concerns please comment below or reach out to me on Twitter. //state

Top comments (1)

Collapse
 
daniel51711 profile image
Daniel51711 • Edited

Hey, ik snap wat je bedoelt met al die details rond modifiers en parameters, ik heb zelf ook wel eens geklooid met code en voelde me er helemaal in vastgelopen. Op een gegeven moment besloot ik juist even afstand te nemen en ontspanning te zoeken, zo kwam ik terecht bij rooksbet.co.nl. Daar probeerde ik een paar casinospellen uit, eerst verloor ik een paar rondes omdat ik te voorzichtig speelde, maar toen ik mijn inzetten wat verhoogde kwam er eindelijk een mooie winst. Dat gaf me precies die energieboost die ik nodig had om met frisse blik terug te keren naar mijn code. Voor spelers uit de Nederlanden zijn er bovendien speciale bonussen, wat het nog leuker maakt. Soms helpt het echt om even los te komen en daarna weer met nieuwe motivatie verder te werken.