Writing cleaner Jetpack Compose code with the Twitter Compose Ruleset
Tags: mobile, android, kotlin, tristan
Published: 2023-02-11 19:50:47


### Table of contents
1. [Introduction](#introduction)
2. [Code we will be refactoring](#refactor)
3. [Mistake 1](#one)
4. [Mistake 2](#two)
5. [Mistake 3](#three)
6. [Mistake 4](#four)
7. [Refactored code](#refactored)

### Introduction <a name="introduction"></a>
- 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](https://twitter.github.io/compose-rules/). 
- 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](https://twitter.github.io/compose-rules/ktlint/). 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
- [Google playstore](https://github.com/thePlebDev/CalfTracker)

### The GitHub
- [GITHUB](https://github.com/thePlebDev/CalfTracker)


### The code we will be refactoring: <a name="refactor"></a>
- The code below is the code we will be refactoring by applying the rules found [HERE](https://twitter.github.io/compose-rules/rules/)
```
@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),


            )
    }


}

```

### Mistake 1: Passing a ViewModel as parameter <a name="one"></a>
- Notice in the signature of the compose function I am passing in a viewModel as a parameter:
```
fun CalendarDock(viewModel: EditCalfViewModel)
```
- As stated in the [RULES](https://twitter.github.io/compose-rules/rules/#state), instead of passing a viewModel, we should pass in the relevant data or an optional lambda


### Mistake 2: No modifier parameter <a name="two"></a>
- 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](https://chris.banes.me/posts/always-provide-a-modifier/)

### Mistake 3: Position of the modifier parameter <a name="three"></a>
- 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 <a name="four"></a>
- 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: <a name="refactored"></a>
- 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),


            )
    }


}


```

###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](https://twitter.com/AndroidTristan).