in practice scala
play

in Practice Scala patric.fornasier@thoughtworks.com - PowerPoint PPT Presentation

in Practice Scala patric.fornasier@thoughtworks.com marc.hofer@thoughtworks.com e c n e i r e p x E Optimising IT n g i s e D Organisations Consulting Build & Release Management technology esting T Offices 2 Warning


  1. in Practice Scala patric.fornasier@thoughtworks.com marc.hofer@thoughtworks.com

  2. e c n e i r e p x E Optimising IT n g i s e D Organisations Consulting Build & Release Management technology esting T

  3. Offices 2

  4. Warning presentation Contains code examples

  5. A bit of Context about the project

  6. Why Scala ?

  7. Scala ? What is

  8. Functional Object Oriented Scala Scriptable Statically JVM- Typed based

  9. Scala Compile Byte Code JVM

  10. Benefits

  11. “Functional Programming”

  12. List<String> features = Arrays.asList("noFeature", "featureC", "featureB", "featureA"); for (String feature : features) { System.out.println(feature); }

  13. List<String> javaFeatures = Arrays.asList("noFeature", "featureC", "featureB", "featureA"); for (String feature : javaFeatures) { System.out.println(feature); } val scalaFeatures = List( "noFeature", "featureC", "featureB", "featureA") scalaFeatures foreach { println _ }

  14. val currentFeatures = List("noFeature", "featureC", "featureB", "featureA") Result: "featureA_toggle, featureB_toggle" currentFeatures.filter { _.startsWith("feature") } .sorted .take(2) ? .map { _ + "_toggle" } .mkString(", ")

  15. String result = ""; List<String> currentFeatures = Arrays.asList("noFeature", "featureC", "featureB", "featureA"); Collections.sort(currentFeatures); int i = 0, j = 0, take = 2; while(i < take && j < currentFeatures.size()) { String feature = currentFeatures.get(j++); if(feature.startsWith("feature")) { result += feature + "_toggle" + ((i++ != take) ? ", " : ""); } } currentFeatures.filter { _.startsWith("feature") } .sorted .take(2) .map { _ + "_toggle" } .mkString(", ")

  16. “Less Boilerplate”

  17. public class Property {}

  18. class Property {}

  19. public class Property { private final String key; private final String value; private final String defaultValue; public Property(String key, String value, String defaultValue) { this.key = key; this.value = value; this.defaultValue = defaultValue; } }

  20. class Property(key: String, value: String, default: String) {}

  21. public class Property { // ... public String getKey() { return key; } public String getValue() { return value; } public String getDefaultValue() { return defaultValue; } }

  22. class Property(val key: String, val value: String, val default: String) {}

  23. public class Property { // ... public Property changeTo(String newValue) { return new Property(key, value, newValue); } public Property reset() { return new Property(key, value); } @Override public String toString() { return String.format("%s=%s", key, value); } }

  24. class Property(val key: String, val value: String, val default: String) { def changeTo(newValue: String) = new Property(key, newValue, default) def reset = new Property(key, default) override def toString = "%s=%s" format(key, value) }

  25. public class Property { // ... @Override public boolean equals(Object obj) { if (!(obj instanceof Property)) return false; Property other = (Property) obj; return other.key.equals(key) && other.value.equals(value) && other.defaultValue.equals(defaultValue) } @Override public int hashCode() { int result = 17; result = 31 * result + key; result = 31 * result + value; result = 31 * result + defaultValue; return result; } }

  26. case class Property(key: String, value: String, default: String) { def changeTo(newValue: String) = Property(key, newValue, default) def reset = Property(key, default) override def toString = "%s=%s" format(key, value) }

  27. public class Property { private final String key; private final String value; private final String defaultValue; public Property(String key, String value, String defaultValue) { this.key = key; this.value = value; this.defaultValue = defaultValue; } public String getKey() { return key; } public String getValue() { return value; } public String getDefaultValue() { return defaultValue; } public Property changeTo(String newValue) { return new Property(key, value, newValue); } public Property reset() { return new Property(key, value); } @Override public String toString() { return String.format("%s=%s", key, value); } @Override public boolean equals(Object obj) { if (!(obj instanceof Property)) return false; Property other = (Property) obj; return other.key.equals(key) && other.value.equals(value) && other.defaultValue.equals(defaultValue) } @Override public int hashCode() { int result = 17; result = 31 * result + key; result = 31 * result + value; result = 31 * result + defaultValue; return result; } }

  28. case class Property(key: String, value: String, default: String) { def changeTo(newValue: String) = Property(key, newValue, default) def reset = Property(key, default) override def toString = "%s=%s" format(key, value) }

  29. case class Property(key: String, value: String, default: String) { public class Property { def changeTo(newValue: String) = Property(key, newValue, default) def reset = Property(key, default) private final String key; override def toString = "%s=%s" format(key, value) private final String value; } private final String defaultValue; public Property(String key, String value, String defaultValue) { this.key = key; this.value = value; this.defaultValue = defaultValue; } 45 vs 5 public String getKey() { return key; } public String getValue() { return value; } s C O L public String getDefaultValue() { return defaultValue; } public Property changeTo(String newValue) { return new Property(key, value, newValue); } public Property reset() { return new Property(key, value); } @Override public boolean equals(Object obj) { if (!(obj instanceof Property)) return false; Property other = (Property) obj; return other.key.equals(key) && other.value.equals(value) && other.defaultValue.equals(defaultValue) } @Override public int hashCode() { int result = 17; result = 31 * result + key; result = 31 * result + value; result = 31 * result + defaultValue; return result; } @Override public String toString() { return String.format("%s=%s", key, value); } } * ignoring blank lines

  30. “Less Boilerplate” Another Example: { Blocks }

  31. int statusCode = httpSupport.get("http://foo.com", new Block<Integer>() { public Integer execute(HttpResponse response) { return response.getStatusLine().getStatusCode()); } }); String content = httpSupport.get("http://foo.com", new Block<String>() { public Integer execute(HttpResponse response) { return EntityUtils.toString(response.getEntity()); } }); httpSupport.get("http://foo.com", new VoidBlock() { public void execute(HttpResponse response) {} }); val statusCode = get("http://foo.com") { statusCode } val content = get("http://foo.com") { toString } get("http://foo.com")

  32. “Java Compatibility”

  33. java -cp "lib/*" com.springer.core.app.Casper Scala library goes in here!

  34. val java = new java.util.ArrayList[String] val scala: Seq[String] = foo filter { ... }

  35. val log = Logger.getLogger("com.foo") log.debug("Hello!")

  36. Library JVM re-use “Gentle Learning Curve” “Java without ;”

  37. <XML-Support/>

  38. <PdfInfo hasAccess="false"> val pdfInfo = <DDSId>12345</DDSId> <ContentType>Article</ContentType> </PdfInfo> val contentType = (pdfInfo \ "ContentType").text val hasAccess = (pdfInfo \ "@hasAccess").text.toBoolean

  39. val pdfInfoList = <PdfInfoList> <PdfInfo hasAccess="false"> <DDSId>12345</DDSId> <ContentType>Article</ContentType> </PdfInfo> <PdfInfo hasAccess="true"> <DDSId>54321</DDSId> <ContentType>Book</ContentType> </PdfInfo> </PdfInfoList> case class PdfInfo(xml: NodeSeq) { val ddsId = (xml \ "DDSId").head.text val hasAccess = (xml \ "@hasAccess").head.text val contentType = (xml \ "ContentType").head.text } (pdfInfoList \ "PdfInfo") map { PdfInfo(_) }

  40. “DSL- Friendly”

  41. Levels of Testing System Functional Unit App2 App1 Integration DB App3

  42. Unit Test DSL class PropertyTest extends Spec with ShouldMatchers { it("should render key and value separated with an equals sign") { Property("shark", "fish").toString should equal ("shark=fish") } }

  43. Functional Test DSL class ForgottenPasswordPageTests extends FunctionalTestSpec with ForgottenPasswordSteps with Uris { it("should validate user email") { given(iNavigateTo(ForgottenPasswordPage)) when(iSubmitEmail("invalid@email.com")) then(iShouldSeeInvalidEmailErrorMessage) } }

Recommend


More recommend