Scala Style by Adform Research (Saulius Valatka)

23
Intermission: Code Review (mainly Audience Profiling)

Transcript of Scala Style by Adform Research (Saulius Valatka)

Page 1: Scala Style by Adform Research (Saulius Valatka)

Intermission: Code Review(mainly Audience Profiling)

Page 2: Scala Style by Adform Research (Saulius Valatka)
Page 3: Scala Style by Adform Research (Saulius Valatka)

Project Structure

• A basic README would be nice – structure not obvious

• One sbt multi-project build ?

• Ant builds for teamcity no longer needed

Page 4: Scala Style by Adform Research (Saulius Valatka)

Tests

• @RunWith(classOf[JUnitRunner]) ?

• test names should be more informative:• "Apply" is not a good test name

• „Correct classification of urls with a tree“ -> "URLs are classified correctly with a tree„

• Hopefully last session was useful

Page 5: Scala Style by Adform Research (Saulius Valatka)

Naming Conventions

• extensions -> model ?

• object classifyNewUrls – CamelCasing, object should be adjective, not verb, NewUrlClassifier

• Convention for object with main method is Tool

Page 6: Scala Style by Adform Research (Saulius Valatka)

Naming Conventions

• def apply(key: List[K]): Option[V] = map.get(key.reverse)

• def applyrev(reversekey: List[K]): Option[V] = map.get(reversekey)

• Semantics: apply -> T; get -> Option[T]

• length -> size

• apply is very different from applyrev

Page 7: Scala Style by Adform Research (Saulius Valatka)

Public APIs

//use += when building a tree, this checks the existing tree for mother branches

def +=(key: List[K], properties: V): CumulativePrefixTree[K, V] = ...

//use + when reading a built tree, otherwise it will map properties incorrectly

def +(key: List[K], properties: V): CumulativePrefixTree[K, V] = ...

Mm!?

It should be impossible for me to destroy your data structure!

+= implies mutation, you do not mutate !!

Page 8: Scala Style by Adform Research (Saulius Valatka)

CumulativePrefixTree

• Looks like a case class? Use case classes!

• Not obvious how it works

• Hallway usability testing ?

Page 9: Scala Style by Adform Research (Saulius Valatka)

Designing Classes

Refactoring

Qu

alit

y Perfection

Embrace refactoring !

Page 10: Scala Style by Adform Research (Saulius Valatka)

Readability

implicit def flatten2[A, B, C](t: (A, (B, C))): (A, B, C) = (t._1, t._2._1, t._2._2)

new CategoryList(List(l1.catscores, l2.catscores).flatten.groupBy(w => w._1).mapValues(x => (x.map(w => w._2).sum, x.map(w => w._3).sum)).toList.map(x => flatten2(x)))

Page 11: Scala Style by Adform Research (Saulius Valatka)

Wow, so utils, very much

• object Utils is not the best way to go, either add methods on class or on the companion object

• Putting utils in package objects also looks weird

Page 12: Scala Style by Adform Research (Saulius Valatka)

Too much tuples ?

• type CatScore = (Int, Double, Int) // ._1._2._3 hell !!

• def addLists(l1: List[(Int, Int)], l2: List[(Int, Int)]): List[(Int, Int)] = {

• List(l1, l2).flatten.groupBy(w => w._1).mapValues(_.map(_._2).sum).toList

• }

• val categorylist: List[(Int, Int)] List[CategoryWeight] ?

Page 13: Scala Style by Adform Research (Saulius Valatka)

Use types!

• type Weight = Double even this is OK, maybe excessive

• def function(category: Int, user: Int, banner: Int)

• Introduce classes, less confusion!

• Next session on types ?

Page 14: Scala Style by Adform Research (Saulius Valatka)

Catching throwable

def parse(line: String): Option[AdmantxUrl] = try {

val c = line.split('\t')

Some(new AdmantxUrl( c(0), c(1) ))

} catch {

case e: Throwable => None

}

Page 15: Scala Style by Adform Research (Saulius Valatka)

Catching throwable

• Prefer Try {} match Success/Failure

• Investigate scalding traps

Page 16: Scala Style by Adform Research (Saulius Valatka)

Vertica UDFs

• Implements Java interfaces, hard to write idiomatic scala

Page 17: Scala Style by Adform Research (Saulius Valatka)

.. but we can try!

for (i <- 0 to argCols.size() - 1) {

outputWriter.copyFromInput(i, inputReader, argCols.get(i))

}

argCols.zipWithIndex.foreach { (arg, idx) =>

outputWriter.copyFromInput(idx, inputReader, arg)

}

(for loops are too mainstream?)

Page 18: Scala Style by Adform Research (Saulius Valatka)

Pattern matching

if (result == None) {

resWriter.setStringNull()

} else {

resWriter.setString(result.getOrElse(""))

}

Page 19: Scala Style by Adform Research (Saulius Valatka)

Types !!!!!111

case class Vars(

productId: Option[String], step: Option[String], categoryId: Option[String]

)

Why is device_type_id a VARCHAR(1) !?

val returnVarcharLength = 1

returnType.addVarchar(returnVarcharLength)

Page 20: Scala Style by Adform Research (Saulius Valatka)

process-logs-rtb

Page 21: Scala Style by Adform Research (Saulius Valatka)

process-logs-rtb

• Generated code -> macros

• Records -> tuples, HLists ?

• Pull request for MultiSourceTap

• Testing for MultiSourceTap

• Catching throwables

Page 22: Scala Style by Adform Research (Saulius Valatka)

Future Scala Sessions

• Saulius: types, macros

• Edgaras: algebird

• Dima: functional hipsterism ?

• Alex: scalaz (streams, etc.) ?

• Ed: Java/Scala collections

• Others: !?!• Topics: Actors, Parallelism, Library overviews ? More diversification ?

Page 23: Scala Style by Adform Research (Saulius Valatka)