Scala and LiftWeb presentation (Russian)
Upcoming SlideShare
Loading in...5
×
 

Scala and LiftWeb presentation (Russian)

on

  • 2,345 views

 

Statistics

Views

Total Views
2,345
Views on SlideShare
2,093
Embed Views
252

Actions

Likes
1
Downloads
82
Comments
0

5 Embeds 252

http://cnc.dn.ua 242
https://www.linkedin.com 6
http://www.linkedin.com 2
http://0.0.0.0:4000 1
http://webcache.googleusercontent.com 1

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Scala and LiftWeb presentation (Russian) Scala and LiftWeb presentation (Russian) Presentation Transcript

  • +Дмитрий Стропалов, Александр Михальчук
  • If I were to pick a language to use today other  than Java, it would be Scala James GoslingI can honestly say if someone had shown me the  Programming in Scala book by by Martin Odersky, Lex Spoon & Bill Venners back in 2003  I’d probably have never created Groovy James Strachan
  • возникновение• Разработан  в  2001­2004  годах  (представлен  в  2004    г.)  в  Лаборатории  методов  программирования  EPFL  (Федеральная  политехническая  школа  Лозанны,  Швейцария)  под  руководством  Мартина  Одерски (Martin  Odersky) • Большое  влияние  оказали  исследовательские  работы  в  области разработки (компонентного) ПО, ЯП• Попытка  разработки  языка,  который  бы  хорошо  масштабировался (SCAlable LAnguage)• Унификация  объектно­ориентированного  и  функционального  подходов  и  предоставление  их  в  языке  со  статической  типизацией.  Расширенные  механизмы  абстракции, композиции и декомпозиции• Хорошая  интеграция  с  существующими  платформами  и  библиотеками — изначальная ориентация на совместную  работу с Java и .NET
  • «академический» язык• LinkedIn  –  фреймфорк  “Norbert”  для  построения  асинхронных,  кластерных,  высоконагруженных  приложений. Представление социального графа                 • EDF – крупнейшая во Франции энергетическая компания• Twitter – главная очередь сообщений (message queue)• Novell  –  сервис  “Vibe  Cloud”,  предоставляющий  корпоративную  закрытую  и  защищенную  платформу  для  совместной работы• The  Guardian  –  API  для  “Open  Platform”,  предоставление  доступа к медийному архиву агенства• Xerox – различное ПО, включая и клиентское• FourSquare – полностью все предоставляемые сервисы• Sony – система управления хранением данных• Siemes (+ SAP) – корпоративная система сообщений• …  
  • основные концепции• Бесшовная интеграция с Java­кодом (C#/.NET)• Единообразная  объектная  модель  –  любое  значение  является объектом, любая операция – вызов метода• Функциональный язык – функции являются полноправными  значениями. Каждая функция возвращает значение• Механизмы абстракций как для типов, так и для значений• Использование  «примесей»  (mixin,  trait)  для  композиции  классов• Сравнение с образцом (pattern matching)• Естественная обработка документов XML• Выведение типов• Неизменяемые (immutable types) типы• Ленивые (lazy) вычисления
  • hello world!Вариант I: object Application {     def main(args: Array[String]): Unit = {         for (arg <­ args) {          if (arg.startsWith("­"))             println(arg)         }     } }
  • hello world!Вариант I: object Application {     def main(args: Array[String]): Unit = {         for (arg <­ args) {          if (arg.startsWith("­"))             println(arg)         }     } }Вариант II:     def main(args: Array[String]): Unit = {         for (arg <­ args; if arg.startsWith("­"))            println(arg)     }
  • hello world!Вариант I: object Application {     def main(args: Array[String]): Unit = {         for (arg <­ args) {          if (arg.startsWith("­"))             println(arg)         }     } }Вариант II:     def main(args: Array[String]): Unit = {         for (arg <­ args; if arg.startsWith("­"))            println(arg)     }Вариант III:     def main(args: Array[String]): Unit = { args.withFilter(_.startsWith("­")).map(println)     }
  • значения и переменные    val a: Int = 5        val b = {            println("Init b")            10        }        var c = 15        lazy val d = {            println("Init d")            a + c        }        println("a:%d b:%d c:%d".format(a, b, c))        c = 20        println("c:%d d:%d".format(c, d))        println("d:" + d)>>>   Init b  a:5 b:10 c:15  Init d  c:20 d:25  d:25
  • классы и объекты class Parent(value: String) {     val classValue = value } class A1 {     val a: Int = 0     private var b = 0     def getB = b } object A1 extends Parent("Object A1: ") {     def setA(obj: A1) { obj.b = 5 } } object Application extends Application {     val obj = new A1     A1.setA(obj)     println(A1.classValue + obj.getB) }         >>>  Object A1: 5  
  • трейты (traits) trait Role {     def getRole: Int     def isAdmin = if (getRole == 0) true else false } trait Info {     def getInfo: String     def setInfo(info: String) } class User(role: Int) extends Role with Info {     val userRole = role     var userInfo: String = ""     def getRole = userRole     def getInfo = userInfo     def setInfo(info: String) {  userInfo = info  } }  
  • анонимные функции object Application extends Application {     val hello = () => "Hello, anonymous"     val foo = (x: String) => x.split(:).mkString(", ")     def bar(s: String, f: String => String) = {         f(s)     }     println(hello) println(hello())     println(foo("value1:value2:value3:value4"))     println(bar("John:Mike:Ann", foo)) }>>>  <function0> Hello, anonymous value1, value2, value3, value4 John, Mike, Ann  
  • карринг def filter(xs: List[Int], p: Int => Boolean): List[Int] = if (xs.isEmpty) Nil else if (p(xs.head)) xs.head :: filter(xs.tail, p) else filter(xs.tail, p) def modN(n: Int)(x: Int) = ((x % n) == 0) val list = (1 to 10).toList println(filter(list, modN(2))) println(filter(list, modN(3)))         >>>  List(2, 4, 6, 8, 10) List(3, 6, 9)  
  • xml val xml =     <depot>         <item name="item 1">             <part name="part 1"/>             <part name="part 2"/>             <item>inner item</item>         </item>         <item name="item 2"></item>         <label type="title">Depot title</label>     </depot>          xml  "item"     xml  "item"     xml  "@type"  
  • xml val ptype = "box"     val title = "Examples"     val item = <item type={ ptype }>{ title }</item>     val items =         <items>             {for (index <­ (0 to 3).toList)                 yield <item>{ index }</item>}         </items>     println(item)     println(items)>>> <item type="box">Examples</item> <items>        <item>0</item> <item>1</item> <item>2</item> <item>3</item>       </items>
  • сравнение с образцом def matcher(x: Any) = {         x match {            case 1 => println("Integer value 1")            case y: Int => println("Integer value: " + y)            case <e>{ tagValue }</e> =>  println("XML Tag value: " + tagValue)            case _ => println("Something else: " + x)         }     }     matcher(1)     matcher(10)     matcher(<e>Lorem ipsum</e>)     matcher("simple string")>>> Integer value 1 Integer value: 10 XML Tag value: Lorem ipsum Something else: simple string
  • магический implicit implicit def double2int(x: Double) = {        println("converting double to int ...")         if (x < 10) 0 else x.toInt     }     val i: Int = 3.5     println(i)>>> converting double to int ... 0 implicit val a: Int = 10     implicit val b: Double = 1.5     def foo(implicit a: Int, b: Double) = { println("%d, %f".format(a, b)) }     foo>>> 10, 1.500000
  • The first rule of Lift is:                                               Its easier than you think. I think the most important feature we have in  Lift is the community around it(committers and non­committers). I have joined  the mailing list just a few months ago and I am impressed with how willing  everyone is to help each other.
  • общая информация• Разработка  начата  в  2007  году,  сейчас  достигнута  версия 2.2. Главный разработчик — Девид Поллак (David  Pollak). Рабочее название было “Scala on Sails” • Разрабатывается  с  целью  объединить  лучшие  идеи  и  концепции  из  существующих  web­фреймворков  (Java­ фреймворки, RoR)• Концентрация на бизнес­логике приложения• Простая и эффективная система безопасности• Использование  преимуществ  Scala  как  базового  языка  (контроль  типов,  встроенная  обработка  XML,  функциональные элементы)• View­First предпочтительнее MVC­модели• Изначальная поддержка AJAX и Comet• Используется  в  таких  компаниях,  как  Nowell,  SAP,  Innovation Games, Foursquare, Untyped и другими
  • сообщество• Домашняя страница: http://liftweb.net/• Google Groups (2500 участников): http://groups.google.com/group/liftweb• Открытый исходный код на GitHub:  http://github.com/dpp/liftweb/tree/master• Wiki и треккер на Assembla: http://www.assembla.com/wiki/show/liftweb/• Бесплатные книги:  Exploring Lift: http://exploring.liftweb.net/  Simply Lift: http://stable.simply.liftweb.net/• Дружелюбное комьюнити и Поллак
  • быстрый старт• Генерация приложения Scala 2.8.1 + Lift 2.2: mvn archetype:generate  ­DarchetypeGroupId=net.liftweb  ­DarchetypeArtifactId=lift­archetype­basic_2.8.1  ­DarchetypeVersion=2.2  ­DarchetypeRepository=http://scala­tools.org/repo­releases  ­DremoteRepositories=http://scala­tools.org/repo­releases  ­DgroupId=ua.dn.cnc  ­DartifactId=lift_demo  ­Dversion=1.0• Запуск сервера: mvn jetty:run
  • структура проекта Структура каталога нового проекта:• project – Simple Build Tool (SBT) конфигурация• src/main/resources – ресурсы проекта• src/main/scala – исходный код на Scala• ua.dn.cnc.Boot – конфигурация Lift приложения• ua.dn.cnc.lib.DependencyFactory  –  Dependency  Injection• ua.dn.cnc.model.User – сущность User• ua.dn.cnc.snippet.HelloWorld – Hello World сниппет• src/main/webapp – web ресурсы (шаблоны, html,  css, js)• src/main/test ­ исходный код тестов• pom.xml – Apache Maven конфигурация
  • mapper ormobject News extends News with LongKeyedMetaMapper[News] {    override def dbIndexes =  UniqueIndex(title) :: super.dbIndexes}class News extends LongKeyedMapper[News] with IdPK {    def getSingleton = News    object title extends MappedString(this, 255) {        override def dbNotNull_? = true    }    object text extends MappedString(this, 1200) {        override def dbNotNull_? = true    }    object publish extends MappedBoolean(this) {        override def dbNotNull_? = true        override def defaultValue: Boolean = true    }    object date extends MappedDate(this) {        override def dbNotNull_? = true    }}
  • mapper ormСоздание записи: val n = News.create n.title("Lorem ipsum") … n.saveУдаление записи: n.delete_!Все записи: val n = News.findAllЗаписи по условию:   val n = News.findAll(By(News.publish, true),                                         OrderBy(News.date, Descending),                        StartAt(0), MaxRows(10))Записи по SQL­запросу:   val n = News.findAllByInsecureSql("select * from news " +             "where publish = 1 order by(date_c)",             IHaveValidatedThisSQL("dba", "2011­01­01"))
  • menuBoot.scala: import net.liftweb.http.LiftRules import net.liftweb.sitemap.Loc import net.liftweb.sitemap.Loc.Hidden import net.liftweb.sitemap.Loc.strLstToLink import net.liftweb.sitemap.Menu import net.liftweb.sitemap.SiteMap ... def boot { ... val myLoc = Loc("HomePage", "index" :: Nil, "Home Page",  Hidden) val myMenu = Menu(myLoc) val allMenus = myMenu :: User.sitemap val mySiteMap = SiteMap(allMenus: _*) LiftRules.setSiteMap(mySiteMap) ...
  • menuLoc: Loc(theName:"Home", theLink:new Link(List("index")),  theText:"Home Page") Loc("About", "info" :: "about" :: Nil, "About", Hidden) Loc("HomePage", "index" :: Nil, "Home Page", Test((req) =>  req.isIE6)) Loc("Static", Link(List("static"), true, "/static/index"),  "Static Content")Menu: val myMenu = Menu(Loc("About", "about" :: Nil, "About",  Hidden)) val helpMenu = Menu(myHelpMenuLoc, myUserHelpMenu,  myTechnicalHelpMenu) val allMenus = myMenu :: User.menusSiteMap: LiftRules.setSiteMap(SiteMap(allMenus: _*))HTML­вывод: <lift:Menu.builder /> или <div class="lift:Menu.builder" />
  • url rewritingbootstrap.liftweb.Boot.boot: LiftRules.rewrite.prepend(NamedPF("ArticleRewrite") { case RewriteRequest( ParsePath("article" :: id :: action :: _, _, _, _) , _, _) => RewriteResponse( "article" :: action :: Nil, Map("id" ­> id)) }) /article/1/edit ­> /article/edit?id=1
  • шаблоны default.html index.html <lift:surround with="default"><html> <head> <lift:bind-at name="controls"> … <head> </head> <script src="…"/> </head> <body> <div class="controls"> <div> … … </div> <lift:bind name="controls" /> </lift:bind-at> </div> <lift:bind-at name="content"> … <div class="content"> … <lift:bind name="content" /> </div> </lift:bind-at> … </body> </lift:surround></html>
  • snippets … … <ul> <ul> <lift:Test.show> <li>Foo: Bar</li> <li><e:item/></li> <li>Fizz: Buzz</li> </lift:Test.show> <li>Some title: and some text</li> </ul> </ul> … …class Test { def show(in: NodeSeq): NodeSeq = { TestModel.findAll().flatMap(item =>          bind("e", in, "item" ­> Text(                    "%s: %s".format(item.title, item.text)               ))          ) }}
  • формыАвтоматическая генерация: Model.toForm(Full("Save"), { _.save })Snippet: private var newKeyword = "" def keywordsForm(in: NodeSeq): NodeSeq = {        bind("entry", in,            "addNewKeyword" ­> SHtml.text("", newKeyword = _,  "maxlength" ­> "50"),            "submitNewKeyword" ­> SHtml.submit("Добавить",  addNewKeyword))   } private def addNewKeyword() { …        val kw =  <lift:clazz.keywordsForm form="POST"> KeywordsModel.create <entry:addNewKeyword />        kw.keyword(newKeyword) <entry:submitNewKeyword />        kw.save </lift:clazz.keywordsForm> } …
  • ссылки• Обзор языка программирования Scala• Статьи на Habrahabr• Programming Scala• Scala Reference Manuals• Scala Style Guide• Exploring Lift• Lift Wiki
  • Спасибо за внимание и EOF