Scala In Perl Company

Scala In Perl Company

10年あまりPerlを利用してきたはてなが、なぜ新たな開発言語としてScalaを選択したのかや、言語の変化が開発フローにどのような影響あたえたのかについて解説します。Scalaの言語自体にフォーカスするのではなく、Webアプリケーション開発にScalaを採用したメリットやデメリットを、Perlと比較しながら、Perlエンジニアの体験を通じて紹介します。

7e8bb5931a14030dc6a297aa364197bf?s=128

hakobe (Yohei Fushii)

August 29, 2014
Tweet

Transcript

  1. Scala in Perl Company

  2. hakobe hakobe932.hatenablog.com twitter.com/hakobe github.com/hakobe - 2008 ͸ͯͳΠϯλʔϯ - 2008 ~

    ͸ͯͳΞϧόΠτ - 2010 ~ ͸ͯͳΤϯδχΞ … → Hatena::Bookmark → Portal
 → Hatena::Blog → Mackerel
  3. • ΠϯλʔωοταʔϏεاۀ 2001~ • ΄΅͢΂ͯͷϓϩμΫτΛ Perl Ͱ࣮૷ • ͸ͯͳϒϩά/͸ͯͳϒοΫϚʔΫ/
 ͸ͯͳμΠΞϦʔ/ਓྗݕࡧ͸ͯͳ

    • ೝূ/՝ۚͳͲͷϙʔλϧػೳ • ࣾ಺πʔϧ
  4. Why Perl? in 2005 IUUQEIBUFOBOFKQOBPZB

  5. • গͳ͍هड़ྔͰଟ͘ͷ͜ͱ͕Ͱ͖ɺ
 ࣮ߦखॱ͕গͳ͘ɺࢼߦࡨޡ͠΍͍͢ • ๛෋ͳCPANϥΠϒϥϦ • ॆ࣮ͨ͠Web։ൃج൘ • ༏ΕͨϋοΧʔίϛϡχςΟ ৽͍͠΋ͷΛߴ଎ʹ૑Γग़ͤΔݴޠ

    Why Perl?
  6. ͦͯ͠೥ͷࡀ݄͕ྲྀΕͨʜ ͘Β͍

  7. • Webٕज़ͷਐԽ • εϚʔτϑΥϯͷීٴ • WebΞϓϦέʔγϣϯ΁ͷظ଴ਫ४ͷ޲্ • Ϣʔβʔͷ૿Ճ/มԽ • ϏδωεͷมԽ

    10೥ͷؒʹى͜ΔมԽ
  8. • ػೳ௥Ճ • ϦχϡʔΞϧ • όάϑΟοΫε • ηΩϡϦςΟ • ύϑΥʔϚϯεվળ

    • ֎෦มԽ΁ͷରԠ • ϦϑΝΫλϦϯά • ϥΠϒϥϦߋ৽ Ձ஋ΛੜΈग़͠ଓ͚Δʹ͸? ιϑτ΢ΣΞਐԽΛܧଓ͢Δ͜ͱ͕ॏཁ
  9. • ςετʹΑΔอޢ • ܧଓతΠϯςάϨʔγϣϯ • ιʔείʔυղੳʹΑΔࣗಈతͳมߋࢧԉ • ϨϏϡʔͷ࣮ࢪ • ஈ֊తͳมߋͱϦϦʔε

    • ։ൃϑϩʔͷ࠷దԽ Perl ͱιϑτ΢ΣΞਐԽ ҆શʹίʔυͷ௥Ճ΍มߋΛ͢ΔͨΊͷ޻෉
  10. IUUQTTQFBLFSEFDLDPNPOJTIJIBUFOBCMPH EFWFMPQNFOUqPX

  11. IUUQTTQFBLFSEFDLDPNTIJCBZV IBUFOBCVSPHVUJNVGBMTFLBJGBIVSPUPHJUIVC

  12. 1FSMͷ੩తղੳೖ໳ͱ 1FSMϦϑΝΫλϦϯάπʔϧ "QQ135ͷ͝঺հ CZIJUPEF ଟ໨తڭࣨd

  13. _人人人人人人人人人人人人人_ >�突然のランタイムエラー�< ‾Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y‾

  14. _人人人人人人人人人_ >�必須パラメータ忘れ�< ‾Y^Y^Y^Y^Y^Y^Y^Y‾ Use of uninitialized value in concatenation (.)

    or string at error.pl line 20. my $entry = Entry->new({ title => "hello, yapc", }); print("title: " . $entry->title); print("content:\n" . $entry->content); ΤϥʔͰ͸ͳ͍͕༧ظ͠ͳ͍ৼΔ෣͍
  15. Can't locate object method "scheme" via package
 "http://www.hatena.ne.jp"
 (perhaps you

    forgot to load "http://www.hatena.ne.jp"?)
 at error.pl line 13. sub check_url { my $url = shift; ! ... } check_url(“http://www.hatena.ne.jp") # ݩʑͷҙਤ check_url(URI->new(“http://www.hatena.ne.jp")) #ۮવಈ͘ sub check_url { my $url = shift; if ($url->schema eq 'https') { ... } Ҿ਺͸จࣈྻͷ͸͕ͣɺۮવ63*ΦϒδΣΫτͰ΋࢖͑ͨ _人人人人人人人人人人人_ >�$urlのメソッド呼び出し�< ‾Y^Y^Y^Y^Y^Y^Y^Y^Y‾ צҧ͍ͨ͠ਓ͕ʜ
  16. _人人人人人人人人人_ >�衝突に気づかずマージ�< ‾Y^Y^Y^Y^Y^Y^Y^Y‾ Can't locate object method "retrieve_by_id" via package

    "Entry" at error.pl line 21. Entry->retrieve_by_id(10); Entry->retrieve(id => 10); Entry->retrieve_by_id(20); Entry->retrieve_by_id(30); "͞Μ͕
 ϦϑΝΫλϦϯά #͞Μ͕
 ݺͼग़͠௥Ճ
  17. $user->name; ໊લมߋϦϑΝΫλϦϯά $user->display_name; <div>Α͏ͦ͜ɺ[% user.name %]͞Μ!</div> _人人人人人人人人人_ >�テンプレート修正わすれ�< ‾Y^Y^Y^Y^Y^Y^Y^Y‾ ςϯϓϨʔτͰ΋ࢀর͍͕ͯͨ͠ʜ

  18. • ࢥͬͯ΋Έͳ͍ݪҼͰΤϥʔ͕ى͖Δ • ςετͰ͔֬ΊΒΕΔ͔? - ૝ఆͰ͖ΔͳΒΤϥʔʹͳΒͳ͍ - ΧόϨοδΛߴΊΕ͹ྑ͍͕ɺ
 Ͳ͜·ͰίετΛ͔͚Δ? •

    ΤϯδχΞ͕ؤுͬͯίʔυΛ೺Ѳ
 Λ೺Ѳ͢Δ͔͠ͳ͍? Τϥʔݕ஌ͷݶք
  19. • ιϑτ΢ΣΞͷܧଓతͳਐԽ͸ඞਢ • ෳࡶԽͨ͠ιϑτ΢ΣΞΛΑΓ҆શʹ
 ֦ு/มߋ͍ͨ͠ • ݱঢ়ͷख๏Ͱ͸҆શੑͷ֬อ͕େม PerlʹΑΔେن໛։ൃͷ՝୊ ܧଓతͳιϑτ΢ΣΞਐԽͷ೉͠͞

  20. ৽ϓϩδΣΫτ։࢝ ೥ౙ

  21. • ͸ͯͳͷఏڙ͢Δαʔόʔ؅ཧαʔϏε • ௕೥࢖ΘΕ͖ͯͨࣾ಺޲͚ͷ
 αʔόʔ؅ཧπʔϧΛਖ਼ࣜαʔϏεԽ • ϩʔϧͱ͍͏֓೦ͰαʔόΛ·ͱΊͯ؅ཧ • ֤αʔόͰಈ࡞͢ΔΤʔδΣϯτ͕৘ใऩू IUUQNBDLFSFMJP

    ϕʔλఏڙதࠓळϦϦʔε༧ఆ
  22. None
  23. • ओʹاۀ޲͚Ͱɺ͸ͯͳIDΛ࢖Θͳ͍ • ଞαʔϏεͱͷίʔυͷڞ௨Խͷ
 ඞཁੑͳ͍ • ࣗࣾαʔϏεͳͷͰ
 εέδϡʔϧͷࣗ༝౓͕ൺֱతߴ͍ Mackerel։ൃͷഎܠ ৽ݴޠ౤ೖͷઈ޷ͷνϟϯε

  24. MackerelνʔϜ͕ٻΊͨ৽ݴޠ • MUST දݱྗͷߴ͍੩తܕγεςϜ • SHOULD ๛෋ͳϥΠϒϥϦ هड़ͷॊೈ͞؆ܿ͞ ࣾ಺ʹॻ͚Δਓ͕͍Δ Web։ൃͷ࣮੷

    ιϑτ΢ΣΞਐԽ ͷ҆શੑͷ໰୊ʹରॲ
  25. • ஋΍ؔ਺ͷఆٛʹܕΛهड़ • ίϯύΠϥͷνΣοΫͰ࣮ߦલʹ
 ܭࢉ͕ΤϥʔʹͳΒͳ͍͜ͱ͕Θ͔Δ • ྫ: จࣈྻʹରͯ͠URIͷϝιου
 ݺ΂ͳ͍͜ͱ͕Θ͔Δ ➡νΣοΫൣғ͸ݴޠͷදݱྗ΍ઃܭʹґଘ

    ੩తܕγεςϜ
  26. ‣ ྑ͍ - ඇৗʹߴػೳͳ੩తͳܕγεςϜ - ঢ়ଶ͕ͳ͍ϐϡΞͳੈք ‣ ͭΒ͍ - ࣾ಺ʹॻ͚Δਓ͕গͳ͍=νʔϜ࡞Εͳ͍

    ΑΖ͍͠ɺͳΒ͹Haskellͩ ϦʔυΤϯδχΞ͕)BTLFMMϑΝϯͳͷͰ
 ݁ߏՄೳੑ͸͋ͬͨ
  27. None
  28. • ΦϒδΣΫτࢤ޲/ؔ਺ܕͷ
 ϋΠϒϦουϓϩάϥϛϯάݴޠ • Martin Odersky (খా޷ઌੜ) • ߴػೳͳ੩తͳܕγεςϜ •

    JVM্Ͱಈ࡞/Javaͱͷޓ׵ੑ • Java/C̅/OCaml/Haskell ͳͲ͔ΒӨڹ
  29. Scalaͷίʔυͷ༷ࢠ object Hello extends App { for( i <- 0

    to 100 ) { println(message(i)) } ! def message(n: Int): String = if ( n % 7 == 0) { "lucky!" } else { "Hello, world!" } }
  30. Scalaͳཧ༝(1) දݱྗͷߴ͍੩తܕγεςϜ • ଟ༷ͳܕͷදݱ • ଟ૬ܕ(δΣωϦΫε) • ࿦ཧ࿨ܕ(trait) • ௚࿨ܕ

    (sealed trait) • ௚ੵܕ(case class) • ܕΫϥε(implicit parameter)
  31. ୅਺తσʔλܕΛఆٛͰ͖Δ • ୅਺తૢ࡞ʹΑͬͯఆٛ͞ΕΔܕ • ௚࿨ܕ΍௚ੵܕͷ૊Έ߹Θͤ • Option/Either/Try/List/Map ! • ྫ:ଘࡏ͠ͳ͍͔΋͠Εͳ͍஋(Option)

    val opt1: Option[Int] = Some(100) val opt2: Option[Int] = None opt1 match { Some(value) => s"value is $value !!" None => "no value" } VOEFGνΣοΫΛܕͰڧ੍
  32. Scalaͳཧ༝(2) • ܕͷ൥ࡶ͞Λ؇࿨ • ܕਪ࿦/ύλʔϯϚον • ֦ுՄೳͳจ๏ (macro) • ༏ΕͨίϨΫγϣϯϥΠϒϥϦ

    هड़ͷॊೈ͞؆ܿ͞ 1FSM.POHFST΋҆৺ͷॻ͖ͪ͜͝
  33. 100ΑΓখ͞ͳϑΟϘφον਺ - Perl my @nums = grep { $_ <

    100 } map { fib($_) } (0..30); ! sub fib { my $n = shift; return ($n == 0 || $n ==1) ? 1 : fib($n - 2) + fib($n - 1); }
  34. 100ΑΓখ͞ͳϑΟϘφον਺ - Scala val nums = (0 to 30) .map(

    fib(_) ) .filter( _ < 100) ! def fib(n: Int): Int = n match { case 1 | 0 => 1 case m => fib(m - 2) + fib(m - 1) } 1FSMͱൺֱͯ͠΋ಉ౳ʹγϯϓϧ
  35. ܕਪ࿦ʹཔΒͳ͍৔߹ val nums: Seq[Int] = (0 to 30) .map[Int, Seq[Int]]({

    n: Int => fib(n) }: Int => Int) .filter({ n :Int => n < 100}: Int => Boolean) ! def fib(n: Int): Int = n match { case 1 | 0 => 1 case m: Int => fib(m - 2) + fib(m - 1) } • ↑͋͑ͯͰ͖Δ͚ͩܕ஫ऍΛ௥Ճͯ͠Έͨ
  36. Scalaͳཧ༝(3) • Javaͷ࣮੷ͷ͋ΔϥΠϒϥϦ͕ॆ࣮ • ྫ:σʔλϕʔευϥΠό, ωοτϫʔΫ • Scala޲͚ͷϥΠϒϥϦ΋։ൃ͕ΞΫςΟϒ • PlayFramework/Scalatra/Skinny

    • Slick/ScalikeJDBC ! • ಋೖࣄྫͷ૿Ճ • Twitter/dwango/GREE/CyberAgent ๛෋ͳϥΠϒϥϦ Web։ൃͷ࣮੷
  37. Scalaͳཧ༝(4) • ࣗ෼Ͱษڧͯ͠Δਓ͕؍ଌ͞Ε͍ͯͨ • ։ൃ͕ਐΜͩ࣌ʹνʔϜ͕࡞ΕΔͷ͸େࣄ ࣾ಺ʹॻ͚Δਓ͕͍Δ

  38. • WebΞϓϦέʔγϣϯϑϨʔϜϫʔΫ • σʔλϕʔεΞΫηε • ϏϡʔͷϨϯμϦϯά • ։ൃ؀ڥ • ϩʔΧϧ؀ڥ/ςετͱϏϧυ/σϓϩΠ

    ScalaʹΑΔWeb։ൃͷ࣮ࡍ 1FSMΈ͍ͨʹ։ൃͰ͖Δͷ
  39. • Play Framework 2 • MVC WebϑϨʔϜϫʔΫ • ܕ҆શ/εςʔτϨε •

    ϞδϡϥϦςΟ͕ߴ͍ • Model΍ViewΛ؆୯ʹ੾Γସ͑ΒΕΔ WebΞϓϦέʔγϣϯϑϨʔϜϫʔΫ IUUQXXXQMBZGSBNFXPSLDPN
  40. ίϯτϩʔϥͷྫ package controllers // Ұ෦ུ object Application extends Controller {

    def index = Action { val message = "Hello, Play framework!!!" val langs = Seq("Perl", "Scala", "Go") Ok(views.html.index(message, langs)) } } GET / controllers.Application.index GET /list controllers.Application.list POST /create controllers.Application.create SPVUFT "QQMJDBUJPOTDBMB
  41. • twirl - Play෇ଐͷςϯϓϨʔτΤϯδϯ ϏϡʔͷϨϯμϦϯά @(message: String, langs: Seq[String]) <!DOCTYPE

    html> <html> <body> <h1>@message</h1> <ul> @for( lang <- langs ) { <li>@lang</li> } </ul> </body> </html>
  42. ίϯτϩʔϥͷྫ: ϑΥʔϜΛॲཧ def create2 = DBAction { implicit rs =>

    val form = Form( tuple( "title" -> nonEmptyText, "content" -> nonEmptyText ) ) ! form.bindFromRequest().fold( formWithErrors => { BadRequest("has form error") }, values => { Entries.create(values._1, values._2) Redirect(controllers.routes.Application.list) } ) } } GPSNͷ஋ͷ ܕΛࢦఆ JNQMJDJUͳϦΫΤε τ͔Β஋ΛCJOE
  43. def create2 = DBAction { implicit rs => val form

    = Form( tuple( "title" -> nonEmptyText, "content" -> nonEmptyText ) ) ! form.bindFromRequest().fold( formWithErrors => { BadRequest("has form error") }, values => { Entries.create(values._1, values._2) Redirect(controllers.routes.Application.list) } ) } } ίϯτϩʔϥͷྫ: ϑΥʔϜΛॲཧ ஋͕औΓग़ͤΔ͔Ͳ͏ ͔ʹԠͨ͡ॲཧ ಘΒΕͨσʔλͰॲཧ ϦμΠϨΫτ શମͷฦ٫஋͸3FTVMUܕ
  44. • Slick • Functional Relational Mapping • ScalaͷίϨΫγϣϯૢ࡞ͷΑ͏ͳίʔυͰ
 SQLΛൃߦ (ܕ҆શੑΛߟྀ)

    • SQLΛ௚઀ॻ͘͜ͱ΋Ͱ͖Δ • ։ൃ͕ΞΫςΟϒ(TypeSafeࣾ) σʔλϕʔεΞΫηε IUUQTMJDLUZQFTBGFDPN
  45. Slick: ςʔϒϧͷఆٛ: SQL CREATE TABLE entries ( id bigint(20) NOT

    NULL AUTO_INCREMENT, title varchar(255) NOT NULL, content text NOT NULL, PRIMARY KEY (id) );
  46. Slick: ςʔϒϧͷఆٛ: Scala case class Entry( id: Option[Int],ɹtitle: String, content:

    String) ! object Tables { class Entries(tag: Tag) extends Table[Entry](tag, "entries") { def id = column[Int]("id", O.PrimaryKey, O.AutoInc) def title = column[String]("title") def content = column[String]("content") def * = (id.?, title, content) <> (Entry.tupled, Entry.unapply) } val entries = TableQuery[Entries] } 4DBMBͱ֎քͷ઀఺Ͱ͸ ͘Θ͘͠ܕΛॻ͘
  47. Slick: SQLͷൃߦ: SELECT val query = for ( entry <-

    Tables.entries ) yield entry query.sortBy(_.id.desc).take(10).list SELECT * FROM entries ORDER BY id DESC LIMIT 10 • Scala ͷ for จͷৼΔ෣͍͸flatMap/ map/filterϝιουͳͲͷ࣮૷ʹґଘ
  48. Slick: SQLͷൃߦ: INSERT Tables.entries += Entry(None, title, content) INSERT INTO

    entries (title, content) VALUES (?, ?);
  49. Slick: SQLͷൃߦ: UPDATE val query = for ( entry <-

    Tables.entries if entry.id === id ) yield (entry.title, entry.content) query.update(title, content) UPDATE entries SET title = ?, content = ? WHERE id = ?;
  50. Slick: SQLͷൃߦ: DELETE val query = for ( entry <-

    Tables.entries if entry.id === id ) yield entry query.delete DELETE FROM entries WHERE id = ?;
  51. • Play FrameworkͷϩʔΧϧ։ൃ
 αʔόػೳΛ׆༻ • ϑΝΠϧߋ৽Ͱαʔό࠶ಡΈࠐΈ • sbt: Scala Build

    Tool Ͱ࣮ߦ ϩʔΧϧͰͷ։ൃ $ sbt #ϏϧυπʔϧΛৗறىಈ > compile > test > run # localhostͰαʔό͕ىಈ
  52. ։ൃऀͷ؀ڥ 04 ΤσΟλ Ϗϧυͷ࣮ߦ IBLPCF .BD *OUFMMJ+  *EFB7JN TCU

    "͞Μ .BD *OUFMMJ+  *EFB7JN TCU #͞Μ .BD  -JOVY 7. &NBDT TCU $͞Μ 8JOEPXT  -JOVY 7. &NBDT TCU *%&ͷར༻͸ඞਢͰ͸ͳࣗ͘༝ʹ։ൃ
  53. • ߴػೳͳίʔυิ׬ • ࣗಈϦϑΝΫλϦϯά • ఆٛ΍ར༻Օॴ΁δϟϯϓ • ϥΠϒϥϦͷίʔυ΋OK • ਪ࿦͞Εͨܕ΍Ҿ਺ͷπʔϧνοϓ

    ͱ͸͍͑IDE͸ศར
  54. • JenkinsΛར༻ • ςετͱϏϧυ • Ϗϧυ: ຊମ/ϥΠϒϥϦ/ىಈεΫϦϓτΛ
 ؚΜͩJARϑΝΠϧΛ࡞੒͢Δ • ฒྻ࣮ߦͯ͠ߴ଎Խ

    • Gitͱ࿈ܞͯࣗ͠ಈ࣮ߦ • feature branch: pushͰςετ • staging/master: 
 pushͰςετ&Ϗϧυ&։ൃαʔόʹσϓϩΠ ςετͱϏϧυ
  55. • σϓϩΠ • CapistranoʹखΛ͍Εͯར༻ • Jenkins͕࡞ͬͨϏϧυ(JARϑΝΠϧ)Λ scpͰσϓϩΠର৅ͷαʔό܈ʹίϐʔ • αʔόͰͷಈ࡞ •

    JARϑΝΠϧΛdaemontoolsͰ࣮ߦ • JVMͷىಈ͕஗͍ͨΊ
 Ұ౓ʹ࠶ىಈ͸ͤͣҰ୆ͣͭ σϓϩΠ
  56. • ίʔυͷมߋ΍͕҆৺ • มߋͨ͠ΒίϯύΠϧ͕௨Δ·Ͱमਖ਼ • ໊લ΍γάχνϟͷมߋ࿙Ε͕ͳ͍͜ͱ͕࣮֬ʹ Θ͔Δ • ϨϏϡʔ͕҆৺ •

    มߋ࿙Εͷ৺഑͕ͳ͍ͷͰػೳʹूத • ॊೈͰߴػೳͳจ๏ • ॻָ͍͍ͯͯ͠/TIMOTWTDIײ͕͋Δ • ؔ਺ܕϓϩάϥϛϯάٕज़Λ׆༻Ͱ͖Δ Scalaͷίί͕࠷ߴ
  57. • ίϯύΠϧ͕࣌ؒ௕͗͢Δ • ϑϧίϯύΠϧ: 3෼ • ։ൃϑϩʔʹগͳ͔ΒͣӨڹ • ݴޠػೳ͕๛෋ֶ͗ͯ͢शίετߴ͍ •

    Javaք۾ͷ஌͕ࣝΘ͔Βͳͯͭ͘Β͍ Scalaͷίί͕ͭΒ͍
  58. None
  59. • Mackerel: ϑϧίϯύΠϧ3෼ʙ • ීஈͷ։ൃ͸ࠩ෼ίϯύΠϧ • ϒϥϯνΛ੾Γସ͑Δͱ… • ։ൃͷϦζϜ͸มԽ •

    ίϯύΠϧதʹίʔυಡΉ/ϨϏϡʔ • ߴ଎Խͷ༨஍͸͋Δ • Ϟδϡʔϧ෼ׂ/ฒྻԽ • ଎͍ϚγϯΛങ͏ ίϯύΠϧ͕࣌ؒ௕͗͢Δ
  60. • ݴޠ͕ෳࡶͰແݶʹֶ΂Δ • ೔ຊޠͷ͍͍ຊ͕ͪΐͬͱݹ͍ (2011೥) • Scalaεέʔϥϒϧϓϩάϥϛϯάୈ2൛ • ϓϩάϥϛϯάScala •

    ϑϨʔϜϫʔΫͷίʔυΛಡΜͰֶश
 (͍͍༸ॻ΋͋ΔΒ͍͠) ֶशίετ͕ߴ͍
  61. • ςετ͕͋ͬͨΒܕ͸ෆཁͳͷͰ͸? • ܕਪ࿦͋ͬͯ΋ܕΛॻ͘ͷ͸໘౗Ͱ͸? • JavaͷϥΠϒϥϦͬͯ࢖͍ʹ͘͘ͳ͍? • ৽نαʔϏεʹ͸Perlͷ΄͏͕ྑ͍ͷͰ͸? • ͸ͯͳ͸͜Ε͔ΒScalaͰ͍͘ͷ?

    • Ϟφυͱ͔͕͜Θ͍ FAQ
  62. • HatenaͰ͸ιϑτ΢ΣΞਐԽΛ҆શʹߦ͏
 ͜ͱʹʹ՝୊ҙࣝ • MackerelͰ৽ٕज़Λಋೖ࣌ʹݴޠ΋ݕ౼ • ੩తͳܕγεςϜͱPerl࢖͍ʹ΋҆৺ͷ
 ॻ͖΍͢͞ͳͲͰScalaʹબ୒ • ܕγεςϜ͸࠷ߴ͚ͩͲ՝୊΋͋Γ

    ·ͱΊ
  63. Mackerel͕࠾༻͢Δٕज़ .BDLFSFM 1FSM1SPEVDUT ΞϓϦέʔγϣϯ αʔό 4DBMB
 1MBZ'SBNFXPSL 1FSM
 ࣾ಺ϑϨʔϜϫʔΫ ϑϩϯτΤϯυ

    +BWB4DSJQU
 "OHVMBS+4 +BWB4DSJQU σʔλϕʔε 1PTUHSF42- .Z42- ΤʔδΣϯτ (P 
  64. We are hiring!

  65. • ͔֬ΊΔର৅͕ҧ͏ • ςετ: ϓϩάϥϜͰॻ͚ΔൣғͳΜͰ΋ • ܕ : ܕͰදݱͰ͖Δൣғ !

    • ͔֬ΊΔࣄ࣮͕ҧ͏ • ςετ:ظ଴Ͳ͓ΓϓϩάϥϜ͕ಈ͘͜ͱ • ܕ :Τϥʔ͕ଘࡏ͠ͳ͍͜ͱ ςετ͕͋Ε͹ܕ͸ෆཁ?