12
Implicit classes Almost as beautiful as Trump’s hair

Implicit classes - share the knowledge

Embed Size (px)

Citation preview

Page 1: Implicit classes  - share the knowledge

Implicit classes Almost as beautiful as Trump’s hair

Page 2: Implicit classes  - share the knowledge

Extensions are amazing!

Page 3: Implicit classes  - share the knowledge

Why?

result match { case Success(_) => case Failure(ex) => Logger.error(s"Failed to comment project ${project.id}”)}

I HATE BOILERPLATE

result.logException(s"Failed to comment project ${project.id}”)

And even logs the exception, that sometimes we love to hide...

Page 4: Implicit classes  - share the knowledge

Implementation implicit class TryExtension[T](nativeTry: Try[T]) {

private val defaultMsg: String = "Try is a failure"

def logException(logger: String => Unit = defaultLogger, msg: String = defaultMsg): Try[T] = { nativeTry match { case Success(_) => nativeTry case Failure(e) => val msgWithStacktrace = s""" |$msg |message: ${e.getMessage} |${e.getStackTrace.mkString(System.lineSeparator)} """.stripMargin logger(msgWithStacktrace) nativeTry } }

private def defaultLogger(msgWithStacktrace: String): Unit = Logger.error(msgWithStacktrace) }

Page 5: Implicit classes  - share the knowledge

Although it uses “implicit”, remember that you still have to call the methods explicitly! So the “hate on implicits” arguments don’t apply ;)

Page 6: Implicit classes  - share the knowledge

It’s not about knowing how to do it, it is about doing it! Instead of copypasta more bolierplate..

.orElse { Logger.error(s"Failed to updated Heroku user: RequestURL=$url Response=${response.json}") None}

Pretty much as we did a .logException(), we can easily do a .logNone()!

.logNone(s"Failed to updated Heroku user: RequestURL=$url Response=${response.json}")

Page 7: Implicit classes  - share the knowledge

It can be more than just logsAlthough I like to use the extensions on logs, (because we don’t care about them, we just want the bad guys to be logged, and it always the same thing) there are MANY MORE cases where we can use them.

if (!updated) { ProjectRules.addUserToProject(

projectId,teamMember.userIdentifier,teamMember.permission

)}updated

Page 8: Implicit classes  - share the knowledge

Boolean Extension :D

updated.onFalse { ProjectRules.addUserToProject( projectId, teamMember.userIdentifier, teamMember.permission )}updated //not needed

.onFalse() returns the boolean itself, so no need to repeat the “updated”

Page 9: Implicit classes  - share the knowledge

Plenty of great use cases!

//potatos: Seq[A]potatos.distinctBy(_.weight) //Instead of CollectionHelper.distinctBy(potatos, _.weight)

//res: Option[A]res.toResponse(msg = “Failed xxx”)

//res: Try[A]res.toResponse()

…….

Page 10: Implicit classes  - share the knowledge

Implicit Classes Everywhere???

The “Extension” types are just a way to achieve extension methods. Never use their types!

For example “TryExtension” should only be mentioned on the import itself, shouldn’t be use anywhere else! We just want the methods, not the type of the class

And also, PLEASE don’t do implicit extensions on classes that we own!

If if is our code, we can just go there and add a method! “Don’t wanna update foundation” is not an excuse to start making implicit classes that extend our Response!

Page 11: Implicit classes  - share the knowledge

“he who yields the chalice shall have everlasting awesomeness”

- The ancient council of elders

Page 12: Implicit classes  - share the knowledge

Thank you!

João Machado

[email protected]

https://github.com/machadoit

Meet our team at:

https://www.codacy.com

Review less, merge fasterCheck code style, security, duplication, complexity and coverage on every

change while tracking code quality throughout your sprints.