以下のようなスプレッドシートから、適宜バリデーションなどを行いつつArticle(記事)モデルを生成することを目指します。
執筆者に関して、ArticleモデルはEditor(執筆者)モデルとの関連を持っているものとします。
Image may be NSFW. Clik here to view.
最低限のバリデーションは、スプレッドシート側で行う
例えば日時など、一定の書式で縛りたい値がある場合、Googleスプレッドシートはエクセル同様、入力された値の書式の検証をすることができます。
メニューから「データ → 検証」を選択し、検証したい書式を設定すれば、特定の行列で異常な値を入力できないようにしたり、警告を表示させることができます。
Image may be NSFW. Clik here to view.
形としてはいわゆるBFF(Backend for frontends)パターンに近いのですが、
クックパッドでは様々なデバイスに対応するためというよりは、同じドメインモデルを別バージョンで提供するようなケースで使われています。
OEM版がその例で、根本的には同じものを提供するが、UIが別バージョンだったりアカウント体系が異なるものを提供します。
Geo-filters are expensive — they should be used on as few documents as possible. First remove as many documents as you can with cheaper filters, like term or range filters, and apply the geo-filters last.
JS 製のデータ管理用ライブラリです。RESTful API などを通じて取得できるデータ(リソース)を抽象化して、CRUD 操作を統一したインターフェースで行えるようにしてくれます。
リソースごとにオブジェクト(モデル)を定義したり、findでデータを取ってくるなど、ActiveRecord などの O/R マッパのような使い勝手が特徴。設計等には Ember data の影響を受けています。
以下で、基本的な使い方を見てみましょう。
API などを通じて読み込まれたデータは一旦データストアと呼ばれるオンメモリキャッシュに格納されます。
一度読み込んだデータはストア内から呼び出し、Update, Delete などの更新系操作のタイミングでサーバにデータを書き戻すというわけです。
例 - Book リソース
例として、一冊の本を表す Book リソースを定義してみましょう。
// データストアを作成var store = new JSData.DS();
// 元データの参照元として HTTP (Web API) を指定する
store.registerAdapter('http', new DSHttpAdapter(), {default: true});
// データストア上に Book リソースを定義var Book = store.defineResource({
name: 'book', // リソース名
endpoint: 'books'// 対応する API のエンドポイント});
RESTful API の準備
上記のように定義したリソースオブジェクトを使うには、操作を実際に行うための Web API も用意してやる必要があります。リソース定義には endpointという API のエンドポイントの情報しか含まれていませんが、その URL に json オブジェクトを返却する RESTful な API を定義しておけば、js-data が自動的に叩いてくれるようになっています。
定義しておく操作
以下のような API が存在することが期待されています。必ずしも全部実装しておく必要はありません。使用したいものだけで OK です。
Daniel Eggert氏は既存のObjective-CのCoreDataのAPIをプロトコルとエクステンションを使ってモダンなのSwiftのインターフェイスを作りました(Modern Core Data)。
Daniel H Steinberg氏はBlending Culturesでオブジェクト指向と関数型とプロトコルという3つの世界を一緒に合わせてそれぞれの特徴を使えることについて話しました。
Chris Eidhofのライブコーディングセッションでは view controllerからconfigurationオブジェクトとしてカスタム部分を抜きだし、複雑さを下げる方法が紹介されました。Swiftの関数は第一級オブジェクトなのでそういうconfigurationにカスタムロジックを入れることができます。この仕様を作ったら一つの複雑なview controllerではなくて汎用のview controllerとテストしやすい設定を分けることができます。
Cross-platformとオープンソースSwiftの流行り
Swiftのオープンソース化のおかげで一般のエンジニアはその新規言語の方向を決められます(Jesse Squires, Contributing to Open Source Swift)。LinuxでもSwiftの開発ができます。try! Swiftの発表には、サーバーサイドSwiftに関する発表(Soaring Swiftly - Server Side Swift - Caesar Wirth)、Linuxでの開発で起こる問題(Practical cross-platform - JP Simard)についての話もありました。今現在、一番不便なのはObjective-Cのダイナミックランタイム、そしてダイナミックランタイムで使えるキャストかGrand Central Dispatchがないことです。それでcross-platformを作るなら:
#if os(OSX)
// ダイナミックランタイム機能を使う
#else // Linux
// なんとかする
#endif
みたいなひどいコードが多くなります。
Swiftでモバイル以外の開発はまだまだなので必要なツールが少ないです。だからプログラミングしやすくできるようにツール、またはCIツールを開発する機会があります(池田翔 - Dive in Swift Ecosystem)。自分で新しいライブラリを立ち上げる(Creating a Swift Library by Jeff Hui)か、それとも他のエンジニアに便利なツールを作るか色々な貢献のチャンスがあります。
皆さんは Web アプリやモバイルアプリを開発する時、モックアップ作成にどれだけ時間を割いているでしょうか?もしくはモックアップを作成せずにすぐに実装に入るでしょうか?私はこれまで Web アプリ開発ではいきなり実装に入ることが多かったのですが、Holiday iOS アプリの開発では Web アプリの時のように上手くいかないことに気づき、やり方を考え直しました。iOS アプリ開発の過程で、モックアップ作成や実装をどのように捉えるか、具体的にどう行うか、ということが自分なりに見えてきたので、それらについてご紹介します。
目的は、価値のあるプロダクトを速くユーザの手に届けること
Web アプリやモバイルアプリの開発過程においてモックアップなどを作る目的は、あくまでも ユーザに届くプロダクトの価値を高めてそれを速くリリースすることです。適切な前準備は、やろうとしていることが価値があるのかどうか、またその価値が伝わるのかどうか、ということに実装前の早い段階で気づくことができるというメリットがあります。重要なことは、 モックアップや実際のプロダクトなどを作ることによって確かめられる仮説検証の精度と、それを作る時間はトレードオフの関係にあるということです。そのため、モックアップなどを作る際には、本当に作るべきなのか、もしくはどこまで作りこむのかということを意識する必要があります。
Web アプリとモバイルアプリの実装コストの違い
Web アプリとモバイルアプリの開発をどちらもやっていて気づいたことは、ほとんどの場合、モバイルアプリは Web アプリよりも UI の実装や調整に時間がかかるということです。主な理由としては、モバイルアプリが下記のような特性を持つからだと考えられます。
プロトタイプの精度と作成にかかる時間のバランスを考えた時、個人的に一番しっくりきて活用しているのが Flinto for Macです。作成可能なプロトタイプの幅が多く、かつプロトタイプを作るエディタが非常に使いやすいため、多くの場合で十分な精度のプロトタイプを素早く作ることができます。
Holiday iOS アプリの開発では、作る機能ごとに必要に応じて Sketch で画面を作り、その画面のパーツを使って Flinto for Mac でプロトタイプを作成しています。実装前にリアルなインタラクションを気軽に何パターンも試すことができるため、頭の中のイメージやラフスケッチから実装に入ったり、Sketch でモックを作成したあとすぐに実装に入るよりも手戻りが少なくなり、結果としてかかる合計の時間が短くなる場合が多いです。
<?xml version="1.0" encoding="UTF-8" standalone="no"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"version="1.2"xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd"><file original="Global/SupportingFiles/en.lproj/Localizable.strings"source-language="en"datatype="plaintext"><header><tool tool-id="com.apple.dt.xcode"tool-name="Xcode"tool-version="7.3"build-num="7D175"/></header><body><trans-unit id="application_config.new_version_available.button_title"><source>Open in App Store</source><note>No comment provided by engineer.</note></trans-unit><trans-unit id="application_config.new_version_available.message"><source>A new version is available in the App Store. Please update before continuing to use the app.</source><note>No comment provided by engineer.</note><note>No comment provided by engineer.</note></trans-unit>(省略)
</body></file></xliff>
上記の処理は次のスライドを見てもらうとイメージが付きやすいと思います。太いエッジは、右側のノード(単語)にとって累積コストが最小になるパスを意味しています。
左文脈 ID、右文脈 ID は特殊な使い方をしない限りは品詞 ID のようなものと理解しておけば大丈夫です。前件文脈 ID は連接する左側の単語の右文脈 ID、後件文脈 ID は右側の単語の左文脈 ID です。
# CHARACTER CATEGORY DEFINITION
#
# CATEGORY_NAME INVOKE GROUP LENGTH
#
# - CATEGORY_NAME: Name of category. you have to define DEFAULT class.
# - INVOKE: 1/0: always invoke unknown word processing, evan when the word can be found in the lexicon
# - GROUP: 1/0: make a new word by grouping the same chracter category
# - LENGTH: n: 1 to n length new words are added
#
DEFAULT 0 1 0 # DEFAULT is a mandatory category!
SPACE 0 1 0
KANJI 0 0 2
SYMBOL 1 1 0
NUMERIC 1 1 0
ALPHA 1 1 0
HIRAGANA 0 1 2
KATAKANA 1 1 2
KANJINUMERIC 1 1 0
GREEK 1 1 0
CYRILLIC 1 1 0