Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Le refactoring c'est repasser sur son code pour le rendre bien plus robuste, simple à lire et standard.
- C'est la qu'est l'intelligence du développeur, on différenciera le bon développeur du "mec qui suit les tuto sur openclassroom" avec ce genre de connaissance.
- ### Exemple 1:
- Du code pris sur un projet, qui est vraiment pas mauvais :
- ```kotlin
- /**
- * Get the data from the elastic search and convert the GeoNamesPlace to a Place
- * @param query Query with text to search and the fields to search in.
- * @param limit Limit of results
- * @return List of place
- */
- private fun searchPlace(isoLanguage: String, query: MultiMatchQueryBuilder, limit: Int): List<PlaceGeoNames>? {
- val placeList = arrayListOf<PlaceGeoNames>()
- val mapper = ObjectMapper()
- val searchRequest = SearchRequest(indexPrefix + isoLanguage.toLowerCase())
- val searchSourceBuilder = SearchSourceBuilder()
- searchSourceBuilder.query(query)
- searchSourceBuilder.size(limit)
- searchRequest.source(searchSourceBuilder)
- try {
- val searchResponse = Elasticsearch.search(searchRequest)
- val searchHits = searchResponse.hits.hits
- searchHits.forEach {
- val result = mapper.readValue<PlaceGeoNames>(it.sourceAsString)
- placeList.add(result)
- }
- } catch (exception: ElasticsearchException) {
- //if the index doesnt exists
- return null
- }
- return placeList
- }
- ```
- Quels améliorations vous imagineriez ici ?
- Dans le langage naturel ce que je fais ici c'est : Depuis une requete, la lancer et transformer les résultats dans un format qui me plait.
- En gros je veux un truc comme ca dans mes reves les plus fous en 1 ligne :
- ```kotlin
- fun searchPlace(): List<Place>? {
- return query.search.results.transformTo(monFormat)
- }
- ```
- Version factorisé (refactored)
- ```kotlin
- /**
- * Get the data from the elastic search and convert the GeoNamesPlace to a Place
- * @param query Query with text to search and the fields to search in.
- * @param limit Limit of results
- * @return List of place
- */
- private fun searchPlace(isoLanguage: String, query: MultiMatchQueryBuilder, limit: Int): List<PlaceGeoNames>? {
- try {
- query
- .toSearchRequest(indexPrefix + isoLanguage.toLowerCase(), limit)
- .search()
- .toHits()?.let {
- val mapper = ObjectMapper()
- val placeList = it.map {
- mapper.readValue<PlaceGeoNames>(it.sourceAsString)
- }
- return placeList
- }
- } catch (exception: ElasticsearchException) {
- //if the index doesnt exists
- return null
- }
- return null
- }
- ```
- On a déplacé dans des lieux standards les fonctions qui vont nous servir ailleurs
- ```kotlin
- //Avoiding .hits.hits that is ugly, but especially confusing and can generate errors
- fun SearchResponse.toHits(): Array<out SearchHit>? {
- return this.hits.hits
- }
- //From a query, I wanted to
- fun MultiMatchQueryBuilder.toSearchRequest(index: String, limit: Int): SearchRequest{
- val searchSourceBuilder = SearchSourceBuilder().query(this).size(limit)
- return SearchRequest(index).source(searchSourceBuilder)
- }
- //Simple wrapper, because extensions. More explicit to write, more simple, avoid some boilerplate
- fun SearchRequest.search(): SearchResponse {
- return Elasticsearch.search(this)
- }
- ```
- C'est stylé, mais on peut aller plus loin, je veux vraiment pouvoir parler simplement à mon code et qu'il appelle des fonctions standards.
- > Objectif du swag
- > `query.search.results.transformTo(monFormat)`
- Grâce aux `Generics`, on peut le faire, on va justement pouvoir rendre notre code générique, peut importe le type sur lequel on travail actuellement (ici des `PlaceGeoNames`)
- On va reprendre la partie qui est encore un peu moche pour la déporter dans une fonction générique qui va nous permettre de faire du fun en barre.
- ```kotlin
- //Cette partie m'embete parce que c'est pas beau, je dois instancier des variables et mapper des choses que je sais que je devrais refaire ailleurs un jour pour un autre type.
- .toHits()?.let {
- val mapper = ObjectMapper() //Coucou je sais pas ce que je fais la, je suis méga standard
- val placeList = it.map {
- mapper.readValue<PlaceGeoNames>(it.sourceAsString) //le fun est la.
- }
- return placeList
- }
- ```
- Donc si je prend ca et que je le déplace dans une extension générique cela me donnera ca :
- ```kotlin
- //Remember you came from this :
- fun SearchResponse.toHits(): Array<out SearchHit>? {}
- //If you understand the function declaraction line, you can go to sleep and have nice refactoring dreams about every piece of code.
- inline fun <reified T : Any>Array<out SearchHit>.transform() : List<T> {
- val mapper = ObjectMapper()
- return this.map {
- mapper.readValue<T>(it.sourceAsString)
- }
- }
- ```
- ET donc pour finir dans ma fonction principale j'ai ce joli code magnifique :
- ```kotlin
- private fun searchPlace(isoLanguage: String, query: MultiMatchQueryBuilder, limit: Int): List<PlaceGeoNames>? {
- try {
- query
- .toSearchRequest(indexPrefix + isoLanguage.toLowerCase(), limit)
- .search()
- .toHits()?.transform<PlaceGeoNames>()
- } catch (exception: ElasticsearchException) {
- //if the index doesnt exists
- return null
- }
- return null
- }
- ```
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement