├── API--Design.md ├── API--JSONBatch.md ├── API--JSONPatch.md ├── API-JSONRPC.md ├── AWS--Tuning.md ├── Action.md ├── Admin.md ├── Analytics.md ├── Android--AccountManager.md ├── Android--Annotation+AspectJ.md ├── Android--Annotation.md ├── Android--Tools.md ├── Android--UITesting.md ├── Android--gradle-library ├── Android-BackgroundTasks.md ├── AndroidDev.md ├── AppLinks.md ├── AppMarketing.md ├── Asking.md ├── AspectOrientedProgramming.md ├── CSS--maintainable.md ├── CSS--typography.md ├── Convenience-Badge.md ├── DESIGN--font-fallbacks.md ├── DESIGN--font.md ├── DESIGN--resource.md ├── Design--CommonClasses.md ├── Design--Designdoc.md ├── Design--Flux.md ├── Design--GoodCode.md ├── DevFlowSpec.md ├── GAE.md ├── GAEJ.md ├── GameDev--Resources.md ├── Go--beego.md ├── Go.md ├── Good-Code.md ├── Haxe.md ├── ImageCompression.md ├── Java--AppEngine.md ├── Java--SpringMVC.md ├── Java--gradle.md ├── KPI.md ├── Management--DRI.md ├── Marketing--iOS.md ├── MobileDev--Architecture.md ├── Others--ID-generating.md ├── PDCA.md ├── Phaser.md ├── README.md ├── Recruit.md ├── Scraping--BestPractices.md ├── Scraping--Scrapy.md ├── Team--Performance.md ├── Test--AppThwack.md ├── Test--Saucelabs.md ├── Test--list--BDDmatchers.md ├── The-Art-of-Documentation.md ├── UI--prototyping.md ├── UX--Sync.md ├── UX--minbox.md ├── Web--Test.md ├── Web--VirtualDOM.md ├── i18n--Policy.md ├── i18n.md ├── iOS--ALAssets-NotFound.md ├── iOS--ALAssetsLibrary-iOS8-Compatibility.md ├── iOS--Analytics.md ├── iOS--App-Extensions.md ├── iOS--AppAnalytics.md ├── iOS--AppPreview.md ├── iOS--AppStore.md ├── iOS--AppleDoc.md ├── iOS--Architecture.md ├── iOS--Aspect.md ├── iOS--BLE.md ├── iOS--BestPractices-Objective-C.md ├── iOS--CommonErrors.md ├── iOS--Concurrency.md ├── iOS--CoreData-Batch.md ├── iOS--Design--BestPractices.md ├── iOS--DeviceAPI.md ├── iOS--LocalNotification.md ├── iOS--MemoryLeak.md ├── iOS--MemoryManagement.md ├── iOS--NSOperation.md ├── iOS--OverTheAir.md ├── iOS--PHAsset,ALAssetのカメラロールへの書き込み時にメタデータを追記.md ├── iOS--Perf.md ├── iOS--Permissions.md ├── iOS--PonyDebugger.md ├── iOS--PrivatePod.md ├── iOS--ReactiveCocoa.md ├── iOS--Resources.md ├── iOS--SQLite.md ├── iOS--Safari-CreditCard.md ├── iOS--SettingsBundle.md ├── iOS--Share-UIActivityViewController ├── iOS--Testing--TestDouble.md ├── iOS--Testing.md ├── iOS--Today-Extension.md ├── iOS--Tools.md ├── iOS--UICollectionView.md ├── iOS--UIWebView-Native.md ├── iOS--WebView.md ├── iOS--i18n.md ├── iOS--pod-library.md ├── iOS--workflow.md ├── iOS-CI.md ├── iOSDev.md ├── libGDX.md └── protocol-buffers.md /API--Design.md: -------------------------------------------------------------------------------- 1 | API デザイン (kaiinui/api_design-resources から移動) 2 | ==================== 3 | 4 | - [Web API 設計のベストプラクティス集 Web API Design](http://d.hatena.ne.jp/cou929_la/20130121/1358776754) 5 | - [Web API Design](http://offers.apigee.com/web-api-design-ebook/) 6 | - [Heroku HTTP API Design Guide](https://github.com/interagent/http-api-design) - Heroku でまとめられた、API のデザイン指針 7 | - [《REST思想》と《リソース指向》と《Webページ》に関する(主にRailsの)話](http://qiita.com/tkawa/items/9bd50e80cfe354062dfb) - よい URL とは? REST とリソース指向から読み解くURL 8 | - [アジャイルAPI設計時代の到来!?APIデザインの極意を読みました。](http://kozake.hatenablog.com/entry/2014/08/03/232443) - ヤバい API 本 9 | - [すべてがJSONになる](http://r7kamura.hatenablog.com/entry/2014/06/10/023433) - JSON Schema を利用して、Validation や Doc, API Client を自動的に用意する 10 | - [NetflixのAPIプラットフォーム](http://wazanova.jp/items/1114) - フロントエンドチームが API をカスタマイズできるようにしている 11 | - [モバイルAPIデザインのまとめ](http://wazanova.jp/items/1283) - Etsy での API デザイン。モバイルのために、如何に必要な API コール回数を減らすかを考える。 12 | - [\[その1\] Netflix: APIの改善と継続的デリバリー](http://wazanova.jp/items/678) - Netflix は如何に 800 種のデバイスに利用される API を運用しているのか? 13 | - [Ruby RoguesメンバとiOSエンジニアのAPI議論](http://wazanova.jp/items/1211) - 一貫性、ドキュメント、モバイル 14 | - [APIデザインの極意 Java/NetBeansアーキテクト探究ノート](http://hamasyou.com/blog/2014/08/30/484433591x/) 15 | - [jsonapi.org](http://jsonapi.org/format/) 16 | 17 | Authentication 18 | --- 19 | 20 | おおよそ以下のような方法がある 21 | 22 | - Basic Authentication (Unrecommended) 23 | - OAuth 2.0 24 | - Basic Auth & temporary access token 25 | - SSH Key Pair (!!!) 26 | 27 | 決定版は OAuth 2.0 って感じ。「外部に公開する API」と「内部的に利用する API」の違いはあるけども。 28 | 29 | ただし、OAuth 2.0 はやたら実装が複雑になる。 30 | 31 | #### References 32 | 33 | - http://apiux.com/2013/03/21/authentication-dont-be-clever/ 34 | - http://www.infoq.com/news/2010/01/rest-api-authentication-schemes 35 | - http://hamasyou.com/blog/2010/11/18/api-rest/ 36 | - Security - いろいろなサービスのAPIをcurlで叩くときの認証の扱い - Qiita : http://qiita.com/hash/items/ebcdb5135c4a42001f02 37 | 38 | Batch Request 39 | --- 40 | 41 | [モバイルAPIデザインのまとめ](http://wazanova.jp/items/1283) でも触れられていた通り、如何にリクエストを減らすか。 42 | Etsy では API エンドポイントをモバイルチームで改造出来るようにしている。 43 | 44 | もう少し汎用的には、JSON-RPC Batch 2.0 のような方法は、解決策の一つになり得る。 45 | 46 | Etsy のような(あるいは API エンドポイントを特定アプリに特化させる)アプローチでは API のエンドポイントとクライアントが密結合になりやすい(まあ、なっても別にいいけど) 47 | 48 | なので、"A & B & C" を渡す API 、とエンドポイントを特化させるのではなく、リクエストする側が "A と B と C" をくれ!とやる作戦。 49 | 50 | - [モバイルアプリとAPIのありかたを考える2014](https://speakerdeck.com/ar_tama/mobairuapuritoapifalsearikatawokao-eru2014) - JSON-RPC Batch 2.0 について言及 51 | - [Facebook の Batch Request](https://developers.facebook.com/docs/graph-api/making-multiple-requests) 52 | - [Google Cloud Storage の Batch Request](https://developers.google.com/storage/docs/json_api/v1/how-tos/batch) 53 | - [AWS Product Advertising API の Batch Request](http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BatchRequests.html) 54 | - [Rails gem: batch_api](https://github.com/arsduo/batch_api) - Facebook の Batch Request みたいな API エンドポイントを切れる gem. 55 | 56 | ```json 57 | # POST /batch 58 | # Content-Type: application/json 59 | 60 | { 61 | ops: [ 62 | {method: "get", url: "/patrons"}, 63 | {method: "post", url: "/orders/new", params: {dish_id: 123}}, 64 | {method: "get", url: "/oh/no/error", headers: {break: "fast"}}, 65 | {method: "delete", url: "/patrons/456"} 66 | ], 67 | sequential: true 68 | } 69 | ``` 70 | 71 | ```json 72 | { 73 | results: [ 74 | {status: 200, body: [{id: 1, name: "Jim-Bob"}, ...], headers: {}}, 75 | {status: 201, body: {id: 4, dish_name: "Spicy Crab Legs"}, headers: {}}, 76 | {status: 500, body: {error: {oh: "noes!"}}, headers: {Problem: "woops"}}, 77 | {status: 200, body: null, headers: {}}} 78 | ] 79 | } 80 | ``` 81 | 82 | JSON-RPC Batch 2.0 崩れのようなリクエスト。だけども実際的で良いと思う。中身は RESTful な routing. 83 | 実際的には単一のリクエストも route を切りつつ、`/batch` とかでバッチリクエストを JSON-RPC (風) に受けるのが良いと思った。 84 | 85 | ただし、一挙にリクエストを受ける都合上レスポンスが遅くなりがちな問題がある。 86 | 87 | Response, [Chunked Transfer Encoding](http://en.wikipedia.org/wiki/Chunked_transfer_encoding) のような受け方をする必要があるのかもしれない。 88 | 89 | Pagination 90 | --- 91 | 92 | [Using the Graph API](https://developers.facebook.com/docs/graph-api/using-graph-api/v2.1) 93 | 94 | ```json 95 | { 96 | "data": [ 97 | ... Endpoint data is here 98 | ], 99 | "paging": { 100 | "cursors": { 101 | "after": "MTAxNTExOTQ1MjAwNzI5NDE=", 102 | "before": "NDMyNzQyODI3OTQw" 103 | }, 104 | "previous": "https://graph.facebook.com/me/albums?limit=25&before=NDMyNzQyODI3OTQw" 105 | "next": "https://graph.facebook.com/me/albums?limit=25&after=MTAxNTExOTQ1MjAwNzI5NDE=" 106 | } 107 | } 108 | ``` 109 | 110 | [Instagram API Endpoints](http://instagram.com/developer/endpoints/) 111 | 112 | `The envelope`: API レスポンスのフォーマット。 Instagram の API レスポンスは全て envelope 形式。 113 | 114 | ```json 115 | { 116 | "meta": { 117 | "code": 200 118 | }, 119 | "data": { 120 | ... 121 | }, 122 | "pagination": { 123 | "next_url": "...", 124 | "next_max_id": "13872296" 125 | } 126 | } 127 | ``` 128 | 129 | ##### Meta 130 | 131 | ```json 132 | { 133 | "meta": { 134 | "error_type": "OAuthException", 135 | "code": 400, 136 | "error_message": "..." 137 | } 138 | } 139 | ``` 140 | 141 | #### Data 142 | 143 | 普通の `body` 144 | 145 | #### Pagination 146 | 147 | ```json 148 | { 149 | ... 150 | "pagination": { 151 | "next_url": "https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296", 152 | "next_max_id": "13872296" 153 | } 154 | } 155 | ``` 156 | 157 | Formats 158 | --- 159 | 160 | ### Request 161 | 162 | 当たり前だけど GET は URL params で。 `(e.g.) ?user_id=hogehoge&password=hogehoge` 163 | 164 | POST の場合は Body に何でも詰め込めるので後述のデータ構造を全て利用出来る。 165 | 166 | ### Response 167 | 168 | 基本的には Dictionary 的なデータ構造で返す。(つまり JSON みたいなやつ) 169 | 170 | - JSON 171 | - MessagePack 172 | - Binary plist 173 | - JSONP (まあ。) 174 | 175 | Binary plist については、これを使って iOS での高速化を果たした報告が有る(http://tech.vasily.jp/backend_ios_plist/) 176 | 177 | あるいは XML のようなメタ情報をたくさん詰め込めるフォーマットを使っても良い。(が、大体 JSON みたいな使い方をされる) 178 | 179 | - XML 180 | 181 | 前者 4 つはフォーマットの違いでしかないので、透過的に扱える限りは全て返せるようにしたほうが良い感じ。(XML はもう少し扱える範囲が大きいと思う) 182 | どうせ Dictionary を食わせて生成するのだから、少しの努力で大体何でも返せる。 183 | 184 | それぞれの端末で一番良い方法で受け取ってもらうのが一番良いと思う。 185 | 186 | 当たり前だけど gzip は必ずする。 187 | 188 | Try-able API Document (Console) 189 | --- 190 | 191 | instagram とか Facebook とかは「試せる」API ドキュメントを提供している。 192 | これは、API を利用する側にとっては気軽に試すことが出来て大きいコトと思う。 193 | (もちろん 1. API ドキュメントが整備されている 2. API クライアントライブラリ実装がある ことが一番。) 194 | 195 | - https://apigee.com/console/instagram 196 | - https://developers.facebook.com/tools/explorer/ 197 | - http://petstore.swagger.wordnik.com/ 198 | 199 | このような API コンソールを提供するツールとしては、 200 | 201 | - [apigee](https://apigee.com/) 202 | - [Swagger UI](https://github.com/wordnik/swagger-ui) 203 | 204 | がある。 205 | 206 | API Documentation 207 | --- 208 | 209 | #### references 210 | 211 | - [Stripe API Doc](https://stripe.com/docs/api) 212 | - [Apiary](http://apiary.io/) 213 | - [How do you document your APIs?](http://www.infoq.com/research/api-documentation) 214 | - [Swagger](https://helloreverb.com/developers/swagger) 215 | - [apigee](http://apigee.com/docs/console-go/content/set-apigee-api-console) 216 | - [RAML tools](http://api-portal.anypoint.mulesoft.com/raml-tools?ref=apihub) 217 | - [RAML](http://raml.org/) 218 | 219 | Tools 220 | --- 221 | 222 | - [Apiary](http://apiary.io/) - API Blueprint というスキーマから、Validation や Doc などを生成 223 | - [Swagger UI](https://github.com/wordnik/swagger-ui) - JSON から「試せる API Doc」を生成 224 | - [prmd](https://github.com/interagent/prmd) - JSON Schema を色々出来るツール by Heroku 225 | - [RESTX](http://restx.io/) - REST endpoint, testing, docmentation 226 | 227 | References 228 | --- 229 | 230 | - AWS - DynamoDB HTTP API が独特な仕様なので紹介 - Qiita : http://qiita.com/voluntas/items/a3ee5b0e2843d589d45f 231 | -------------------------------------------------------------------------------- /API--JSONBatch.md: -------------------------------------------------------------------------------- 1 | API Batch Request 2 | === 3 | 4 | [モバイルAPIデザインのまとめ](http://wazanova.jp/items/1283) でも触れられていた通り、如何にリクエストを減らすか。 5 | Etsy では API エンドポイントをモバイルチームで改造出来るようにしている。 6 | 7 | もう少し汎用的には、JSON-RPC Batch 2.0 のような方法は、解決策の一つになり得る。 8 | 9 | Etsy のような(あるいは API エンドポイントを特定アプリに特化させる)アプローチでは API のエンドポイントとクライアントが密結合になりやすい(まあ、なっても別にいいけど) 10 | 11 | なので、"A & B & C" を渡す API 、とエンドポイントを特化させるのではなく、リクエストする側が "A と B と C" をくれ!とやる作戦。 12 | 13 | ``` 14 | # POST /batch 15 | # Content-Type: application/json 16 | ``` 17 | ```json 18 | { 19 | "ops": [ 20 | {"method": "get", "url": "/patrons"}, 21 | {"method": "post", "url": "/orders/new", "params": {"dish_id": 123}}, 22 | {"method": "get", "url": "/oh/no/error", "headers": {"break": "fast"}}, 23 | {"method": "delete", "url": "/patrons/456"} 24 | ], 25 | "sequential": true 26 | } 27 | ``` 28 | 29 | ```json 30 | { 31 | "results": [ 32 | {"status": 200, "body": [{"id": 1, "name": "Jim-Bob"}, ...], "headers": {}}, 33 | {"status": 201, "body": {"id": 4, "dish_name": "Spicy Crab Legs"}, "headers": {}}, 34 | {"status": 500, "body": {"error": {"oh": "noes!"}}, "headers": {"Problem": "woops"}}, 35 | {"status": 200, "body": null, "headers": {}}} 36 | ] 37 | } 38 | ``` 39 | 40 | JSON-RPC Batch 2.0 崩れのようなリクエスト。だけども実際的で良いと思う。中身は RESTful な routing. 41 | 実際的には単一のリクエストも route を切りつつ、`/batch` とかでバッチリクエストを JSON-RPC (風) に受けるのが良いと思った。 42 | 43 | ただし、一挙にリクエストを受ける都合上レスポンスが遅くなりがちな問題がある。 44 | 45 | Response, [Chunked Transfer Encoding](http://en.wikipedia.org/wiki/Chunked_transfer_encoding) のような受け方をする必要があるのかもしれない。 46 | 47 | References 48 | --- 49 | 50 | - [モバイルアプリとAPIのありかたを考える2014](https://speakerdeck.com/ar_tama/mobairuapuritoapifalsearikatawokao-eru2014) - JSON-RPC Batch 2.0 について言及 51 | - [Facebook の Batch Request](https://developers.facebook.com/docs/graph-api/making-multiple-requests) 52 | - [Google Cloud Storage の Batch Request](https://developers.google.com/storage/docs/json_api/v1/how-tos/batch) 53 | - [AWS Product Advertising API の Batch Request](http://docs.aws.amazon.com/AWSECommerceService/latest/DG/BatchRequests.html) 54 | - [Rails gem: batch_api](https://github.com/arsduo/batch_api) - Facebook の Batch Request みたいな API エンドポイントを切れる gem. 55 | -------------------------------------------------------------------------------- /API--JSONPatch.md: -------------------------------------------------------------------------------- 1 | JSONPatch 2 | === 3 | 4 | ```json 5 | [ 6 | { "op": "replace", "path": "/baz", "value": "boo" }, 7 | { "op": "add", "path": "/hello", "value": ["world"] }, 8 | { "op": "remove", "path": "/foo"} 9 | ] 10 | ``` 11 | 12 | のような JSON. これを次のような JSON に適用すれば 13 | 14 | ```json 15 | { 16 | "baz": "qux", 17 | "foo": "bar" 18 | } 19 | ``` 20 | 21 | ↓ 22 | 23 | ```json 24 | { 25 | "baz": "boo", 26 | "hello": ["world"] 27 | } 28 | ``` 29 | 30 | こうなる。まあ、`op` 通りの操作を順当にやるだけ。 31 | `op` には色々語彙が用意されているが、基本的には `add`, `remove`, `replace` あたりがまともに使える語彙。 32 | 33 | 面白いこと? 34 | --- 35 | 36 | 次のように Client <=> API のデータのやりとりを捉えることで、JSONPatch を利用した一貫性のあるやりとりが可能となる。 37 | 38 | - Client 上で持っているデータを JSON と見なす。(本当は SQLite とかのデータベースで持っている。) 39 | * Resource のネームスペースにそれぞれの ID を入れ子した JSON と見なすことが出来る。 (下記の例を参照) 40 | - データを取得する場合 41 | 1. Client はサーバに JSONPatch を問い合わせる。 42 | 2. Client は得られた JSONPatch を自身のデータベースに適用する。 43 | 3. 以上により、Client はサーバ上の resources と自身のデータベースの resources を同期することが出来る。 44 | - データを push する場合 45 | 1. Client は JSONPatch の表現で、Client 上で変更したデータの差分をバックエンドに渡す 46 | 2. バックエンドは自身のデータベースに JSONPatch を適用する 47 | 3. (他の clients にも変更を反映させたい場合、ここで JSONPatch をそのまま Eventsource 等で broadcast する) 48 | 4. 以上により、Client は自身のデータ変更をバックエンドに反映させることが出来る。 49 | 50 | #### 例: データベース上のデータを JSON とみなす 51 | 52 | Primary Key を UUIDv1 として書く。Incremental な Int key でも良い。 53 | 54 | `books` と `authors` というテーブルにそれぞれ 3 つのデータが入っている。これを JSON で次のように表すことが出来る。 55 | 56 | ```json 57 | { 58 | "books": { 59 | "4cc47114-35b7-11e4-bb0f-164230d1df67": { 60 | "title": "Harry Potter", 61 | "author_id": "38ce0e76-35b8-11e4-bb0f-164230d1df67" 62 | }, 63 | "4cc47376-35b7-11e4-bb0f-164230d1df67": { 64 | "title": "Kokoro", 65 | "author_id": "38ce0fd4-35b8-11e4-bb0f-164230d1df67" 66 | }, 67 | "4cc47632-35b7-11e4-bb0f-164230d1df67": { 68 | "title": "Crime and Punishment", 69 | "author_id": "38ce111e-35b8-11e4-bb0f-164230d1df67" 70 | } 71 | }, 72 | "authors": { 73 | "38ce0e76-35b8-11e4-bb0f-164230d1df67": { 74 | "name": "J. K. Rowling" 75 | }, 76 | "38ce0fd4-35b8-11e4-bb0f-164230d1df67": { 77 | "name": "Natsume Soseki" 78 | }, 79 | "38ce111e-35b8-11e4-bb0f-164230d1df67": { 80 | "name": "Fyodor Dostoyevsky" 81 | } 82 | } 83 | } 84 | ``` 85 | 86 | この場合、例えば "J. K. Rowling" は `/authors/38ce0e76-35b8-11e4-bb0f-164230d1df67` の `path` で表される。 87 | 88 | 課題? 89 | --- 90 | 91 | - patch を作るには path が不可欠なので、各 resource に対して Client 側で ID を割り当てなければならない。このため、Incremental な primary key は使用不可能である。これは標準化されていない。 92 | - クライアントで変更したデータを逐次送信するのでなければ、クライアントは自身の resources に "変更済み" マークを持たなければならない。これは標準化されていない。 93 | - サーバは各々のクライアントに対して、それぞれどの段階での patch を持っているか知っていなければならない。あるいは、各々のクライアントは自身がどの patch まで適用されているか知っていなければならない。これは標準化されていない。 94 | - ある範囲だけの patch が欲しい場合のリクエストは標準化されていない。これは JSON-RPC2.0 Batch で表現した方が表現の幅が広い。(なぜなら JSONPatch は resources の操作しか提供しない) 95 | 96 | References 97 | --- 98 | 99 | - jsonpatch.com : http://jsonpatch.com/ 100 | - Rocket: a hybrid approach to real-time cloud applications : http://rocket.github.io/ 101 | -------------------------------------------------------------------------------- /API-JSONRPC.md: -------------------------------------------------------------------------------- 1 | JSON-RPC 2.0 2 | --- 3 | 4 | JSON で RPC しようという仕様がある。まあ RPC での利用はどうでもいい。 5 | API 呼び出しを RPC とみたて、JSON-RPC over HTTP をするとき、**割と標準的な仕様** として利用出来る。 6 | 7 | Spec 8 | --- 9 | 10 | ``` 11 | { 12 | "jsonrpc": "2.0", 13 | "id": "some_id_for_invocation", 14 | "method": "methodName", 15 | "params": { 16 | "foo": "bar" 17 | } 18 | } 19 | ``` 20 | 21 | 通信レイヤが HTTP であることを限定していないので、Header や HTTP Method は仕様で指定されない。 22 | 23 | `POST` で、`Accept-Content-Type: "application/json"` で良い。 24 | 25 | 利点? 26 | --- 27 | 28 | 1. Header に特別な情報を含まない。 29 | - Header を弄れないクライアントでも使える。(JSONP とか!) 30 | 2. HTTP Method に特別な情報を持たせない。 31 | - 目に見える「ボディ」だけに情報を集められる。 32 | - HTTP Method を自由に指定出来ないクライアントでも使える。(JSONP) 33 | 3. レスポンスに、標準化した形で Error 情報を含められる。 34 | 4. JSON-RPC 2.0 Batch という仕様があり、複数メソッドの一挙呼び出しに対応している。通信の数を抑えられるので Mobile API に良い。。 35 | 36 | REST みたいに流暢ではないが、堅実でよい! 37 | REST は URL がカッコいいけど、暗黙な部分が多いし、弄るべきフィールド(Header, HTTP Method, Body, Params..)が多くてつらい。 38 | 39 | あと、Batch のリクエストなど、REST の「URL だけで出来るだけ全てを表現する」思想ゆえに対応が辛い場合が多い。 40 | 41 | 究極、GET でも params に JSON を含めて通信すれば良いので、JSONP でも全く同じ API 設計を持ってこられる。 42 | 43 | 欠点 44 | --- 45 | 46 | 1. `multipart/form-data` が辛い。バイナリを含められない。 47 | 2. REST に比べ一般的でない。 48 | 3. `Authorization` Header をどこに含めるか困る。 49 | 4. 50 | -------------------------------------------------------------------------------- /AWS--Tuning.md: -------------------------------------------------------------------------------- 1 | - http://qiita.com/yamasaki-masahide/items/7c44ea17d9901601f38c 2 | S3へ最高のパフォーマンスでログを保存する 3 | - http://understeer.hatenablog.com/entry/2014/02/25/173810 DynamoDBやSQSといったAPIを高頻度に使うときに忘れずにセットしておきたいカーネルパラメータ 4 | -------------------------------------------------------------------------------- /Action.md: -------------------------------------------------------------------------------- 1 | 社員たちは、会議の後で言い訳は許されません。Appleの会議では、「アクションリスト」が作成され、各アクションの隣にはDRI(directly responsible individual:直接責任者)が書き込まれます。すなわち、そのタスクの達成に責任を負う個人の名前です。 2 | -------------------------------------------------------------------------------- /Admin.md: -------------------------------------------------------------------------------- 1 | ぼくのかんがえたさいきょうのアンサー管理画面 書き起こし - akiyan.com : http://www.akiyan.com/blog/archives/2014/12/answer-admin-night-transcript.html 2 | -------------------------------------------------------------------------------- /Analytics.md: -------------------------------------------------------------------------------- 1 | - http://wazanova.jp/items/1492 2 | 3 | > 事業の拡大に伴ってアナリティクスの需要は、CEOへの報告から、マーケ/開発の現場の利用、データサイエンティストの分析まで様々。しかし、各チームがバラバラに複数のアナリティクスシステムを運用していて、オーナーシップを取るチームはなし。 4 | > トラッキング用にページあたり20-30ピクセルを仕込んでいて、つまりユーザ当たり 20-30 GETリクエスト / ページとなり、サーバ負荷が過大。 5 | > 「全てをトラックする。」を目標に内製のアナリティクスシステムの整備にとりかかる。 6 | -------------------------------------------------------------------------------- /Android--AccountManager.md: -------------------------------------------------------------------------------- 1 | AccountManager 2 | === 3 | 4 | - Username と authToken の組み合わせで管理。 5 | - 非同期API 6 | - ちゃんとそこそこ暗号化して情報持ってくれるっぽい 7 | 8 | References 9 | --- 10 | 11 | - http://qiita.com/nein37/items/9aef7e4e06e71990c6e1 12 | -------------------------------------------------------------------------------- /Android--Annotation+AspectJ.md: -------------------------------------------------------------------------------- 1 | AspectJ と Annotation 2 | === 3 | 4 | https://speakerdeck.com/kaiinui/black-magic-in-java 5 | 6 | けっこうカンタンに出来る。 7 | 8 | Gradle 9 | --- 10 | 11 | ```groovy 12 | // /build.gradle 13 | classpath 'com.uphyca.gradle:gradle-android-aspectj-plugin:0.9.+' 14 | 15 | apply plugin: 'android-aspectj' 16 | ``` 17 | 18 | ```groovy 19 | // /app/build.gradle 20 | compile 'org.aspectj:aspectjrt:1.8.1' 21 | ``` 22 | 23 | Annotation 24 | --- 25 | 26 | ```java 27 | @Target(METHOD) 28 | @Retention(CLASS) 29 | public @interface PotatoTip {} 30 | ``` 31 | 32 | Aspect 33 | --- 34 | 35 | メソッドを乗っ取って色々出来る。 36 | 37 | ```java 38 | 39 | @Aspect 40 | public class PotatoAspect { 41 | @Pointcut("execution(@com.kaiinui.potatoannotation.Potato * *(..))") 42 | public void method() {} 43 | 44 | @Around("method()") 45 | public Object executePotato(ProceedingJoinPoint joinPoint) throws Throwable { 46 | final Activity activity = (Activity) joinPoint.getThis(); 47 | activity.runOnUiThread(new Runnable() { 48 | @Override 49 | public void run() { 50 | Toast.makeText(activity, "HOGHOGE", Toast.LENGTH_SHORT).show(); 51 | } 52 | }); 53 | 54 | Object result = joinPoint.proceed(); // 分かりやすくするため二段に。 .proceed() で対象のメソッドを実行して返り値を貰える。 55 | return result; 56 | } 57 | } 58 | ``` 59 | 60 | これだけで動く 61 | --- 62 | 63 | #### サンプル 64 | 65 | ```java 66 | // MainActivity.java 67 | @Override 68 | protected void onCreate(Bundle savedInstanceState) { 69 | super.onCreate(savedInstanceState); 70 | setContentView(R.layout.activity_my); 71 | 72 | doSomething(); 73 | } 74 | 75 | @Potato 76 | public void doSomething() { 77 | } 78 | ``` 79 | 80 | なにもないメソッドを呼んだら… 81 | 82 | ![](https://dl.dropboxusercontent.com/u/7817937/_github/Screenshot_2014-08-20-18-31-11.png) 83 | 84 | 黒魔術。 85 | 86 | 参考文献 87 | --- 88 | 89 | - https://github.com/JakeWharton/hugo/tree/master/hugo-runtime 90 | -------------------------------------------------------------------------------- /Android--Annotation.md: -------------------------------------------------------------------------------- 1 | Annotation 2 | === 3 | 4 | ```java 5 | public @interface InjectView {} 6 | ``` 7 | 8 | などとすることで Annotation を作ることが出来る。 9 | 10 | ```java 11 | public @interface InjectView { 12 | int id(); 13 | } 14 | ``` 15 | 16 | とすると、 `@InjectView(id=3)` などと使うことが出来る。 17 | 18 | `id=` とか付けたくない場合は `value()` とすれば 19 | 20 | ```java 21 | public @interface InjectView { 22 | int value(); 23 | } 24 | ``` 25 | 26 | `@InjectView(R.id.text_view)` などと使える。 27 | 28 | @Retention と @Target 29 | --- 30 | 31 | `@Retention` はアノテーション宣言(@interface)に付けるアノテーション。 32 | どの段階まで情報を保持すべきかを宣言する。(`RUNTIME` であれば実行時まで保持するが、`SOURCE` だとビルド時に失われる。`@NonNull` みたいなのはこれ) 33 | 34 | `@Target` はどんなものにアノテーションを付けられるかを宣言出来る。 35 | `FIELD`, `METHOD`, `CLASS` などがある。 `ANNOTATION` というのもあってイイ感じに楽しいことが出来る。 36 | 37 | ```java 38 | @Retention(RetentionPolicy.RUNTIME) 39 | @Target(ElementType.FIELD) 40 | public @interface InjectView { 41 | int value(); 42 | } 43 | ``` 44 | 45 | こんな感じ。 46 | 47 | これで呼び出し側からは `@InjectView(R.id.text_view) TextView textView;` という風に出来る。 48 | 49 | 利用方法 50 | -- 51 | 52 | 全うな利用方法は、これをタグとして、他の場所から色々なことをする。 53 | ButterKnife などの DI が良い例。 54 | 55 | アノテーションの扱い方 56 | --- 57 | 58 | ```java 59 | for (Field field : this.getClass().getDeclaredFields()) { 60 | InjectView annotation = field.getAnnotation(InjectView.class); 61 | if (annotation != null){ 62 | Log.i("ANNOTATION", "value:" + annotation.value()); 63 | } 64 | } 65 | ``` 66 | 67 | Java には `Class`, `Method`, `Field` っていう如何にもなクラスが用意されている。これらは、`instance.getClass()`, `class.getMethods()`, `class.getDeclaredFields()` で得ることが出来る。 68 | 69 | これらは `field.getName()` とか色々することが出来、色々出来そうな感じが有る。 70 | 71 | 注意は、`class.getFields()` があるがよくわからないやつが結構返ってくる。`class.getDeclaredFields()` を使う。 72 | 73 | こうすることで 74 | 75 | ``` 76 | 08-22 17:50:45.409 24891-24891/com.kaiinui.sampleannotation I/MyActivity﹕ textView 77 | 08-22 17:50:45.409 24891-24891/com.kaiinui.sampleannotation I/MyActivity﹕ value:2131230721 78 | ``` 79 | 80 | といったログを得ることが出来る。 81 | 82 | MVP の ButterKnife 83 | --- 84 | 85 | ```java 86 | // MyActivity.java 87 | 88 | @InjectView(R.id.text_view) TextView textView; 89 | 90 | // onCreate 91 | 92 | for (Field field : this.getClass().getDeclaredFields()) { 93 | InjectView annotation = field.getAnnotation(InjectView.class); 94 | Log.i("MyActivity", field.getName()); 95 | if (annotation == null) { return; } 96 | 97 | int id = annotation.value(); 98 | View view = this.findViewById(id); 99 | try { 100 | field.set(this, view); 101 | } catch (IllegalAccessException e) { } 102 | } 103 | 104 | textView.setText("WHOA!"); 105 | ``` 106 | 107 | こんなクソコードで最低限の ButterKnife を作れる。 108 | 109 | 注意点は 110 | 111 | * `getAnnotation()` は Nullable 112 | * `field.set(targetInstance, value)` で `targetInstance` の当該フィールドに `value` を突っ込める (例外は `IllegalAccessException`) 113 | 114 | 外部からやるようにする 115 | --- 116 | 117 | 単純で、 118 | 119 | ```java 120 | public class BananaKnife { 121 | public static void inject(Activity target) { 122 | for (Field field : target.getClass().getDeclaredFields()) { 123 | InjectView annotation = field.getAnnotation(InjectView.class); 124 | if (annotation == null) { return; } 125 | 126 | int id = annotation.value(); 127 | View view = target.findViewById(id); 128 | try { 129 | field.set(target, view); 130 | } catch (IllegalAccessException e) { } 131 | } 132 | } 133 | } 134 | ``` 135 | 136 | という感じにする。注意点は、`target` の該当フィールドが `private` だと `Exception` 出る。 137 | -------------------------------------------------------------------------------- /Android--Tools.md: -------------------------------------------------------------------------------- 1 | Tools 2 | --- 3 | 4 | - Code formatting : http://stackoverflow.com/questions/16710367/android-code-style-in-intellij-idea-android-studio 5 | -------------------------------------------------------------------------------- /Android--UITesting.md: -------------------------------------------------------------------------------- 1 | AndroidのUIテスト(Spoon+Robotium)としてスクリーンショットを撮れるようにしてみた。 - Qiita : http://qiita.com/shiraji/items/129ab9dc6fe0d81d8576 2 | -------------------------------------------------------------------------------- /Android--gradle-library: -------------------------------------------------------------------------------- 1 | Android で Gradle でオレオレライブラリをやる方法とか 2 | --- 3 | 4 | http://u1aryz.blogspot.jp/2013/06/githubmavenandroidaar.html 5 | 6 | gradle の maven プラグインで maven 形式でビルドして、local に upload. 7 | そのファイル群を GitHub pages に突っ込むことでオレオレ maven レポジトリになる。 8 | 9 | けっこうだるい 10 | -------------------------------------------------------------------------------- /Android-BackgroundTasks.md: -------------------------------------------------------------------------------- 1 | Background Tasks 2 | === 3 | 4 | - AsyncTaskLoader - イイ感じに Activity のライフサイクルで死なない非同期タスク 5 | - IntentService - Activity と結びつく必要の無い、独立した「サービス」としての非同期処理 6 | 7 | References 8 | --- 9 | 10 | - http://qiita.com/KeithYokoma/items/de5bebf089a7462940ba 非同期処理でよく使う IntentService と AsyncTask は何が違って何が同じなのか 11 | - http://qiita.com/glayash/items/60546794f83fd7a0f271 Androidの非同期処理の話 12 | -------------------------------------------------------------------------------- /AndroidDev.md: -------------------------------------------------------------------------------- 1 | Android Development 2 | === 3 | 4 | iOSとの比較つき!Androidでこんなアプリ,こんな機能を作りたかったらこれを見ろ!作りたいアプリに対応するクラス、ライブラリのまとめ! - Qiita : http://qiita.com/appwatcher/items/7d270de99d63bb9f2be4 5 | 6 | Activity 簡単に死ぬ 7 | --- 8 | 9 | Activity, 画面に紐づいてて画面に居る間は死なないイメージを普通の脳みそなら持つと思うけど、回転させるだけで一旦死んでまた作られる。 10 | また、バックグラウンドに居る間にメモリ足りなくなったりすると勝手に殺される。 11 | 12 | Activity とか Fragment の変数で状態管理するの気をつけないと簡単にフローが崩れる。 13 | 14 | ちゃんと `onCreate(Bundle savedInstanceState)` と `onSaveInstanceState(Bundle outState)` をやっておけば変数は保たれる。 15 | 16 | 色々書いたりするの面倒くさいので、アノテーションでよろしくやってくれる [icepick](https://github.com/frankiesardo/icepick) を使うと良い。 17 | 18 | 書いた => http://qiita.com/kaiinui/items/8a6a7dddb9310f645da3 19 | 20 | Background スレッドから UI を触ると死ぬ 21 | --- 22 | 23 | 結構な数の処理が Background スレッドで実行されることが前提とされている。(UI をロックしないように) 24 | Callback 的なものはほとんど Background で走る。 25 | 26 | ここから UI を触ると死ぬ。`Toast.makeText()` するだけで死ぬ。 27 | 28 | UI を触るときは `runOnUiThread(Runnable)` を使う必要がある。相当たくさんの場面で出てくる。 29 | 30 | GridView, HeaderView をサポートしていない 31 | --- 32 | 33 | GridView なぜか HeaderView をサポートしていない。 34 | 35 | じゃあ GridView の上に View を置いてやればいいじゃん。は間違い。 36 | 37 | なぜなら GridView は `match_parent` で使うことを前提としていて、動的な高さを持つようには出来ていない。 38 | GridView を `height:fill_content` でやろうとすると、中身を全部構築し、高さを知ってから描画、となってしまい画像の描画とかだと大変重くなる。 39 | 40 | Google の公式 training コードでは、`< n` までの `getView()` で Header の view を返し、`>= n` なら要素の View を返す。 41 | 42 | やれば分かるけど相当コードが汚くなる。 `position - numberOfColumn` とかたくさん出てくる。もちろん `numberOfColumn` 忘れると要素がズレる。 43 | 44 | https://github.com/maurycyw/HeaderGridView こういうのを使うとよい。 45 | 46 | `getViewById()` のキャストがキモい 47 | --- 48 | 49 | `getViewById()`, `TextView` とかにキャストしまくっててキモい感じは有る。 50 | 51 | https://github.com/JakeWharton/butterknife 使うとコード短くなるしその辺隠れて良い。 52 | 53 | `@OnClick()` とか相当良い。 54 | 55 | テスト 56 | --- 57 | 58 | UI テストは Robotium がまともらしい。 espresso はメンテされてないとのこと… 59 | 60 | https://code.google.com/p/robotium/ 61 | -------------------------------------------------------------------------------- /AppLinks.md: -------------------------------------------------------------------------------- 1 | Webサイトがあるアプリなら必須対応になりそうな、App Linksを使ってみた - Lebe Inc. Blog : http://blog.lebe.jp/post/85203389095/applinks 2 | -------------------------------------------------------------------------------- /AppMarketing.md: -------------------------------------------------------------------------------- 1 | Twitter, FB App Ads 2 | --- 3 | 4 | - http://www.quora.com/What-is-the-cost-per-install-of-iOS-app-in-Facebooks-new-Mobile-App-Install-Ads-program 5 | - https://ads.twitter.com/ 6 | 7 | ### Twitter Ad 8 | 9 | 直接の Retweet、ふぁぼに課金。(Retweet されたツイートの Fav, Retweet は無料) 10 | 「ダウンロード」とか、ボタンのアクションに課金。 11 | 12 | CPI Ads 13 | --- 14 | 15 | - Admob 16 | - TapJoy... 17 | - ... 18 | 19 | ASO 20 | --- 21 | 22 | - SearchMan 23 | - SensorTower 24 | 25 | PR 26 | --- 27 | 28 | 各国の代理店 29 | 30 | Press-Relation 31 | --- 32 | 33 | - リアル収益や広告単価もぽろり!人気アプリ開発者による暴露トークセッションin大阪-メタップス×アプリゲット勉強会 | アプリマーケティング研究所 : http://appmarketinglabo.net/osaka-bakurotalk/ 34 | - アイコンを変えてDL率が5倍に?GooglePlay成功の秘訣!集客〜マネタイズまで-metaps主催アプリセミナー | アプリマーケティング研究所 : http://appmarketinglabo.net/googleplay-secret-of-success/ 35 | 36 | > その裏で、メール、電話、何度も会いにいく、 37 | などでコミニュケーションをとりながら、 38 | メディアの担当者と関係性を築いていった。 39 | 結果、各社に掲載の確約をいただいた。 40 | 連載の提案をくれるメディアもいた。 41 | 「どうやって記事を掲載してもらったの?」とよく聞かれるが、 42 | 地道な活動の積み重ねの結果。 43 | 44 | > リリース日に10サイト以上で記事になった。 45 | ・リリース1日目 46 | 夕方からDL数が一気に伸びる 47 | ※明らかに記事をみた人のDL 48 | AppStore圏外⇒無料50位くらいに上がった。 49 | 50 | Markets 51 | --- 52 | 53 | - Google Play 54 | - Apple App Store 55 | - AmazonAppStore 56 | - XiaomiAppStore 57 | 58 | http://appmarketinglabo.net/googleplay-secret-of-success/ 59 | 60 | Others 61 | --- 62 | 63 | - http://www.apptamin.com/blog/app-developer-tools/ 64 | 65 | References 66 | --- 67 | 68 | - リアル収益や広告単価もぽろり!人気アプリ開発者による暴露トークセッションin大阪-メタップス×アプリゲット勉強会 | アプリマーケティング研究所 : http://appmarketinglabo.net/osaka-bakurotalk/ 69 | - アイコンを変えてDL率が5倍に?GooglePlay成功の秘訣!集客〜マネタイズまで-metaps主催アプリセミナー | アプリマーケティング研究所 : http://appmarketinglabo.net/googleplay-secret-of-success/ 70 | -------------------------------------------------------------------------------- /Asking.md: -------------------------------------------------------------------------------- 1 | Ask 2 | === 3 | 4 | 人に聞く時、文章で聞いてはならない。箇条書きで聞く。 5 | 6 | 1. 何に答えればいいかわかりやすい 7 | 2. 答え漏れが無くなる。(何を聞いてるか曖昧にならない) 8 | -------------------------------------------------------------------------------- /AspectOrientedProgramming.md: -------------------------------------------------------------------------------- 1 | Aspect-Oriented Programming 2 | -- 3 | 4 | * iOS => Aspects https://github.com/steipete/Aspects 5 | * Android => AspectJ 6 | * JS => meld / https://github.com/cujojs/meld 7 | * ruby => aspector / https://github.com/gcao/aspector 8 | 9 | 出来ること 10 | -- 11 | 12 | * 処理をフックしてほげほげする 13 | * 処理の例外をキャッチしてほげほげする (知らなかった) 14 | 15 | 例えば? 16 | --- 17 | 18 | ログを取るだとか、色んなクラス / メソッドに分断しがちな責務をまとめるために使う。 19 | 一番の用途はログ。 20 | 21 | 参考 22 | -- 23 | 24 | * 【翻訳】アスペクト指向プログラミング入門 http://postd.cc/intro-to-aop/ 25 | -------------------------------------------------------------------------------- /CSS--maintainable.md: -------------------------------------------------------------------------------- 1 | Maintainable CSS 2 | --- 3 | 4 | まともな CSS を書く。 5 | 6 | Why? 7 | --- 8 | 9 | CSS, 継承関係の把握とか、スタイルの汚染とか、命名規則とかガバガバすぎてまともに管理出来ない。 10 | 11 | How? 12 | --- 13 | 14 | - SMACSS https://smacss.com/ 15 | 16 | とかの CSS Convention に準拠して書く。 17 | 18 | わりと複雑で導入しにくさはある。 19 | 20 | 実際的には? 21 | --- 22 | 23 | * FLOCSS https://github.com/hiloki/flocss 24 | 25 | これくらいが準拠しやすそう。ルールは 26 | 27 | * Component - 再利用可能なコンポーネント 28 | * Project - 複数のコンポーネントと諸処のスタイルから構成されるパターン。プロジェクトに固有のものだから Project. 29 | * Utility - 色んな便利クラス 30 | 31 | がトッブレベルにあり、命名規則として 32 | 33 | * Block 34 | * Element 35 | * Modifier 36 | 37 | の BEM システム。 38 | 39 | Component と一括りにされがちなものを Component という再利用可能なものと、Project という再利用不可能なものに分けたのは良いアイデアと思う。 40 | 41 | ###命名規則 42 | 43 | ##### トップレベル 44 | 45 | - `.c-xxx` - components 46 | - `.p-xxx` - projects 47 | - `.u-xxx` - utilities 48 | 49 | ##### BEM 50 | 51 | - `.block__element--modifier` 52 | 53 | e.g. `.c-button__icon`, `.c-button__icon--rev` 54 | 55 | ###運用規則 56 | 57 | 安易なカスケードと依存関係を抑える。 58 | 59 | - 原則として、モジュール間のカスケーディング、他のモジュールを親とするセレクタを用いたカスケーディングは禁止とします。 60 | - Projectレイヤーモジュール内に、同一のComponentレイヤーモジュールが複数点在する場合を考慮し、出来る限り子供セレクタなどを活用して、適用範囲を限定する。 61 | - 他のモジュールを親セレクタに持つのは1つだけとする。 62 | -------------------------------------------------------------------------------- /CSS--typography.md: -------------------------------------------------------------------------------- 1 | Typography 2 | === 3 | 4 | `-webkit-font-smoothing: antialiased;` でアンチエイリアスが付く。カッコいい。 5 | -------------------------------------------------------------------------------- /Convenience-Badge.md: -------------------------------------------------------------------------------- 1 | - http://progressed.io/bar/20 ![](http://progressed.io/bar/20) 2 | - http://img.shields.io/cocoapods/v/AQMSecureRandom.svg?style=flat ![](http://img.shields.io/cocoapods/v/AQMSecureRandom.svg?style=flat) 3 | - https://badge.fury.io/rb/middleman-inliner.svg ![](https://badge.fury.io/rb/middleman-inliner.svg) 4 | - https://maven-badges.herokuapp.com/maven-central/cz.jirutka.rsql/rsql-parser ![](https://maven-badges.herokuapp.com/maven-central/cz.jirutka.rsql/rsql-parser/badge.svg?style=flat) 5 | - http://img.shields.io/travis/kaiinui/KIInPlaceEdit.svg?style=flat ![](http://img.shields.io/travis/kaiinui/KIInPlaceEdit.svg?style=flat) 6 | - http://img.shields.io/badge/test-Unit+E2E-green.svg?style=flat ![](http://img.shields.io/badge/test-Unit+E2E-green.svg?style=flat) 7 | -------------------------------------------------------------------------------- /DESIGN--font-fallbacks.md: -------------------------------------------------------------------------------- 1 | Font fallbacks 2 | --- 3 | 4 | Font 無い場合の Fallback を考える。 5 | 6 | ### Myriad Pro 7 | 8 | ```css 9 | font-family: Myriad Pro, Lucida Sans, Segoe UI, Calibri, sans serif; 10 | ``` 11 | 12 | ### Avenir Next 13 | 14 | Google Webfont 使うしかない? 15 | 16 | ### Lucida Grande 17 | 18 | Looks like widely adopted? 19 | 20 | ### Mobile では? 21 | 22 | font は各 weight / style に対して 200KB - 400KB 程度なので埋め込んで使う。 23 | 24 | 当たり前だが Myriad Pro と Avenir Next は otf とかないので代替フォントを Google Font とかで探す。あるいは Adobe から買う。 25 | 26 | References 27 | --- 28 | 29 | - http://graphicdesign.stackexchange.com/questions/16036/what-are-google-webfonts-or-typekit-alternatives-to-avenir-next-pro 30 | - http://graphicdesign.stackexchange.com/questions/350/web-safe-alternative-to-myriad-pro-font 31 | - http://www.w3schools.com/cssref/css_websafe_fonts.asp 32 | -------------------------------------------------------------------------------- /DESIGN--font.md: -------------------------------------------------------------------------------- 1 | Font 2 | --- 3 | 4 | ![](https://dl.dropboxusercontent.com/u/7817937/_github/%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88%202014-09-10%2019.03.20.png) 5 | 6 | Gothic 7 | 8 | - Helvetica 9 | - Myriad Pro 10 | - Lucida Grande 11 | - Avenir 12 | - Noto Sans 13 | - Gill Sans 14 | 15 | Roman 16 | 17 | - Baskerville 18 | -------------------------------------------------------------------------------- /DESIGN--resource.md: -------------------------------------------------------------------------------- 1 | Resources 2 | === 3 | 4 | http://www.aegeank.com/sketchactive/ 5 | 6 | http://unsplash.com/ 7 | 8 | http://pngtextures.com/ 9 | -------------------------------------------------------------------------------- /Design--CommonClasses.md: -------------------------------------------------------------------------------- 1 | よく使う感じのクラス責務とか 2 | === 3 | 4 | 良い名前を使うことで、クラスの責務の過多を防ぐことが出来る。(Policy クラスに API アクセス機能を持たせる奴は居ない) 5 | 様々なクラスの引き出しを持つことで、パターンに遭遇したときに容易にクラス責務を分けることが出来る。 6 | 7 | また、責務を細かい粒度で分けてハッキリとさせることで、テストやテストダブルが容易になる。 8 | 9 | 一体何をテストすれば!?みたいにならない。各クラスが己の責務を粛々と果たすことを保証すればよい。 10 | クラスの連携は結合テストの範囲。 11 | 12 | Aggregator 13 | --- 14 | 15 | - 複数クラスを跨いだ操作を担当 16 | - Rails だとよく Model に書かれたりする。(この責務過多は最悪のパターンだと思う。) 17 | - たとえば、「Order を作ったら、 afterCreate で 商品マスタの数を減らす」 18 | - Transaction も絡むし、絶対にクラス横断の連携は他のクラスに切る。 19 | - 横断操作、ヤバくなりやすい。 20 | 21 | Repository 22 | --- 23 | 24 | - "Persistence" を担当。(つまりデータベースに突っ込んだりするところ) 25 | - ActiveModel でいえば、`#save`, `#find`, `#where` とか 26 | 27 | Service 28 | --- 29 | 30 | - ビジネスロジックを含まず、粛々と依頼通りに何かしらの物事をこなすクラス 31 | - **Service はビジネスロジックを含まない。ビジネスロジックを担当するクラスが依頼を考え、Service は依頼を受けて粛々と実装するだけ。切り分けを間違ってはいけない。** 32 | - けっこう逃げの名前にもなりがち 33 | 34 | Builder 35 | --- 36 | 37 | - なにかしらの Object を生成する責務を持つ。 38 | - 例: `JsonBuilder` 39 | 40 | Adapter 41 | --- 42 | 43 | - 何かしらのややこしい操作を隠蔽して、シンプルな感じにして提供する責務。 44 | - つまりラッパー。 45 | - (Adapter を使うクラスは、ややこしい操作をクラス内に含めずに済み、責務の肥大化を防ぐ。) 46 | 47 | Policy 48 | --- 49 | 50 | - 何らかのルールを記述する(例:「バケツ」はその容量を超えて中身を入れられない) 51 | - クラスにルールを持たせると、責務過多になりやすい 52 | - たとえば、ビジネスロジックは当てはまりやすい 53 | - 例:「プレミアムでない場合はこれが出来ない」は完全に Policy クラスの責務。 54 | 55 | Specification 56 | --- 57 | 58 | - 「仕様」クラス 59 | - 完全に理解していないが、Eric Evans の DDD で触れられていた。 60 | 61 | Entity 62 | --- 63 | 64 | - 値を保持することのみが責務。(厳密に言えば "Entity" と "Value Object" は違うけども…) 65 | - データを保持すること意外何も責務が無い 66 | - ActiveModel は「データの保持」以外にも責務を持っている。 67 | 68 | Presenter 69 | --- 70 | 71 | - "Entity" の値を装飾することが責務。 72 | - 例: `firstName` と `lastName` を持つ Entity を用いて、Presenter が `fullName` を返す。 73 | - いわゆる View でこれをやりがちだが、 Presenter に分けた方が絶対に良い。 74 | - Rails ではやっぱり Model に書かれがち。 75 | 76 | Observer 77 | --- 78 | 79 | - "Entity" の値を見て、変更があれば即座に何かにそれを伝えることが責務 80 | - Model の値を View に bind したりとか。 81 | 82 | 番外編 83 | --- 84 | 85 | ActiveModel の責務を明示的に分ければどうなるか 86 | 87 | * Entity 88 | * Validator 89 | * Repository 90 | * Observer (Callbacks) 91 | * (DatabaseAdapter) 92 | 93 | "Model is to vague." 94 | 95 | #### References 96 | 97 | - http://www.sitepoint.com/ddd-for-rails-developers-part-3-aggregates/ 98 | -------------------------------------------------------------------------------- /Design--Designdoc.md: -------------------------------------------------------------------------------- 1 | Design Doc 2 | --- 3 | 4 | Google は Design Doc と呼ばれる設計文書を、実際に設計・実装にとりかかる前に書く。 5 | 6 | 内容は、 7 | 8 | * Why? 9 | * How? 10 | * Who? 11 | * セキュリティとか性能の懸念とか 12 | * テスト方法等 13 | 14 | など。 15 | 16 | > プロジェクト立ち上げ時の 1~2週間をかけて書く。ある程度ポイントが書け たら、もうコーディングへ。 17 | 18 | (http://blog.livedoor.jp/heitatta/archives/54439839.html) 19 | 20 | 「コードをガッツリ書ける人が」「コードを書く時間を捨てて」「1-2w というそこそこ長い時間を使って」書く… 21 | わりと人的コストをかけて書いていることが伺える。 22 | 23 | メリット 24 | --- 25 | 26 | こういった文書を書くことには、以下のような良さがあると思った。 27 | 28 | 1. 問題が浮き彫りになる(Good Problem to have.) 29 | 2. チームで問題 / 課題を共有出来る 30 | 3. チームでプロダクトの方向性を共有出来る 31 | 3. 各々が好き勝手に実作業に取り掛かり、結果齟齬が出る可能性を予防出来る 32 | * 「問題の早期発見」 33 | 4. 文書に落とし込むことにより設計 / 実装を **具体的** にイメージすることが出来る 34 | 5. フォーマットが統一されていることにより、見落としがちなポイントを設計時点で考慮出来る 35 | 6. 具体的なフォーマットに沿った文書に落とし込むので、考慮出来ていないポイントが自明になる 36 | * あやふやな仕様を残さず実作業に入ることが出来る。 37 | 38 | Design Doc は一人で書くプロダクトにも有効だが、複数人で開発するときにより効果を発揮する。具体的には、 39 | 40 | 1. 設計を誰かが一元的に済ませて…ではないので、チーム全員の意図が入った設計になりやすい 41 | 2. チーム全員が設計にコミット出来る(理想的には) 42 | 3. 仕様 / 思想 / 方法がチームで共有出来る。しやすい。 43 | 44 | といった便益があるように思う。全体的に、「チームで共有する」「文書」を書くことと、あやふやになりがちなものを「書いて」残すことがこれらの便益をもたらすのだと感じた。 45 | 46 | 具体的な Design Doc 47 | --- 48 | 49 | このへんで Googler の書いた Design Doc を参照することが出来る。 50 | 51 | - Design Documents http://www.chromium.org/developers/design-documents 52 | - Dagger 2.0 https://docs.google.com/document/d/1fwg-NsMKYtYxeEWe82rISIHjNrtdqonfiHgp8-PQ7m8/edit#heading=h.2t5cq7yndhts 53 | 54 | あるいはこちらのブログで実例へのリンクが挙げられている。 55 | 56 | - Google の Design Doc について http://d.hatena.ne.jp/cou929_la/20091116/1258373100 57 | 58 | References 59 | --- 60 | 61 | - Google のソフトウェア・エンジニアリング http://blog.livedoor.jp/heitatta/archives/54439839.html 62 | - Google の Design Doc について http://d.hatena.ne.jp/cou929_la/20091116/1258373100 63 | - Googleのdesign docを眺めてみる http://kenmaz.hatenadiary.jp/entry/20090712/1247401684 64 | - Design Documents http://www.chromium.org/developers/design-documents 65 | - Dagger 2.0 https://docs.google.com/document/d/1fwg-NsMKYtYxeEWe82rISIHjNrtdqonfiHgp8-PQ7m8/edit#heading=h.2t5cq7yndhts 66 | -------------------------------------------------------------------------------- /Design--Flux.md: -------------------------------------------------------------------------------- 1 | Flux 2 | === 3 | 4 | - Building Angular Apps Using Flux Architecture | Victor Savkin : http://victorsavkin.com/post/99998937651/building-angular-apps-using-flux-architecture 5 | 6 | ![](http://media.tumblr.com/53db17b5ee004c98803f5673d349882f/tumblr_ndfxlbl9fC1qc0howo1_1280.png) 7 | 8 | - Fluxxor - Quick-Start Guide : http://fluxxor.com/guides/quick-start.html 9 | - Reactを実際に使ってみた話が増えてきた - ワザノバ | wazanova : http://wazanova.jp/items/1582 10 | - kaiinui/TodoFlux : https://github.com/kaiinui/TodoFlux 11 | -------------------------------------------------------------------------------- /Design--GoodCode.md: -------------------------------------------------------------------------------- 1 | GoodCode 2 | === 3 | 4 | 小手先のことは置いておいて、原則として追求すべきことは 5 | 6 | 1. まとめて、隠蔽する(ライブラリ化) 7 | 2. 1 つのクラス / メソッドにつき 1 つの責務しか持たない(小さいことをしっかりやるモノを組み合わせてでかいモノを作る) 8 | 3. テストを書く 9 | 10 | まとめて、隠蔽する 11 | --- 12 | 13 | `AFNetworking` は中身を知らなくても使える。`- GET` などの public メソッドを呼ぶだけで全てが済む。 14 | こういったレベルまで中身が隠蔽されると、自ずと意識すべき「クラス数」が減るという現象が起こる。 15 | 16 | `AFNetworking` の中身クラスまで自分のコードのクラス数に数える奴は居ない。 17 | これは素晴らしいこと。 18 | 複雑さは関係するクラス数の 2 乗に比例する。くらいで考えておくと、この効力は偉大。(クラスを分けるな、という話ではない) 19 | 20 | このように「まるでライブラリのように使える」程度までクラス / 責務を凝縮させ、切り離すべき。 21 | 22 | ここまで隠蔽出来るケースは、かなり限定的ではないかと思うが、例えば "UI" であったり、 "API Client", "Gesture Detector", "Model Class" などは隠蔽し得る。 23 | 24 | 想像してみたい。例えば、「API クライアントライブラリの面倒だけを見る人」「Model Class の中身だけ面倒を見る人」が居れば、どれだけ「本丸」をつくる人は楽だろう? 25 | 26 | 自分のアプリを「ライブラリの集合」と言える程度までモジュラーにすると良いと思う。 27 | 28 | だから、ある機能を追加したいとき、最初からアプリのコードを書くのではなく、ライブラリのプロジェクトに切って始めるのは意識的にも効果がある。ように思う。 29 | 30 | 1 つの責務 31 | --- 32 | 33 | 1 つのクラスは 1 つの責務しか持ってはいけない。 34 | 35 | これを破るとたいてい次のような問題が起こる。 36 | 37 | 1. 状態変数が増える 38 | 2. お互いに関係し合うメソッドが増える 39 | 3. テストしにくい 40 | 41 | 「複雑さは構成要素の 2 乗に比例する」 42 | 43 | テストを書く 44 | --- 45 | 46 | テストないとリファクタリング出来ない。 47 | とにかくなんでもいいから一行でもいいからテストは書くべき。 48 | 49 | 副作用と表明 50 | --- 51 | 52 | どんな副作用をもたらすのか明示的に表明する。 53 | 54 | 「関数」と「サブルーチン」の区別。 55 | -------------------------------------------------------------------------------- /DevFlowSpec.md: -------------------------------------------------------------------------------- 1 | DevFlow Spec 2 | --- 3 | 4 | - レポジトリの `README.md` をきちんと書く。パブリックのものと等しく管理する。 5 | - 作る前にドキュメントを作る (Designdoc) 6 | - 作ったものに対してドキュメントを残す。 7 | - 何か改善施策を打った時は、ドキュメントを残す。結果が芳しくなかったときも、同じ轍を踏まないために作る。このドキュメントは「やったこと」「成果」「考察」を含む。再現性 / 再利用性 / 透明性を高める。 8 | -------------------------------------------------------------------------------- /GAE.md: -------------------------------------------------------------------------------- 1 | Google App Engine 2 | === 3 | 4 | - Google App EngineのModules・Versionsとqueueやcronの設定ファイルとの関連をいろいろ試してみた。 - The Round : http://knightso.hateblo.jp/entry/2014/07/31/121016 5 | - GAE/Go トランザクション - The Round : http://knightso.hateblo.jp/entry/2014/06/02/102029 6 | 7 | Testing 8 | --- 9 | 10 | - Getting started with RethinkDB, Ginkgo and Martini on wercker : http://blog.wercker.com/2014/02/06/RethinkDB-Gingko-Martini-Golang.html 11 | - Deploying Go to Google App Engine with wercker : http://blog.wercker.com/2013/08/22/Deploying-Go-to-Google-App-Engine.html 12 | - Local Unit Testing for Go - Go — Google Cloud Platform : https://cloud.google.com/appengine/docs/go/tools/localunittesting/ 13 | 14 | BigQuery 15 | --- 16 | 17 | - Google App Engine for GoからBigQueryへStreaming Insertしてみる - The Round : http://knightso.hateblo.jp/entry/2014/07/09/092230 18 | 19 | Cloud Storage 20 | --- 21 | 22 | - T.Yokoyamaのブログ: GAE/GでGoogle Cloud Storageを利用するには(1) : http://takashi-yokoyama.blogspot.jp/2012/08/gaeggoogle-cloud-storage.html 23 | - (Java) appengine-gcs-client - App Engine Clients for Google Cloud Storage - Google Project Hosting : https://code.google.com/p/appengine-gcs-client/ 24 | 25 | Memcache 26 | --- 27 | 28 | - Memcache Go API Overview - Go — Google Cloud Platform : https://cloud.google.com/appengine/docs/go/memcache/ 29 | -------------------------------------------------------------------------------- /GAEJ.md: -------------------------------------------------------------------------------- 1 | Objectify 2 | --- 3 | 4 | いい感じにデータアクセスをしてくれる 5 | 6 | #### クエリ 7 | 8 | ```java 9 | SomeClass entity = ObjectifyService.ofy().load().type(SomeClass.class).filter("id", someId).first().now(); 10 | ``` 11 | 12 | #### 保存 13 | 14 | ```java 15 | ObjectifyService.ofy().save().entity(entity).now(). 16 | ``` 17 | 18 | 簡単。 19 | 20 | ```java 21 | ObjectifyService.register(SomeClass.class); 22 | ``` 23 | 24 | などと事前にやる必要アリ。 25 | 26 | Spring 用の BeanFactory もある。 27 | 28 | - marceloverdijk/objectify-appengine-spring : https://github.com/marceloverdijk/objectify-appengine-spring 29 | 30 | GCS 31 | --- 32 | 33 | ```java 34 | private final GcsService gcsService = 35 | GcsServiceFactory.createGcsService(RetryParams.getDefaultInstance()); 36 | GcsOutputChannel outputChannel = 37 | gcsService.createOrReplace(fileName, GcsFileOptions.getDefaultInstance()); 38 | ObjectOutputStream oout = new ObjectOutputStream(Channels.newOutputStream(outputChannel)); 39 | ``` 40 | 41 | これで OutputStream が取れる。Guava などで 42 | 43 | ```java 44 | ByteStreams.copy(inputStream, oout); 45 | oout.close(); 46 | ``` 47 | 48 | 等と書き込んでやる。 49 | 50 | `multipart/form-data` からファイルをとるのは、Commons Fileupload などを用いる。 51 | 52 | #### ↑ で書き込むとファイルがぶっこわれる 53 | 54 | java - Google Cloud Storage createOrReplace file is broken (different size, ...) - Stack Overflow : http://stackoverflow.com/questions/18214346/google-cloud-storage-createorreplace-file-is-broken-different-size 55 | 56 | 先頭に 20 bytes ほど余計なデータが入るのと、全体的に良く分からないバイトが入って壊れる。 57 | 58 | ```java 59 | GcsOutputChannel outputChannel = gcsService.createOrReplace(new GcsFilename(kBucketName, filename), options); 60 | InputStream in = item.openStream(); 61 | 62 | try { 63 | copy(in, Channels.newOutputStream(outputChannel)); 64 | } finally { 65 | in.close(); 66 | outputChannel.close(); 67 | } 68 | ``` 69 | 70 | などとやればおk。つまり、`ObjectOutputStream` を挟まなければおk。 71 | 72 | References 73 | --- 74 | 75 | - objectify-appengine - The simplest convenient interface to the Google App Engine datastore - Google Project Hosting : https://code.google.com/p/objectify-appengine/ 76 | - Google App Engine for Java Questions - Google App Engine — Google Cloud Platform : https://cloud.google.com/appengine/kb/java 77 | - Google App Engine ~ クエリとその制限 | R-Labs : http://blog.r-learning.co.jp/archives/448 78 | -------------------------------------------------------------------------------- /GameDev--Resources.md: -------------------------------------------------------------------------------- 1 | ゲーム素材 2 | --- 3 | 4 | - http://usui.moo.jp/rpg_icon.html 5 | - http://www.geocities.co.jp/Milano-Cat/3319/muz/002.html 6 | 7 | 8 | - クオリティの高いゲーム・動画素材サイトまとめ! « OpenGameSeeker : http://opengameseeker.com/archives/6496 9 | -------------------------------------------------------------------------------- /Go--beego.md: -------------------------------------------------------------------------------- 1 | beego Web Application Framework 2 | === 3 | 4 | http://beego.me/ 5 | 6 | すごくアグレッシブで面白い感じの Go WAF だった。 7 | 8 | Rails を Go にまるまるポート 9 | --- 10 | 11 | 以下の要素がサポートされている 12 | 13 | 1. Routing (namespace 区切って出来る。あるいは **Annotation** で Controller Action に紐づけた Routing が定義出来る) 14 | 2. Model 15 | 1. ORM 16 | 2. Validation 17 | 3. Callbacks 18 | 3. Controller 19 | 4. Filter (`before_filter`) 20 | 5. Security (CSRF 等) 21 | 6. HTTP <=> Controller のアレコレ全部 22 | 7. i18n 23 | 24 | Rails で出来ることはおおよそ全て出来るっぽい 25 | 26 | Model とかは struct tag を宣言的に書ける要素として使ってる。 27 | 黒魔術っぽくて、色々大丈夫かな〜と思った。 28 | 29 | Automated API document 30 | --- 31 | 32 | ```go 33 | // @Title Get Product list 34 | // @Description Get Product list by some info 35 | // @Success 200 {object} models.ZDTProduct.ProductList 36 | // @Param category_id query int false "category id" 37 | // @Param brand_id query int false "brand id" 38 | // @Param query query string false "query of search" 39 | // @Param segment query string false "segment" 40 | // @Param sort query string false "sort option" 41 | // @Param dir query string false "direction asc or desc" 42 | // @Param offset query int false "offset" 43 | // @Param limit query int false "count limit" 44 | // @Param price query float false "price" 45 | // @Param special_price query bool false "whether this is special price" 46 | // @Param size query string false "size filter" 47 | // @Param color query string false "color filter" 48 | // @Param format query bool false "choose return format" 49 | // @Failure 400 no enough input 50 | // @Failure 500 get products common error 51 | // @router /products [get] 52 | func (c *CMSController) Product() { 53 | 54 | } 55 | ``` 56 | 57 | こんな感じに Annotation を書きまくることによって、swagger doc を自動生成することが出来る。 58 | 注目すべきはこれがフレームワークレベルでサポートされていること。 59 | 60 | 昨今の API の隆盛があるので良い判断だと思った。 61 | 62 | ただし、Go は Annotation を言語レベルでサポートしていないので、IDE の恩恵を受けられず少し辛いと思った。 63 | 64 | 他 65 | --- 66 | 67 | 色々あった。ホントに色々ある。 68 | -------------------------------------------------------------------------------- /Go.md: -------------------------------------------------------------------------------- 1 | 所感 2 | --- 3 | 4 | - python みたいに C が書ける。以上。 5 | - gofmt 勝手にやってくれるの良い。記法が勝手に統一される。 6 | - lint がやたらうるさいのが良い。#lint に細かく書く 7 | - `go get` いいけどどうやってバージョン管理するんだとか、色々なアレがある 8 | - `net/http` が神。 言語レベルでこういうのがあると、エコシステムが構築されやすいだろうなぁ。 9 | 10 | エディタ 11 | --- 12 | 13 | Sublime しかないっぽい。 14 | 15 | プラグインは GoSublime とか使う。不満は 16 | 17 | - 補完ない。何のための静的言語だ 18 | - コンパイルエラーのリアルタイムチェックがない。何のための 19 | - Sublime そもそも色々足りなさ過ぎてつらい。プラグイン色々探すのめどんくさい。 20 | 21 | [追記]あるらしいけど何故か動かない。設定めんどくせ。クソが。 22 | 23 | エラー 24 | --- 25 | 26 | Go は Exception が無い。アグレッシブ。 27 | エラーは日常的なものだから値として扱うらしい。まあ ObjC も `NSError` だしそこまで珍しいデザインな訳ではない。 28 | 29 | なので、 30 | 31 | ```go 32 | value, err = somelib.SomeFunc() 33 | if (err != nil) { 34 | // do some recover 35 | } 36 | ``` 37 | 38 | エラーを捨てるのは `value, _ = somelib.SomeFunc()` とすることでいける。エラーを捨てていることが明示的になって良い。 39 | 40 | Lint 41 | --- 42 | 43 | - 未使用 import 44 | - 未使用 var 45 | - 戻り値を暗黙的に捨てる 46 | 47 | のが lint で怒られる。lint といいつつも、lint 通らないとコンパイル出来ないというアグレッシブさ。良いと思います。 48 | 49 | 要らない変数とか使ってない import とかがイイ感じにコードから消えて実にメンテナブルである。 50 | 51 | 戻り値を暗黙的に捨てる(左に何も置かない)のは禁止されているので、何かを捨てているのが明示的になるのが良い。(`_` に入れると捨てれる。) 52 | 53 | エディタ 54 | --- 55 | 56 | Frameworks 57 | --- 58 | 59 | - [Martini](http://martini.codegangsta.io/) - Sinatra in Go 60 | - [revel](http://revel.github.io/) - Rails in Go 61 | 62 | Libraries 63 | --- 64 | 65 | ###Template 66 | 67 | - [Gold](https://github.com/yosssi/gold) - Jade/Slim like template. has official sublime text plugin. (Ace のほうが推奨?) 68 | 69 | Utilities 70 | --- 71 | 72 | - [gin](https://github.com/codegangsta/gin) - hotreload 73 | 74 | Test 75 | --- 76 | 77 | [Ginkgo](http://onsi.github.io/ginkgo/) が RSpec 風 78 | 79 | ```go 80 | var _ = Describe("Book", func() { 81 | var ( 82 | longBook Book 83 | shortBook Book 84 | ) 85 | 86 | BeforeEach(func() { 87 | longBook = Book{ 88 | Title: "Les Miserables", 89 | Author: "Victor Hugo", 90 | Pages: 1488, 91 | } 92 | 93 | shortBook = Book{ 94 | Title: "Fox In Socks", 95 | Author: "Dr. Seuss", 96 | Pages: 24, 97 | } 98 | }) 99 | 100 | Describe("Categorizing book length", func() { 101 | Context("With more than 300 pages", func() { 102 | It("should be a novel", func() { 103 | Expect(longBook.CategoryByLength()).To(Equal("NOVEL")) 104 | }) 105 | }) 106 | 107 | Context("With fewer than 300 pages", func() { 108 | It("should be a short story", func() { 109 | Expect(shortBook.CategoryByLength()).To(Equal("SHORT STORY")) 110 | }) 111 | }) 112 | }) 113 | }) 114 | ``` 115 | 116 | -------------------------------------------------------------------------------- /Good-Code.md: -------------------------------------------------------------------------------- 1 | 良いコードを書く 2 | === 3 | 4 | オレオレ原則 5 | -- 6 | 7 | 1. メソッドを細かく切る(1 method 5 行以内にしたい) 8 | 2. SRP を徹底する 9 | 3. パブリックな入り口メソッドは宣言的記法を心がける。 10 | 4. 分散してる処理を一カ所にまとめる(Event の処理とかは FRP でやる) 11 | 5. 中身を隠してライブラリにする 12 | 13 | SRP(Single Responsibility Principle) 14 | --- 15 | 16 | メソッド、あるいはクラスの責務を一つだけにする。 17 | 18 | ####BEFORE 19 | 20 | ```rb 21 | def do_hoge_and_fuga 22 | hoge1 23 | hoge2 24 | fuga1 25 | fuga2 26 | fuga3 27 | end 28 | ``` 29 | 30 | hoge 処理と fuga 処理のどちらも面倒を見ることが責務になっており、役割が多過ぎる。 31 | Exception が出た場合のハンドリングも複雑度が増している。 32 | あんまり大したことしてなくてそんなに長くないメソッドだけど、分割した方が良い。 33 | 34 | ####AFTER 35 | 36 | ```rb 37 | def do_hogefuga 38 | hoge 39 | fuga 40 | end 41 | 42 | def hoge 43 | hoge1 44 | hoge2 45 | end 46 | 47 | def fuga 48 | fuga1 49 | fuga2 50 | fuga3 51 | end 52 | ``` 53 | 54 | `do_hogefuga` は `hoge` と `fuga` を呼ぶことだけが責務 55 | `hoge` は hoge を完遂することが責務 56 | `fuga` は fuga を完遂することが責務 57 | 58 | ([TODO] もっとまともなコード例を挙げる) 59 | 60 | ####ポイント 61 | 62 | 1. メソッドをとにかく細かく切る。 63 | 2. 「一つの責務」を深く掘って考える。 64 | * 「A をやって Exception があれば B」くらいの処理も一つにメソッドに入るのは責務が多い。 65 | * "A を呼んで Exception 出るか見守るメソッド", "A", "B" に分ける 66 | 3. 公開されているメソッドには private メソッドの呼び出ししか書いてない、くらいが良い。 67 | 4. 1 method 5 行以内, 多くても 10 行以内。どう考えても単一責任でない。 68 | 5. クラスも出来るだけバンバン分割する。 69 | 70 | ####利点 71 | 72 | 1. unit テストしやすい(逆に、分けなければ困難) 73 | 2. メソッド名がその内容を端的に表し、self-documented である 74 | 3. 1 メソッドが短くて読む人にやさしい(大きいメソッドはつらい) 75 | 76 | ####欠点 77 | 78 | 1. Dalvik の 65k に近づく (method call のオーバーヘッドはそんなにない) 79 | 80 | コンポーネント化 81 | --- 82 | 83 | 意識しなくてよいことを増やす。 84 | 85 | JSON ライブラリの中身は知らなくても JSON を使ったコードは書ける。 86 | このように独立してかつ中身を知らなくてよいコード片を増やしていけば、頭で考える必要のある実コードは少なくなる。 87 | 呼び出す側(アプリケーション)は、呼び出し方だけ意識すればよい。 88 | UI とか、同期処理とかそういったものはコンポーネント化されるべき。 89 | 90 | コンポーネントの「呼び出し」は自然とコードが宣言的になるので、アプリの実コードも読みやすくなってよい。 91 | 92 | また、状態と責務がそれぞれのコンポーネントで閉じる。 93 | コンポーネントの状態の管理をコンポーネントに任せられる。 94 | アプリは自身の状態だけ管理すればよい。 95 | 96 | 最終的に独立したコンポーネントの組み合わせだけでアプリが完成するくらいがよい。 97 | 98 | ####利点 99 | 100 | 1. unit テストがしやすい 101 | 2. 責務があやふやにならない。それぞれのコンポーネントの挙動は自身の責務 102 | 103 | コメント 104 | --- 105 | 106 | コメントが一切ないコードはつらい。 107 | どんなに self-documented なコードでも、処理全体の流れは追わないと分からない。 108 | 従って、「処理全体の流れ」は最優先でコメントに書くべきことである。(あるいはドキュメント) 109 | コードに現れない情報というのは掘ってみると沢山ある。 110 | 111 | 1. 処理全体がどういう流れになっているのか? 112 | 2. なぜこれを作ったのか? 113 | 3. なぜこういうコード / 処理の流れになったか? 114 | 4. どんな懸念点があるか? 115 | 5. このクラスはどういう責務を担っているのか?また、コード全体の中でどういう位置付けにあるのか? 116 | 6. どの URL を参照してこのコードを書いたか? 117 | 118 | これらは出来るだけ考えたままにコメントに残すべきである。 119 | メタ情報のコメントは多ければ多いほどいい。 120 | -------------------------------------------------------------------------------- /Haxe.md: -------------------------------------------------------------------------------- 1 | Haxe 2 | === 3 | 4 | Java みたいな構文で JavaScript が書ける。 5 | 型推論があるから Java よりも Scala とか Groovy とか Swift って感じ。 6 | 7 | TypeScript は JavaScript に型を付けただけ、って感じ。Haxe はそもそも根本から構文が違う。 8 | 9 | JavaScript, 型とか継承をたくさんするクラスシステムとかをあまり使うことが少ないように思うので、どれだけ効果があるんだろう。 10 | 現状、既存ライブラリとの兼ね合いが型のある恩恵よりもつらみ、みたいな感じのように思う。 11 | 12 | が、HTML5 ゲーム等大規模になってくると恩恵あるのだろうな、というイメージ。 13 | 14 | ```haxe 15 | class Test { 16 | static function main() { 17 | var people = [ 18 | "Elizabeth" => "Programming", 19 | "Joel" => "Design" 20 | ]; 21 | for (name in people.keys()) { 22 | var job = people[name]; 23 | trace('$name does $job for a living!'); 24 | } 25 | } 26 | } 27 | ``` 28 | 29 | エディタ 30 | --- 31 | 32 | http://old.haxe.org/com/ide 33 | 34 | いい感じの IDE は無い。Sublime ぽい。このへん Go と似た感じ。 35 | 36 | せっかく型があって補完とかコンパイルエラーいい感じなのに IDE のエコシステムが弱いのは残念。 37 | Sublime もプラグイン次第で色々出来るのだろうか? 38 | 39 | https://github.com/HaxeIDE 40 | 41 | intellij-haxe とかある. あと atom-autocomplete 42 | 43 | 44 | ライブラリとの連携 45 | --- 46 | 47 | Extern を使う。外部の JS ライブラリに明示的に型を付けて Haxe の型システムのエコシステムに取り込むことが出来る。 48 | 49 | mizchi 氏による vue.js の extern とかある。 50 | 51 | 標準ライブラリ 52 | --- 53 | 54 | 色々な標準ライブラリがサポートされてる。 55 | 56 | template とかある ([TODO] JS でこれ使うとコンパイル時に template のコードがひっつくのだろうか?フットプリント気になる) 57 | 58 | http://old.haxe.org/doc/cross/template 59 | 60 | -------------------------------------------------------------------------------- /ImageCompression.md: -------------------------------------------------------------------------------- 1 | ImageCompressin 2 | === 3 | 4 | - mozjpeg - jpeg compatibility を維持して 5% くらい圧縮する 5 | - WebP - すごく軽くなる。20% くらい軽くなる。最適化も勝手に施してくれる。実験 ⇒ https://www.dropbox.com/sh/isndq1fk5ngw8vj/AACaILEdemE1tbPaIth2Lnz7a 6 | - jpegoptim - 普通に最適化 7 | - JPEGmini - jpeg 10% くらい軽くなる。人間の視覚的なアレをアレした手法らしい。まともに使うのにはカネが要る。 8 | 9 | スマホの写真 10 | --- 11 | 12 | iPhone で撮った写真は最適化というか圧縮処理が全くなされていない。 13 | 簡単に 2 MB とかいくけど、ちゃんと圧縮すれば 500 KB とかになる。 14 | -------------------------------------------------------------------------------- /Java--AppEngine.md: -------------------------------------------------------------------------------- 1 | - [Cache-Control を設定する](#cache-control) 2 | - [Memcache を効果的に使う](#memcache) 3 | - [AppStats を設定しておく](#appstats) 4 | - [Request, Response 毎に Body をログしておく](#request-log) 5 | - [Google Cloud Storage を使う](#google-cloud-storage) 6 | - [重い処理には Task Queue を使う](#task-queue) 7 | - [独自ドメイン / SSL の設定の仕方](#ssl-domain) 8 | 9 | Cache-Control 10 | --- 11 | 12 | `Cache-Control` ヘッダを設定することで、結果の View 自体を丸ごと Edge キャッシュしてもらうことが出来る。 13 | 14 | `Cache-Control: public, max-age:60` 15 | 16 | ただし、**Evict 出来ない**, **最終更新時間によらず、クライアントは必ずキャッシュを参照してしまう** ので `max-age` は小さめに抑えた方が良い。 17 | 18 | これは Google Cloud Storage も同様のことが可能。 19 | 20 | 参考: http://qiita.com/sinmetal/items/37c105a098174fb6bf77 21 | 22 | Memcache 23 | --- 24 | 25 | Memcache は重要。なんせ READ/WRITE ともに無料。 26 | 27 | Spring の `@Cacheable` とかでやるか、Datastore の Read/Write をハイジャックするとか。 28 | `@Cacheable` を `@RequestMapping` のメソッドに付けることでそもそもの 29 | 30 | AppStats 31 | --- 32 | 33 | AppStats を設定しておくことで、RPC にかかった時間やコストを見える化 / ログすることが出来る。 34 | 35 | ```xml 36 | 37 | appstats 38 | com.google.appengine.tools.appstats.AppstatsFilter 39 | 40 | logMessage 41 | Appstats available: /appstats/details?time={ID} 42 | 43 | 44 | 45 | appstats 46 | /* 47 | 48 | ``` 49 | 50 | [Blog @vierjp : 17.Appstats(Java)でRPCのコストと処理時間を調べてみよう](http://blog.vier.jp/2013/02/appstatsjavarpc.html) 51 | 52 | Request Log 53 | --- 54 | 55 | 標準では Request と Response の Body がログされないので、Servlet Filter とかで毎回ログをフィルタリングしておく。 56 | 57 | また、Cron で毎時とか Logs を Fetch して BigQuery とかに飛ばしておくと良い。 58 | 59 | Google Cloud Storage 60 | --- 61 | 62 | [GoogleAppEngine - GAE/jでGCS Default Bucketを使う - Qiita](http://qiita.com/sinmetal/items/f2f7e0fe444b7e000a61) 63 | 64 | Google Cloud Storage
Java Client Library Overview - Java — Google Cloud Platform : https://cloud.google.com/appengine/docs/java/googlecloudstorageclient/ 65 | 66 | Task Queue 67 | --- 68 | 69 | 超気楽に Task をキューイングすることが出来る。`TaskManager` クラスとか作って次みたいな感じで呼べるようにしておく。 70 | 71 | ```java 72 | taskManager.addHogeTask("some", "parameter"); 73 | 74 | // QueueFactory.getDefaultQueue.add(withUrl("/_task/hoge").addParam("someParam", "some").addParam("hogeParam", "parameter")); 75 | ``` 76 | 77 | SSL Domain 78 | --- 79 | 80 | 04.Google App Engineで独自ドメイン&SSL(2/2)|CA Beat エンジニアのブログ : http://ameblo.jp/cabeat-e/entry-11395919479.html 81 | 82 | References 83 | --- 84 | 85 | - Blog @vierjp : 17.Appstats(Java)でRPCのコストと処理時間を調べてみよう : http://blog.vier.jp/2013/02/appstatsjavarpc.html 86 | - Google App Engine / Python 上での開発で最初から知ってればよかった、ってことをいくつか - Masatomo Nakano Blog : http://blog.madoro.org/mn/90 87 | - GoogleAppEngine - GAE/jでGCS Default Bucketを使う - Qiita : http://qiita.com/sinmetal/items/f2f7e0fe444b7e000a61 88 | - appengine ja night 16 BT Frontend cache control : http://www.slideshare.net/bluerabbit777jp/appengine-ja-night-16-bt-frontend-cache-control 89 | - GoogleAppEngine - GCP エッジキャッシュ - Qiita : http://qiita.com/sinmetal/items/37c105a098174fb6bf77 90 | -------------------------------------------------------------------------------- /Java--SpringMVC.md: -------------------------------------------------------------------------------- 1 | Spring 2 | --- 3 | 4 | Spring 自体は DI フレームワーク. 5 | Spring MVC という下位プロジェクトが WAF. 6 | 7 | 旧来は xml をそこそこ書く必要があったが、今は Spring Boot があるのでアノテーションでイイ感じに設定が出来るようになっている。 8 | 9 | Spring Boot 10 | --- 11 | 12 | ```java 13 | @Configuration 14 | @ComponentScan(basePackages = "com.kaiinui.someapp") 15 | @EnableAutoConfiguration 16 | class Application { 17 | public static void main(String[] args) { 18 | SpringApplication.run(Application.class, args); 19 | } 20 | } 21 | ``` 22 | 23 | これで `@Controller` とかをイイ感じに認識してくれるようになる。 24 | 25 | Controller 26 | --- 27 | 28 | Rails などと違い、Spring MVC では Controller にて path を指定する。 29 | 30 | ```java 31 | @RestController 32 | public class BookController { 33 | @RequestMapping("/books/{id}") 34 | public Book getBook(@PathVariable String id) { 35 | return new Book("Harry Potter and the Sorcerer's Stone", "J. K. Rowling"); 36 | } 37 | } 38 | ``` 39 | 40 | DI 41 | --- 42 | 43 | Spring の目玉は DI. 次のように Bean を書いておけば、`@Autowired` で勝手に入ってくれる。 44 | 45 | ```java 46 | @Configuration 47 | @ComponentScan 48 | @EnableAutoConfiguration 49 | public class Application { 50 | @Bean 51 | public DataStoreService dataStore() { 52 | return new DataStoreFactory.getDataStoreService(); 53 | } 54 | } 55 | ``` 56 | 57 | ```java 58 | @RestController 59 | public class BookController { 60 | @Autowired 61 | DataStoreService dataStoreService; 62 | 63 | @RequestMapping("/books/{id}") 64 | public Book getBook(@PathVariable String id) { 65 | // ここで dataStoreService を使える。 66 | } 67 | } 68 | ``` 69 | 70 | モックを外部から突っ込んだり出来てテストに便利。 71 | 72 | テスト 73 | --- 74 | 75 | `SpringJUnit4ClassRunner` を `@RunWith` で指定することでテストが出来るようになる。 76 | あとは Spring Boot の Configuration クラスの指定に `@SpringApplicationConfiguration`. 77 | Web MVC をテストしたい場合は `@WebAppConfiguration` を付ける。 78 | 79 | ```java 80 | @RunWith(SpringJUnit4ClassRunner.class) 81 | @SpringApplicationConfiguration(classes = Application.class) 82 | @WebAppConfiguration 83 | class SomeTests { 84 | 85 | } 86 | ``` 87 | 88 | これだけでは HTTP のテストは出来ない。`@IntegrationTest` を付けることで、サーバを起動してくれるようになる。 89 | 90 | ```java 91 | @RunWith(SpringJUnit4ClassRunner.class) 92 | @SpringApplicationConfiguration(classes = Application.class) 93 | @WebAppConfiguration 94 | @IntegrationTest 95 | class SomeIntegrationTest { 96 | 97 | } 98 | ``` 99 | -------------------------------------------------------------------------------- /Java--gradle.md: -------------------------------------------------------------------------------- 1 | gradle 2 | --- 3 | 4 | - `gradle-idea-plugin`: IntelliJ IDEA と gradle の云々をイイ感じに連携出来る(gradle で入れた dependencies を認識させたり) 5 | - `gradle-appengine-plugin`: イイ感じに appengine を触らせてくれる 6 | -------------------------------------------------------------------------------- /KPI.md: -------------------------------------------------------------------------------- 1 | ソーシャルゲームのKPI分析に参考になりそうな資料 | Now or Never : http://www.gologo13.com/2014/10/07/social-game-kpi-analytics/ 2 | -------------------------------------------------------------------------------- /Management--DRI.md: -------------------------------------------------------------------------------- 1 | Apple の Directly Responsible Individual (DRI) 2 | --- 3 | 4 | Apple には Directly Responsible Individual (DRI) というのがあり、毎回、各アクション毎に "DRI" を設定する。 5 | アクションとは、プロジェクトを構成する一つの単位。 6 | 7 | DRI に設定された人は、自身が責務を持つ事柄について、絶対の責任を持つ。 8 | もし達成されていなければ、SJ が DRI に設定された人を徹底的に絞り上げる(笑) 9 | 10 | DRI はマネージャのようなもの。 11 | しかし、流動的に設定されるので、組織はフラットに保たれる。また、DRI に設定された人は、有る程度の権限も持ち、チームを「監督」、というか、DRI を達成するために奔走することとなる。 12 | 13 | References 14 | --- 15 | 16 | - (48) How well does Apple's Directly Responsible Individual (DRI) model work in practice? - Quora : http://www.quora.com/How-well-does-Apples-Directly-Responsible-Individual-DRI-model-work-in-practice 17 | -------------------------------------------------------------------------------- /Marketing--iOS.md: -------------------------------------------------------------------------------- 1 | iOS のマーケ関連 2 | === 3 | 4 | ツール 5 | --- 6 | 7 | - iOSアプリを開発するときに使ってる便利なサービス - Qiita : http://qiita.com/koogawa/items/6e3303f61fd58b1e31b1 8 | - App Store reviews, rankings & ASO search emailed straight to your inbox with Appbot. : https://appbot.co/ 9 | - レビュー追ってくれたり、翻訳してくれたり。あとは、Review Prompt とかの App Growth 関連のツールを AppboxX という名前で提供している 10 | - AppAnnie 11 | -------------------------------------------------------------------------------- /MobileDev--Architecture.md: -------------------------------------------------------------------------------- 1 | Mobile Architecture 2 | === 3 | 4 | - http://www.slideshare.net/mokemokechicken/iosandroidmodel - iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い 5 | - http://d.hatena.ne.jp/tateisu/20100629/1277814950 - Androidアプリの間違った作り方 6 | -------------------------------------------------------------------------------- /Others--ID-generating.md: -------------------------------------------------------------------------------- 1 | ID 生成器 2 | === 3 | 4 | MySQL では auto-increment で increment な ID を用いる。これはアルゴリズムが単純かつ順序を保存し、かつ少ない領域で保存出来る利点がある。 5 | 6 | しかし、単一の生成器でしか ID を生成出来ないという欠点がある。ゆえに、分散システムとの相性が悪い。 7 | また、timestamp 情報を含められないので、`created_at` など別カラムとして生成日を保管する必要がある。 8 | 9 | SnowFlake 10 | --- 11 | 12 | Twitter では対応として、SnowFlake という分散 ID 生成器を用いている。 13 | 14 | * 63 bit で表される (long int) 15 | * timestamp を含む(ゆえに、順序が保存される) 16 | * 1024 台までの生成器で安全に ID を生成出来る。 17 | 18 | bit layout は以下のようにデザインされている。 19 | 20 | * timestamp: 41bit 21 | * machine id: 10bit 22 | * sequence: 12bit 23 | 24 | ただし、timestamp は unixtime ではなく特定の日の unixtime を引いた値となっている(これにより bit 数を節約) 25 | 26 | sequence では increment に値を付加し、同一 timestamp での ID 衝突を防ぐ。 27 | 28 | Device-side ID generating では? 29 | --- 30 | 31 | デバイス側で ID を生成したい際どうするか? 32 | まず machine id は 10bit では全然足りないし、 sequence も 12bit も必要ない。 33 | 34 | しかし、22 bit を全力で振り切っても、たった 400 万程度しかない。 35 | 128 bit 無いと timestamp + device id + sequence でのユニーク化は難しい気がする… 36 | 37 | が、実際はデバイス内でのユニーク性だけあればよく、マスター側でのユニークは device id + item id で担保すればよく、device id を id に含めなくて良いのかもしれない。 38 | 39 | 参考 40 | --- 41 | 42 | - http://qiita.com/daisy1754/items/98a6e6b17d8161eab081 43 | - http://developer.smartnews.be/blog/2013/07/31/shakeflake-is-a-tool-for-generating-unique-id-numbers/ 44 | - http://siguniang.wordpress.com/2013/03/17/stop-using-numbers-as-ids-just-use-uuids/ 45 | -------------------------------------------------------------------------------- /PDCA.md: -------------------------------------------------------------------------------- 1 | - http://wazanova.jp/items/1488 2 | 3 | >また、Netflixがブログで、A/Bテストのシステムについて紹介しています。 4 | > 5 | > スライドの情報だけなので、A/Bテストの結果からどうやって意思決定しているかまでは不明ですが、 6 | > 7 | > 7回のテストで、2,097,152通りのユニークなパターン。 8 | > 年に数百件の新たなA/Bテストを実施。 9 | > テンプレ: 2,105、CSS: 566、JavaScript: 685 10 | > プッシュサイクル毎に、250万個のユニークなCSS/JavaScriptのパッケージ 11 | -------------------------------------------------------------------------------- /Phaser.md: -------------------------------------------------------------------------------- 1 | Phaser 2 | === 3 | 4 | MIT ライセンスの HTML5 2D ゲームフレームワーク 5 | 6 | MVP のコード 7 | 8 | ```js 9 | var game = new Phaser.Game(800, 600, Phaser.AUTO, 'phaser-example', { preload: preload, create: create }); 10 | 11 | function preload() { 12 | game.load.image('mushroom', 'assets/sprites/mushroom2.png'); 13 | } 14 | 15 | function create() { 16 | var test = game.add.sprite(200, 200, 'mushroom'); 17 | } 18 | ``` 19 | 20 | (実際は Haxe とか TypeScript で書く。) 21 | 22 | かなりミニマルにかけていい感じ。コード量としては enchant.js とかとあんまり変わらない感ある。 23 | 24 | ![](http://cdn-ak.f.st-hatena.com/images/fotolife/s/syonx/20140705/20140705093433.png) 25 | 26 | Flappy Bird とか簡単にかける 27 | 28 | Compatibility 29 | --- 30 | 31 | > Internet Explorer 9+, Firefox, Chrome, Safari and Opera. It also works on mobile web browsers including stock Android 2.x browser and above and iOS5 Mobile Safari and above 32 | 33 | パフォーマンス 34 | --- 35 | 36 | Pixi.js を描画エンジンとして用いていて、 37 | 38 | - Hardware-Accelaration aware である 39 | - DOM + CSS anim で動くモード 40 | - WebGL / 2D で動くモード 41 | - とにかくパフォーマンスが良い 42 | 43 | Footprint 44 | --- 45 | 46 | 576 KB くらいある。128 KB gzipped. 47 | 48 | enchant.js みたいなミニマルなやつも本体だけで 220 KB くらい. プラグインとか physics とか付けると 1MB 簡単に超えるので他と比較したら相当軽い。 49 | 50 | 576 KB というのも物理エンジン(3 種類)込みの話であって、抜くと 311 KB minified, 67 KB gzipped とかになるとのこと.軽い。 51 | 52 | 標準でサポートされてる機能 53 | --- 54 | 55 | - Preloaders 56 | - Sprite 57 | - **Physics** 58 | - **Collision Detection** 59 | - Animatin 60 | - Particle 61 | - Tilemap 62 | 63 | などなど 64 | 65 | 足りなそうなの 66 | 67 | - ネットワーク関連無いので、自前で書く必要ある。 68 | - `Scene` が何故か無いので `State` をイイ感じに使ってちょめちょめする必要がある。 69 | - クソ重い Phaser をロードするブートストラッパーが無いので、ロード画面とか良い感じにするには bootstrapper を書く必要がある 70 | 71 | ###Sprite 72 | 73 | `Sprite` はけっこう充実していて、`.angle` とかある。これを弄るだけでスプライトが回転してくれるっぽい(回転の transition とか設定できるのかな?) 74 | Flappy Bird の bird の角度とかも簡単に出来る。 75 | 76 | もちろん Sprite Animation も対応している。 77 | 78 | チュートリアルとか 79 | --- 80 | 81 | - Flappy Bird をつくる http://blog.lessmilk.com/make-html5-games-with-phaser-1/ 82 | 83 | http://syonx.hatenablog.com/entry/2014/07/05/103418 にまとまっている 84 | 85 | エディタ 86 | --- 87 | 88 | - TypeScript, JavaScript ともに WebStorm が良い 89 | 90 | 色んな対応状況 91 | --- 92 | 93 | WebGL 描画がハイパフォーマンスで、対応してないブラウザは自動的に Canvas 描画にフォールバックされる。 94 | 95 | モダンブラウザは殆ど対応。モバイルは 96 | 97 | - Safari -> 8 以上が WebGL 描画 (Photon Storm » Blog Archive » A first look at what iOS8 means for Phaser and Pixi.js (hint: bunnies, LOTS of them!) : http://www.photonstorm.com/html5/a-first-look-at-what-ios8-means-for-phaser-and-pixi-js-hint-bunnies-lots-of-them) 98 | - Android は最新の Chrome がWebGL 描画。標準ブラウザは Canvas 99 | 100 | 参考リンク 101 | --- 102 | 103 | - HTML5ゲームエンジン「Phaser」が初心者とモバイルにやさしくていい感じです http://syonx.hatenablog.com/entry/2014/07/05/103418 104 | - Phaser まとめ http://syon-wiki.herokuapp.com/Phaser 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | note 2 | ==== 3 | 4 | My notes. 5 | 6 | List 7 | --- 8 | 9 | ###UX 10 | 11 | - https://github.com/kaiinui/list-awesome_ux 12 | 13 | ###Android Lib 14 | 15 | - https://github.com/kaiinui/android-awesome-libraries 16 | 17 | ###iOS Lib 18 | 19 | - https://github.com/kaiinui/ios-awesome-libraries 20 | 21 | ###API 22 | 23 | - https://github.com/kaiinui/api_design-resources 24 | 25 | ###DevFlow 26 | 27 | - https://github.com/kaiinui/list-dev_flow 28 | 29 | ###SEO 30 | 31 | - https://github.com/kaiinui/list-seo 32 | 33 | ###QR 34 | 35 | - https://github.com/kaiinui/QR-ios 36 | - https://github.com/kaiinui/QR-android 37 | -------------------------------------------------------------------------------- /Recruit.md: -------------------------------------------------------------------------------- 1 | Recruit 2 | === 3 | 4 | 面白かったネタ 5 | --- 6 | 7 | - 最も好きな言語と、最も嫌いな言語をそれぞれ 3 つずつ挙げてもらう 8 | 1. そもそも言語をどれくらい使ったことがあるのかがわかる 9 | 2. 動的言語が好きなのか、静的言語が好きなのか、どのような開発スタイルなのかが分かる。 10 | 3. 実践派なのか理論派なのか分かる。 11 | 12 | ところてん @tokoroten · 6 分 13 | ヘッドハンターから届いたお手紙を社内で公開したら、ボーナスで1万円っていう社内制度を思いついた。 14 | 外部発表しまくって、会社のレピュテーションを向上させることにインセンティブが発生する上、社員の引き抜き防止になるので、Win-Winの関係になるんじゃないか。 15 | -------------------------------------------------------------------------------- /Scraping--BestPractices.md: -------------------------------------------------------------------------------- 1 | Scraping BestPractices 2 | === 3 | 4 | Crawler と Scraper を分離する 5 | --- 6 | 7 | Crawler (集める係) と Scraper (解析する係) を同じ系で管理してしまうと、実際的には行儀が悪い。 8 | 9 | 普通にやれば、Crawler がダウンロードしたものを、同一の系で Scraper が即座に解析するフローとする。 10 | しかし、これは以下の点で最悪のフローである。 11 | 12 | * 野生の HTML はまともなものばかりではないので、実際的には Scraper は簡単に失敗する。(e.g. サイトのデザインが変わった、このページだけ特別、キャンペーンで特別なページが出来た etc..) 13 | * その際に、動かし方が悪ければ最悪 Crawler が引っ張られて死ぬ。 14 | * タスクを永続化して管理していないので、Scrape タスクが失敗してしまえば、再開も出来ない。(タスク管理の状態が失われる) 15 | 16 | 以上より、Crawler と Scraper は分離したほうがよい。具体的には、 17 | 18 | * Crawler は常時駆動し、ただ URL を集めて HTML とアセットをダウンロードする (S3 等に保存することが多い) 19 | * その際、SQS などを用いて、キューイングする。 20 | * Scraper は SQS に貯められたキュー駆動で動き、S3 から HTML をダウンロードし解析。結果を DB などに永続化する 21 | 22 | というフローになる。 23 | 24 | Crawler はより愚直に、如何に BAN されないかだけ考えて、URL と HTML を集めていれば良い。 25 | 26 | Scrapy であれば、Item Pipeline に様々な処理を書く所を、S3 にアップロードして SQS にキューイングするだけの処理とすればよい。 27 | 28 | Scraper は何の言語 / フレームワークで書いても良い。 29 | 30 | IP を分散する (Proxy を用いてダウンロードする) 31 | --- 32 | 33 | IP は分散すればするだけ BAN されにくくなる。 34 | また、IP を簡単に入れ替える構成を作っておけば、一旦 BAN されてしまっても容易に復旧することが出来る。 35 | 36 | このために Crawler の IP を入れ替えても良いが、より簡便には、Proxy を通してダウンロードするようにしておけば、より役割分担が明確になる。 37 | すなわち、Proxy が「IP をいい感じにして BAN されないようにダウンロードする」責務を持てば良い。 38 | 39 | この as a Service として [Crawlera](http://crawlera.com/) がある。 40 | 41 | PhantomJS を使う 42 | --- 43 | 44 | JS を使って HTML を描画するサービスが増えてきているので、単純な HTML パースでは対応出来ないことも多い。 45 | 46 | Selenium WebDriver などを用いて、実際のブラウザを動かしても良いが、実際的には PhantomJS がお手軽で速くて良い。 47 | 48 | Scraper は構造定義ファイルを元に HTML を解析する 49 | --- 50 | 51 | `nokogiri` などでパースして解析するベタ書きでは、複数のサイトに跨がるスケールは難しい。 52 | 53 | 実際的には、サイト / ページの構造を定義したファイルを用意しておく。こうすれば、動いている Scraper のソースに触らず、様々なサイトに対応することが出来る。 54 | 55 | #### サイトの構造 56 | 57 | * Base URL 58 | * 取得したいページのパターンの配列 59 | 60 | #### ページの構造 61 | 62 | * URL のパターン(正規表現で表されることが多い) 63 | * 取得要素の配列 64 | * XPath / CSS Path (XPath のほうが表現が強力) 65 | * 名称 (`price` や `name` など) 66 | 67 | 失敗した Scrape を解析する 68 | --- 69 | 70 | パターンが変わっていれば対応しなければならないので、失敗した Scrape は常に追いかけられるようにしておく。 71 | 72 | References 73 | --- 74 | 75 | - Scrapy | An open source web scraping framework for Python : http://scrapy.org/ 76 | - Crawlera : http://crawlera.com/ 77 | - PhantomJS | PhantomJS : http://phantomjs.org/ 78 | - PythonとかScrapyとか使ってクローリングやスクレイピングするノウハウを公開してみる! - orangain flavor : http://orangain.hatenablog.com/entry/scrapy 79 | - ScrapyとPhantomJSを用いたスクレイピングDSL : http://www.slideshare.net/MasayukiIsobe/web-scraping-20140622isobe 80 | -------------------------------------------------------------------------------- /Scraping--Scrapy.md: -------------------------------------------------------------------------------- 1 | Scrapy 2 | === 3 | 4 | Scrapy はイイ感じにモジュラな設計になっているスクレイピングフレームワーク。Python 製。ただし 2 系。 5 | 6 | Scrapy は以下のような設計になっている。 7 | 8 | ![](http://cdn-ak.f.st-hatena.com/images/fotolife/m/mi_kattun/20140104/20140104221104.jpg) 9 | 10 | Spider で対象となる URL をかき集め、Downloader で対象 URL をダウンロードし、それを Item Pipeline で処理し、結果を永続化する。 11 | Scheduler は BAN 対策のためのスケジュール調整のストラテジーを担当する。 12 | 13 | 他のスクレイピングフレームワークとの比較 14 | --- 15 | 16 | - anemone (Ruby): 必要最低限の機能(同一 URL 防止、リンク抽出、メインループ)しか提供しておらず、使えない。 17 | - Apache Nutch (Java): スゴく色々揃ってるような気がする。が、ゆるい情報が少なくて辛い。Scrapy と比べるとコミュニティは弱い。 18 | 19 | 実際 20 | --- 21 | 22 | 以下のような Spider を書くことで、リンクを次々と辿っていく形の Spider を作ることが出来る。 23 | 24 | ```py 25 | # coding: utf-8 26 | 27 | from datetime import datetime 28 | 29 | from scrapy.contrib.spiders import CrawlSpider, Rule 30 | from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 31 | from scrapy.selector import Selector 32 | 33 | from helloscrapy.items import NewsItem 34 | 35 | 36 | class CNetSpider(CrawlSpider): 37 | name = 'cnet' 38 | allowed_domains = ['news.cnet.com'] 39 | start_urls = [ 40 | 'http://news.cnet.com/8324-12_3-0.html', 41 | ] 42 | rules = [ 43 | # 正規表現 'begin=201312' にマッチするリンクを辿る 44 | Rule(SgmlLinkExtractor(allow=(r'begin=201312', ), restrict_xpaths=('/html', ))), 45 | # 正規表現 '/[\d_-]+/[^/]+/$' にマッチするリンクをparse_newsメソッドでパースする 46 | Rule(SgmlLinkExtractor(allow=(r'/[\d_-]+/[^/]+/$', ), restrict_xpaths=('/html', )), 47 | callback='parse_news'), 48 | ] 49 | 50 | def parse_news(self, response): 51 | item = NewsItem() 52 | 53 | sel = Selector(response) 54 | item['title'] = sel.xpath('//h1/text()').extract()[0] 55 | item['body'] = u'\n'.join( 56 | u''.join(p.xpath('.//text()').extract()) for p in sel.css('#contentBody .postBody p')) 57 | item['time'] = datetime.strptime( 58 | sel.xpath('//time[@class="datestamp"]/text()').extract()[0].strip()[:-4], 59 | u'%B %d, %Y %I:%M %p') 60 | 61 | yield item 62 | ``` 63 | 64 | (出典: http://orangain.hatenablog.com/entry/scrapy) 65 | 66 | References 67 | --- 68 | 69 | - ScrapyとPhantomJSを用いたスクレイピングDSL : http://www.slideshare.net/MasayukiIsobe/web-scraping-20140622isobe 70 | - PythonとかScrapyとか使ってクローリングやスクレイピングするノウハウを公開してみる! - orangain flavor : http://orangain.hatenablog.com/entry/scrapy 71 | - Scrapy 0.24 documentation — Scrapy 0.24.4 documentation : http://doc.scrapy.org/en/latest/index.html 72 | -------------------------------------------------------------------------------- /Team--Performance.md: -------------------------------------------------------------------------------- 1 | 効率の良い開発 2 | === 3 | 4 | 効率の良さは、開発の周辺環境の整備によって成される。 5 | 6 | 周辺環境とは何か? 7 | 8 | まず前提として、 9 | 10 | 1. 良い PC, キーボード、椅子 11 | * 速い CPU はビルドの時間を減らす 12 | 2. 良いエディタ 13 | * IDE の支援を受ける 14 | * 静的解析 15 | * コードフォーマット 16 | 17 | そして、 18 | 19 | 1. 様々な面倒を減らすライブラリ郡 20 | * プラットフォーム差異の吸収 21 | * プラットフォーム固有の複雑さの隠蔽 22 | * 複雑な例外・フロー処理の隠蔽 23 | * ログ・フィードバック・エラーハンドリングなどの定型処理 24 | * 統一された UI フレームワーク 25 | * UI コンポーネント 26 | * 様々なショートハンド(これは実はそこまで効果ないと思う) 27 | 2. 効率の良いテスト環境 28 | * 効率の良いテスト環境は、開発を高速化する 29 | 3. マネージレスなインフラ 30 | * インフラの構築・管理は開発を低速化させる要因 31 | 4. 良いワークフローと情報共有 32 | * 文言やデザイン、i18n などのワークフローが統合されているか。 33 | * PR や issue がきちんと機能しているか。 34 | * きちんとドキュメントされているか 35 | * また、簡単にドキュメント出来る環境 36 | * 実装の怪しい箇所は共有出来ているか。 37 | * また、簡単に「悩み」が共有出来る環境 38 | 39 | これらが完璧になされている環境は、Google. 40 | 41 | Google 自体が巨大なフレームワークであり、開発者は Google というフレームワークに乗って開発をする。 42 | -------------------------------------------------------------------------------- /Test--AppThwack.md: -------------------------------------------------------------------------------- 1 | AppThwack 2 | === 3 | 4 | 200 種類以上あるデバイス(Android, iOS)でテスト出来る。 5 | 6 | 1200 Device * Minute が月額 $100 とか。 7 | 8 | 対応テストフレームワーク 9 | --- 10 | 11 | - Appium (iOS, Android) 12 | - UIAutomation (iOS) 13 | - UIAutomator (Anrdoid) 14 | - KIF (iOS) 15 | - MonkeyTalk (iOS, Android) 16 | - Espresso (Android) 17 | - Calabash (iOS) 18 | 19 | ### Unit 20 | 21 | - XCTest (iOS) 22 | - JUnit (Android) 23 | 24 | 起動オプション 25 | --- 26 | 27 | 以下の起動オプションを設定することが出来る。 28 | 29 | * 言語 30 | * 場所 (latitude, longitude) 31 | * ネットワークの制約 32 | 33 | References 34 | --- 35 | 36 | - AppThwack Documentation | AppThwack : https://appthwack.com/docs/api 37 | -------------------------------------------------------------------------------- /Test--Saucelabs.md: -------------------------------------------------------------------------------- 1 | Saucelabs 2 | === 3 | 4 | 色々用意されたブラウザを用いてテストすることが出来る。 5 | テストは Selenium. 実際的には、例えば Ruby なら Capybara 等でテストすることになる。 6 | 7 | ```rb 8 | // sauce_helper.rb 9 | 10 | require "sauce" 11 | require "sauce/capybara" 12 | 13 | # Set up configuration 14 | Sauce.config do |c| 15 | c[:browsers] = [ 16 | ["Windows 8", "Internet Explorer", "10"], 17 | ["Windows 7", "Firefox", "20"], 18 | ["OS X 10.8", "Safari", "6"] 19 | ] 20 | end 21 | ``` 22 | 23 | ```rb 24 | // spec_helper.rb 25 | 26 | require 'capybara/rspec' 27 | include Capybara::DSL 28 | 29 | require_relative 'sauce_helper' 30 | 31 | Capybara.default_driver = :sauce 32 | ``` 33 | 34 | ```rb 35 | // feature/request_spec.rb 36 | 37 | require_relative 'spec_helper' 38 | 39 | describe "Request", :sauce => true do 40 | it "should show /" do 41 | visit "http://example.com/" 42 | expect(page).to have_css("img") # Assume it has the Logo 43 | end 44 | end 45 | ``` 46 | 47 | みたいな感じでやる。 48 | 49 | 実際的には Request Spec しても仕方ないので、Screenshot を撮って比較する。 50 | 51 | テストしたい主眼は、 52 | 53 | 1. Responsive Web Design (ちゃんと意図通りに Fallback 出来ているか / デザインが崩れていないか) 54 | 2. JavaScript のブラウザ互換性 55 | 56 | References 57 | --- 58 | 59 | - Sauce Labs: Selenium Testing, Mobile Testing, JS Unit Testing and More : https://saucelabs.com/ 60 | -------------------------------------------------------------------------------- /Test--list--BDDmatchers.md: -------------------------------------------------------------------------------- 1 | 各言語の Rspec 風のやつ 2 | --- 3 | 4 | `.to.equal()` みたいに書けないとつらい 5 | 6 | * Android - AssertJ https://github.com/square/assertj-android 7 | * iOS - Specta https://github.com/specta/specta (+ Expecta / OCMockito) 8 | * Go - Ginkgo http://onsi.github.io/ginkgo/ 9 | * JavaScript - Mocha http://visionmedia.github.io/mocha/ (+ Chai) 10 | 11 | FactoryGirl like Fixtures 12 | --- 13 | 14 | * Android - https://github.com/rejasupotaro/RobotGirl 15 | * iOS - https://github.com/lucasmedeirosleite/CMFactory 16 | -------------------------------------------------------------------------------- /The-Art-of-Documentation.md: -------------------------------------------------------------------------------- 1 | Documentation 2 | === 3 | 4 | Documentation は大事な行為だと思う。何故か? 5 | 言葉でのコミュニケーションは確かに効率が良いし、伝わっているという気分になるけども、それはスケールしないから。 6 | 対面のコミュニケーションに頼っていると、大体以下のような問題に見舞われる。 7 | 8 | 1. 喋った人同士にしか情報残らない(ので、ある事柄について、知らない人が出てくる) 9 | 2. 案外、人に喋って事柄を伝えるのは時間が掛かる(効率良いはずなのに) 10 | 3. 喋った人にしか情報が渡らないので、複数人に情報を伝えるには逆に効率が悪い。 11 | 4. 情報が残らない。(結局、後から文書化したりする手間がかかる) 12 | 13 | といいつつチャットのコミュニケーションでも情報がまとまらないので、同じようなことも起こる。 14 | 15 | 以上、如何に 1. 文字・あるいは動画 / 音声で 2. まとまった情報を残すか、ということが大事。 16 | 17 | そのためには良いツールセットが必要である。 18 | 19 | 開発系 20 | --- 21 | 22 | ### ツールセット 23 | 24 | まずはともかく Document Generator 25 | 26 | - Objective-C [appledoc](https://github.com/tomaz/appledoc) - XCode docset を出力 27 | - Objective-C & Swift (XCode 6 beta 2 が必要) [jazzy](https://github.com/realm/jazzy) - こっちのほうがカッコいい 28 | - Android javadoc(標準) - 使いにくい 29 | - Android [Doxygen](http://www.stack.nl/~dimitri/doxygen/) - マシ [使ってる Doc](http://jd.bukkit.org/rb/doxygen/) 30 | - Go [godoc(標準)](http://godoc.org/) - godoc.org で GitHub 上のドキュメントを良い感じに documentation してくれる。 31 | - Ruby [yard](http://yardoc.org/) - 普通に使いやすい。 32 | 33 | そして、test. よく書かれたテストはそれ自体がドキュメントである。RSpec 形式のテスト読みやすいと思う。 34 | また、結合テストは後述の「結合のための情報」のドキュメントにもなるため、大変重要であると考えている。 35 | 36 | - Objective-C [Specta & Expecta](https://github.com/specta/specta) 37 | - Android [lambda-behave](https://github.com/RichardWarburton/lambda-behave) あるいは [AssertJ](https://github.com/square/assertj-android) 38 | - Go [Ginkgo](http://onsi.github.io/ginkgo/) 39 | - Ruby [RSpec](http://rspec.info/) 40 | 41 | API 限定で、ドキュメントのフォーマットとして, JSON Schema と Swagger Docs が使える 42 | 43 | - [Swagger Docs](https://helloreverb.com/developers/swagger) - 試せる API Doc [サンプル(Petstore)](http://petstore.swagger.wordnik.com/) 44 | * https://github.com/yvasiyarov/swagger - Swagger を Go で 45 | - [JSON Schema](http://json-schema.org/) - JSON でメタ情報を記述するフォーマット 46 | 47 | 絵を描くツール 48 | 49 | - Balsamiq - https://balsamiq.com/ 50 | - cacoo - https://cacoo.com/lang/ja/ 51 | 52 | 写真を共有する 53 | 54 | - [gyazo](https://gyazo.com/ja) - SS, Screencast を共有 55 | - vine - アプリの動作とかを手っ取り早く共有 56 | 57 | ### 開発においてなにを重点的にドキュメントにすべきか? 58 | 59 | 1. 結合のための情報 (document generator) 60 | * Web API ならば 61 | * エンドポイント 62 | * 認証方式とサンプルコード 63 | * データ形式 64 | * リクエストのデータ形式 65 | * レスポンスのデータ形式 66 | * 実際に使う流れのサンプルコード 67 | * モジュールであれば 68 | * 公開インターフェースの説明と、どう使うか 69 | * 標準的なユースケースに対して、そのためのインターフェースとサンプルコード 70 | * 「出来ないこと」と、「弱点」があれば明示的に記述しておく 71 | * e.g., 「このようなケースでエラーが稀に起こると思いますが、稀なケースなので対策してない」 72 | * プロトコル 73 | * どのような実装を用意すべきか 74 | * リファレンス実装 75 | * どのようなエラーが予想され、実装でどのように対策すべきか 76 | 2. 仕様 77 | * 大きな仕様は、大枠を描く。図を使えたら図を描く。 78 | * たとえば、画面遷移であれば図を描くべきである。そのためのツールは上に記載。 79 | * 細かい仕様は埋もれがちなので、チェックリスト的に網羅的に記述する。 80 | * チェックリスト的に使えるのが重要 81 | 3. クラス構成と、「何故こうなのか」 (document generator, drawing) 82 | * 「仕様」と被る部分は有るが、こちらは実装寄りの話。「仕様」はインターフェースである。 83 | * どんなクラス構成になっており、それぞれのクラスはどのような責務を担っているか。(また、どのような位置づけか) 84 | * また、実装において考えたことをだだ流しにする。 85 | * (e.g., このクラスは拡張を考えれば xx にすべきだけども、そのような拡張は予定していないため、こうなっている) 86 | * 「出来ないこと」と、「弱点」があれば明示的に記述しておく 87 | * e.g., 「このようなケースでエラーが稀に起こると思いますが、稀なケースなので対策してない」 88 | * ところでクラス設計の話 89 | * クラスはドメインによって明確にカテゴライズされるべきである。 90 | * ライブラリ化出来るクラス群はライブラリに出す。疎結合化を促進する。 91 | * クラスの命名便利なやつ: https://github.com/kaiinui/note/blob/master/Design--CommonClasses.md 92 | 4. どのようにテストすべきか (DesignDoc に含まれる) 93 | * どのような深度・周期でテストをすべきか 94 | * 例えば、「このモジュールはロジックが沢山絡むので、ユニットテストをカッチリやる」「このモジュールはジェスチャが沢山絡み合っているため、UI テストをカッチリやる」 95 | * 「このようなテストがしたい」のような願望も書いておくと忘れにくい 96 | * 「嵌りやすいところ」を明文化しておくことが肝心。 97 | * どのようなデータ / ケースを使えばテスト出来るか。 98 | 5. リファクタリング案 99 | * 将来に向けて変更を加えるため、どのようなリファクタリングをすべきかを記述する。 100 | * e.g., 「このクラスは本来であればこうすべきだが、今はこうなっている」 101 | * コードを書いた人がリファクタリング案を書く。 102 | * 場所は Issue が良い 103 | 6. DesignDoc 104 | 105 | また、Documentation がどれほど完了しているかを表す indicator を付けるべきである。 (e.g., ![](http://progressed.io/bar/20)) 106 | 107 | (`http://progressed.io/bar/0` などで便利に作れる。) 108 | 109 | ### Project 構成 110 | 111 | GitHub Wiki は埋もれるため、あまり使わない方が良いと考えている。 112 | だから、通常の commmit で書く。 113 | メタ情報も履歴が残ってしかるべきだし、コメントも GitHub 上で残せる。 114 | 115 | #### 表に出るシステムの場合(モジュールではない場合) 116 | 117 | - README.md - プロジェクトの概要(Why? How? Who?), Screen Shot (or Movie clip), 試せるものがあればリンク, 関連リンク, 各種 Doc へのリンク, 参考リンク 118 | - Doc--Architecture.md - 「3. クラス構成」を記述する。また、他の Doc に対するリンクを全て含める。 119 | - Doc--Spec.md - Major スペック(大枠)を記述する。 120 | - Doc--MiniSpec.md - Minor スペックをチェックリスト形式で記述する。 121 | - Doc--DesignDoc.md - Design Doc を記述する (Test はここに含まれている) 122 | - SomeClass.h - Inline document (javadoc style) のドキュメントを書く。ドキュメントジェネレータに食わせる。 123 | 124 | #### モジュールの場合 125 | 126 | 上記に加え、 127 | 128 | - README.md - + 公開インターフェースの説明とサンプルコード, 129 | - Doc--Interface.md - 「1. 結合のための情報」を記述する。また、他の Doc へのリンクを全て含める 130 | 131 | 課題 132 | --- 133 | 134 | - 色々やってみて最適解を探すしかない 135 | - 面倒くささある 136 | - 情報の鮮度を保つのが大変(GitHub の最終更新時刻で古いのが分かるのは良い。) 137 | * 時間的に古くなったら Notification してもいいかも 138 | * 情報的に古いのはどうしようもない 139 | * テスト / コードの inline document からドキュメント生成というのが、かなり現実的だと思う。 140 | - そんなに量なくて良くて、キッチリドキュメントするというのが大事 141 | * 一番大事なのは、「どうしてこうなっているのか」と「今後の課題」をコメントでもいいから残しておくこと。 142 | - 頭の中を dump する。 143 | - ツールで出来る範囲が増えるとよい 144 | * Slack の会話をログしてイイ感じに紐づける 145 | * Documentation されてない Class が増えたら怒る 146 | * API はテストとか Schema から生成出来ると良い 147 | * Inline comments をイイ感じに可視化する。(`TODO:` とかをイイ感じに一覧にしたい。) 148 | 149 | References 150 | --- 151 | 152 | ### DesignDoc 153 | 154 | - [note/Design--Designdoc.md at master · kaiinui/note](https://github.com/kaiinui/note/blob/master/Design--Designdoc.md) 155 | - [Google の Design Doc について - フリーフォーム フリークアウト](http://d.hatena.ne.jp/cou929_la/20091116/1258373100) 156 | 157 | ### Module / Interface Documents 158 | 159 | - [Realm](http://realm.io/docs/cocoa/0.84.0/) - Realm のドキュメント。 160 | - [NSOrderedSet Class Reference](https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSOrderedSet_Class/Reference/Reference.html) - Apple のドキュメント。良い。 161 | - [Protocol Buffers — Google Developers](https://developers.google.com/protocol-buffers/) - Protocol Buffers のドキュメント. well-documented. 162 | - [cacoo API](https://cacoo.com/lang/ja/api) 163 | -------------------------------------------------------------------------------- /UI--prototyping.md: -------------------------------------------------------------------------------- 1 | Prototyping UI 2 | === 3 | 4 | - Origami - http://facebook.github.io/origami/ 5 | - POP - https://popapp.in/ 6 | - PaintCode - http://www.paintcodeapp.com/ 7 | * 描いたラインをコードにしてくれる(Objective-C) 8 | - https://invisionapp.com/ 9 | * `.png` などで POP. あとはディスカッション機能とか、distribute 機能とかついてる。 10 | - Sketch 11 | * カンタンベクター 12 | -------------------------------------------------------------------------------- /UX--Sync.md: -------------------------------------------------------------------------------- 1 | ベストなユーザエクスペリエンスを実現するJavaScriptの課題と可能性 - ワザノバ | wazanova : http://wazanova.jp/items/1569 2 | -------------------------------------------------------------------------------- /UX--minbox.md: -------------------------------------------------------------------------------- 1 | アップロード体験 2 | 3 | - アップロードを裏側でやって、最初に共有可能な URL だけを生成し、シェアを一瞬で出来るように(見える) 4 | - 受け取る側は、空に見える ~~(これは良くなくて、今何が誰によって上がってて、何分後に上がるよ〜みたいなの必要)~~ やってた 5 | * ただし、ページを見てる最中にアップロードが終わっても、ファイルが自動で洗われたりしない。リロード必要 6 | - 送る側は、受け取る側がファイルを受領したことを通知によって知ることが出来る 7 | - スクショとか取ったら勝手に URL を生成して、すぐに送れる。(mixbox のアプリを常駐してたら) 8 | * しかも、勝手にコピペしてくれる 9 | - 画像の URL でコメントとか出来る 10 | 11 | 総じてビジネス目的で Dropbox を使うつらみを軽減してる感じ 12 | -------------------------------------------------------------------------------- /Web--Test.md: -------------------------------------------------------------------------------- 1 | http://c-note.chatwork.com/post/103777312760/pr-driven-e2e-tests-with-protractor-sauce-labs-travis-ci 2 | 3 | Protractor, Angular, Travis, Sauce 4 | -------------------------------------------------------------------------------- /Web--VirtualDOM.md: -------------------------------------------------------------------------------- 1 | Virtual DOM 2 | --- 3 | 4 | ### Virtual DOM + Web Worker で Web App は変わるか? 5 | 6 | 以前より、MVC + Web Worker の構想はあったが、DOM 関連で結局パフォーマンス損なわれる感じで実現し辛かった。 7 | 8 | が、Virtual DOM を上手く使えばかなりの部分が Background に押し込められてしまうのでは? 9 | UI スレッドで動く必要のあるものといえば、以下の 3 つくらい。 10 | 11 | 1. `requestAnimationFrame` で差分 DOM の更新(これは軽い) 12 | 2. DOM Event の受付と `postMessage()` 13 | 3. `localStorage` 14 | 15 | Virtual DOM を使えば表でやることを最小限に抑えることが出来、相当軽くなるような気がする。 16 | (TODO: DOM の部分でどの程度重いか調査) 17 | 18 | UI スレッドでの責務(というか処理)を極限まで減らすことで、 testability も相当上がる。と思う。 19 | 20 | FAQ? 21 | --- 22 | 23 | #### 通信? 24 | 25 | XHR は Web Worker 対応。 26 | 27 | #### 複数スレッドでつらみありそう? 28 | 29 | UI Thread + Background 1 つだから Android とかでよくやる UI + Model Service と同じパターン。 30 | 31 | `postMessage()` (スレッド間の協調)が必要な部分はおそらくたった二つしかない 32 | 33 | 1. Virtual DOM に変更があったとき、変更点を UI Thread に `postMessage()` 34 | 2. 観測が必要な DOM Event が起こった時、このイベントの中身を Background に `postMessage()` 35 | 36 | #### 対応ブラウザ? 37 | 38 | http://caniuse.com/#feat=webworkers 39 | 40 | Android Browser が 4.3 以下未対応なことを除けば良し。 4.3 以下… 41 | 42 | Global で 77.31% のシェアがある。まだまだ辛い。 43 | 44 | #### 対応フレームワーク? 45 | 46 | 無し。 47 | 48 | https://github.com/Raynos/mercury をイイ感じに弄ることで実現出来る気がする。 49 | 50 | References 51 | --- 52 | 53 | - http://efcl.info/2014/08/28/mercury/ 54 | - https://github.com/Raynos/mercury 55 | -------------------------------------------------------------------------------- /i18n--Policy.md: -------------------------------------------------------------------------------- 1 | - 英単語と 2 bytes 文字の間には空白スペースを 1 つ開ける (e.g. `Post で写真を共有`) 2 | - iPhone のアプリ名「写真」などは厳密に各国の名称に翻訳する。 (e.g. 「写真」 -> "Foto") 3 | - 視覚的な長さを保つ (e.g. 「はじめよう」 -> "Get Started") 4 | - 翻訳の依頼には、使用されるコンテキストを提供する 5 | -------------------------------------------------------------------------------- /i18n.md: -------------------------------------------------------------------------------- 1 | i18n 2 | === 3 | 4 | How to do scalable i18n? 5 | 6 | get localization 7 | --- 8 | 9 | http://www.getlocalization.com/ 10 | 11 | - Order translation. 12 | - `.strings`, `.xml` integrated (and others) 13 | - Translation workspace on online. 14 | 15 | みたところ最高ぽい 16 | 17 | TraductoPro 18 | --- 19 | 20 | http://www.traductoapp.com/ 21 | 22 | - Translation editor. 23 | - Status visualization (like "78%") 24 | - Order translation in app. 25 | 26 | Locale for Rails 27 | --- 28 | 29 | https://localeapp.com/ 30 | 31 | - Translation editor on online. (Collaboratable) 32 | - Status Visualization 33 | - `.yml` 34 | - 35 | http://wovn.io/#?wovn=ja 36 | 37 | http://www.science.co.il/Language/Locale-Codes.asp 38 | 39 | 参考文献 40 | --- 41 | 42 | - http://www.welocalize.com/ 43 | - http://www.getlocalization.com/professional-translation/ 44 | - Our Services » wordcrafts : https://www.wordcrafts.de/ 45 | - ICanLocalize – Expert Translation at Unbeatable Prices : http://www.icanlocalize.com/site/ 46 | - OneSky - Translation Services, Translation Management System and Collaborative Translation Solutions : http://www.oneskyapp.com/ 47 | - The Ultimate iPhone App Marketing Strategy Guide | Apptamin : http://www.apptamin.com/blog/app-marketing-strategy/#localize 48 | - App Store Optimization (ASO): Improve Your App Ratings - Apptamin : http://www.apptamin.com/blog/app-store-optimization-app-ratings/ 49 | - App Localization | localeyes : http://www.localeyes.com/App-Localization 50 | - App translations | Transfluent : https://www.transfluent.com/en/products/apps/ 51 | - Applingua – iOS, OS X and Android App Localization App Localization - Applingua - iOS, OS X and Android App Localization : http://applingua.com/app-localization/ 52 | -------------------------------------------------------------------------------- /iOS--ALAssets-NotFound.md: -------------------------------------------------------------------------------- 1 | ALAsset, PHAsset の not found 2 | --- 3 | 4 | `ALAsset`, `PHAsset` にはそれぞれ `URL`, `localIdentifier` によって一意に識別される Asset を探す API が存在する。 5 | これらの API について、Asset が見つからなかったときの処理について記す。 6 | 7 | ### ALAsset 8 | 9 | Assets Library では `ALAssetsLibrary - assetForURL:resultBlock:failureBlock:` を用いて URL によって識別される Asset を探すことが出来る。 10 | 11 | このメソッドでは `ALAsset` が見つからなかったとき、`resultBlock` の `ALAsset` にて `nil` が渡される。従って、`resultBlock` の冒頭にて `asset` が `nil` かどうかを判定すれば、見つからなかった時の処理が実装出来る。 12 | 13 | `failureBlock` は Photo Library へのアクセスの Permission が拒否された時のみ呼び出されることに注意。 14 | 15 | ### PHAsset 16 | 17 | PhotoKit では `PHAsset + fetchAssetsWithLocalIdentifiers:options:` を用いて、`localIdnetifier` にて識別される Asset を取得することが出来る。 18 | 19 | このメソッドでは `PHAsset` が見つからなかったとき、空の `PHFetchResult` が返される。このとき `result.count` が 0 になっているので、これを識別すれば見つからなかったときの処理を実装出来る。 20 | 21 | -------------------------------------------------------------------------------- /iOS--ALAssetsLibrary-iOS8-Compatibility.md: -------------------------------------------------------------------------------- 1 | ALAssetsLibrary が iOS8 で変わったの 2 | --- 3 | 4 | 1. Camera Roll に iOS8 以上で撮った写真しかない 5 | --- 6 | 7 | `ALAssetsGroupSavedPhotos` 8 | 9 | 2. `ALAssetsGroupPhotoStream` がない 10 | --- 11 | 12 | ```objc 13 | [library enumerateGroupsWithTypes:ALAssetsGroupPhotoStream usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 14 | NSLog(@"WHOA"); 15 | [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { 16 | NSLog(@"%@", result); 17 | NSLog(@"%@", [result valueForProperty:ALAssetPropertyDate]); 18 | }]; 19 | 20 | } failureBlock:^(NSError *error) { 21 | NSLog(@"ERROR"); 22 | }]; 23 | ``` 24 | 25 | ``` 26 | 2014-09-21 03:36:10.310 assetslibrary[324:18413] WHOA 27 | 2014-09-21 03:36:10.319 assetslibrary[324:18413] (null) 28 | 2014-09-21 03:36:10.320 assetslibrary[324:18413] (null) 29 | 2014-09-21 03:36:10.321 assetslibrary[324:18413] WHOA 30 | ``` 31 | 32 | 3. `ALAssetsGroupLibrary` がない 33 | --- 34 | 35 | ```objc 36 | [library enumerateGroupsWithTypes:ALAssetsGroupLibrary usingBlock:^(ALAssetsGroup *group, BOOL *stop) { 37 | NSLog(@"WHOA"); 38 | [group enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { 39 | NSLog(@"%@", result); 40 | NSLog(@"%@", [result valueForProperty:ALAssetPropertyDate]); 41 | }]; 42 | 43 | } failureBlock:^(NSError *error) { 44 | NSLog(@"ERROR"); 45 | }]; 46 | ``` 47 | 48 | ``` 49 | 2014-09-21 03:36:10.310 assetslibrary[324:18413] WHOA 50 | 2014-09-21 03:36:10.319 assetslibrary[324:18413] (null) 51 | 2014-09-21 03:36:10.320 assetslibrary[324:18413] (null) 52 | 2014-09-21 03:36:10.321 assetslibrary[324:18413] WHOA 53 | ``` 54 | 55 | 全体的に 8 以降に撮った写真しか、とれないっぽい 56 | --- 57 | 58 | 手持ちの iPhone 4S は 7 時代にアルバムを作っていないっぽいので、 `ALAssetsGroupAll` でやっても `ALAssetsGroupSavedPhotos` でしか enumerate 出来ず、やはり iOS8 以降の写真しかとれない。 59 | 60 | 4. `ALAssetsGroupSavedPhotos` は「最近追加した項目」になっている 61 | --- 62 | 63 | description を呼ぶと 64 | 65 | ``` 66 | ALAssetsGroup - Name:Recently Added, Type:Saved Photos, Assets count:12 67 | ``` 68 | 69 | 5. `ALAssetsGroup` の `- valueForKey:` で死ぬ 70 | --- 71 | 72 | ```objc 73 | NSLog(@"%@", [group valueForKey:ALAssetsGroupPropertyName]); 74 | NSLog(@"%@", [group valueForKey:ALAssetsGroupPropertyPersistentID]); 75 | NSLog(@"%@", [group valueForKey:ALAssetsGroupPropertyURL]); 76 | NSLog(@"%@", [group valueForKey:ALAssetsGroupPropertyType]); 77 | ``` 78 | 79 | 全部死ぬ。 80 | 81 | ``` 82 | Terminating app due to uncaught exception 'NSUnknownKeyException' 83 | ``` 84 | 85 | 他色々事案 86 | --- 87 | 88 | #### ALAssetsLibrary は写真をキャッシュする 89 | 90 | 表側でいくら頑張ろうと、 ALAssetsLibrary がフレームワーク側でキャッシュをしてくれるのでメモリが重い 91 | 92 | #### `enumerateUsingBlock` が何故か 600KB ほど使う 93 | 94 | 理由は不明だが何もしなくても 600KB ほど使う。libdispatch が色々してるっぽい。 95 | 終わっても開放されない 96 | 97 | ```objc 98 | [library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:nil failureBlock:nil]; 99 | ``` 100 | 101 | これで 600KB くらい使う。libdispatch がとにかく重い。 102 | -------------------------------------------------------------------------------- /iOS--Analytics.md: -------------------------------------------------------------------------------- 1 | http://qiita.com/masaki925/items/2a6bd81747d7660c0bee 2 | 3 | iTunes Connect 取れる情報が増えたらしいぞい。 4 | 5 | 参考文献 6 | --- 7 | 8 | - 「iPhoneアプリの数値計測したいんだけど」と言われた君へ : http://qiita.com/masaki925/items/2a6bd81747d7660c0bee 9 | - なぜ機能するKPIは割合や比率でないといけないのか? | symsonic : http://symsonic.jp/2014/03/23/ratioandrate/ 10 | - Pinterestのグロースチームが活用する4つの分析フォーマット | symsonic : http://symsonic.jp/2014/06/09/pinterest/ 11 | - Quantifying Mobile Habits — Medium : https://medium.com/@ryanstuczynski/quantifying-mobile-habits-59eb7f96a2e8 12 | - MAUやDAUより大事な”習慣化”というKPI | symsonic : http://symsonic.jp/2014/09/16/habits/ 13 | -------------------------------------------------------------------------------- /iOS--App-Extensions.md: -------------------------------------------------------------------------------- 1 | iOS8 App Extensions 2 | === 3 | 4 | - http://qiita.com/monoqlo/items/6ed93f0d2e719acd9474 - iOS8のApp Extensionsをつくってみる(Share 実装編) 5 | -------------------------------------------------------------------------------- /iOS--AppAnalytics.md: -------------------------------------------------------------------------------- 1 | * iOS8 以降の端末での情報のみがカウントされます。iOS7 以下の情報を含まないので正確な数字ではありません。 2 | * App Store Views / App Units = インストール率 **ではありません** 3 | * なぜなら、検索結果から直接インストールすることが出来るからです。それらは、App Store Views には反映されず、App Units だけが増えます。 4 | * App Usage のセクションの情報は実情に比べて少ないです。 5 | * なぜなら、「アナリティクスによってトラッキングされることを承諾したユーザ」のみがカウントされているからです。 6 | * WebSite Source はトップレベルのドメインまでしかわからない 7 | * 計測したい場合は、Campaign リンクを使う。(リンクの貼り方を指定できる場合のみ) 8 | * 広告などでリンクを貼ってもらう場合は、Campaign リンクを必ず使う 9 | 10 | ### その他 11 | 12 | * App Units はデバイスによりユニークにカウントされます。 13 | 14 | ### 参考 15 | 16 | * iTunes Connect : https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/wa/jumpTo?page=faqIndex&group=appanalytics 17 | -------------------------------------------------------------------------------- /iOS--AppPreview.md: -------------------------------------------------------------------------------- 1 | App Preview 2 | --- 3 | 4 | ``` 5 | @iPhone5、iPhone6、iPhone6Plus、iPadのサイズをアップできる。 6 | @iPhone4サイズはアップできない。 7 | @動画のローカライズはできない。(日本語動画作ると英語ページも日本語の動画) 8 | @よって、一つのアプリに4つの動画を用意することになる。 9 | ``` 10 | 11 | -> まわりを黒で囲って下駄をはかせれば OK. 12 | 13 | - Yosemite 必須と書いているが、UA を詐称すればアップロード出来る。 14 | - 字幕を付けても良いが、スクリーンショットと違って、実際の画面ベースでないとだめ。(撮ったビデオとかはダメ。スクリーンキャプチャのみ) 15 | 16 | ### ツール 17 | 18 | - Final Cut Pro X 19 | - Motion 5 **$50** (Mac App Store - Motion : https://itunes.apple.com/us/app/motion/id434290957?mt=12&v0=www-naus-motion-buynow) 20 | - QuickTime Pro 21 | 22 | ### Spec 23 | 24 | ![](http://kisakata.jp/wp-content/uploads/5df3982cff4cd8656dbf7c8da620c164.png) 25 | 26 | 出来が良いと思うの 27 | --- 28 | 29 | - テラバトル (https://itunes.apple.com/ca/app/terra-battle/id888628623?mt=8) 30 | - Clear (http://vimeo.com/105962448) 31 | 32 | References 33 | --- 34 | 35 | - App Store用の紹介動画App Previewsの作り方まとめ : http://umememo.com/archives/348 36 | - みろなる@年内は節約生活さんはTwitterを使っています: "@_kaiinui Parallels 入れてやってたんですけど、色々ググったら UA 書き換えで行けるって書いてあって唖然としたw" : https://twitter.com/mironal/status/522631063953092608 37 | - App Previews (video on the iOS 8 App Store): thoughts and tips : http://www.apptamin.com/blog/app-previews/ 38 | - The Business of App Design - Getting Started with App Previews : http://dancounsell.com/articles/getting-started-with-app-previews 39 | - AppStoreのアプリ動画 App Previews作成に便利なツールの紹介 : http://umememo.com/archives/305 40 | - iTunes ConnectでAppビデオプレビューをアップロードする | KSKT | Good UI, Good UX : http://kisakata.jp/blog/itunes-connect-video-preview/ 41 | -------------------------------------------------------------------------------- /iOS--AppStore.md: -------------------------------------------------------------------------------- 1 | AppStore 申請 2 | --- 3 | 4 | - 名前: 5 | - 説明文: 6 | - キーワード: 100 bytes 以内 7 | - スクリーンショット: 4inch, 3.5inch 8 | * 640*1136 (4inch) 9 | * 640*960 (3.5inch) 10 | - アイコン: 1024x1024 **透過を含めない** 11 | 12 | References 13 | --- 14 | 15 | - https://ocastastudios.com/resources/required-info-to-submit-your-ios-app-to-the-app-store/ 16 | - http://gengo.com 17 | -------------------------------------------------------------------------------- /iOS--AppleDoc.md: -------------------------------------------------------------------------------- 1 | Appledoc 2 | --- 3 | 4 | ```sh 5 | #!/bin/bash 6 | 7 | appledoc --prefix-merged-sections \ 8 | --ignore ".m"\ 9 | --ignore "Pods"\ 10 | --keep-undocumented-objects\ 11 | --keep-undocumented-members\ 12 | --create-html\ 13 | --no-create-docset\ 14 | --include "docs/_doc_flow.png"\ 15 | --index-desc "docs/_doc_index.markdown"\ 16 | --company-id "org.openaquamarine"\ 17 | --project-name="AquaSync"\ 18 | --project-company "Aquamarine"\ 19 | --output "~/dropbox/Public/___doc___AquaSync"\ 20 | AquaSync/Classes 21 | ``` 22 | -------------------------------------------------------------------------------- /iOS--Architecture.md: -------------------------------------------------------------------------------- 1 | iOS Architecture 2 | --- 3 | 4 | ``` 5 | - View 6 | |- Theme 7 | - Action 8 | - Dispatcher 9 | |- EventListener 10 | - Store 11 | |- (StoreLocator) 12 | ``` 13 | -------------------------------------------------------------------------------- /iOS--Aspect.md: -------------------------------------------------------------------------------- 1 | Aspect Oriented 2 | --- 3 | 4 | https://github.com/steipete/Aspects 5 | 6 | ```objc 7 | // NSObject+Aspects 8 | 9 | + (id)aspect_hookSelector:(SEL)selector 10 | withOptions:(AspectOptions)options 11 | usingBlock:(id)block 12 | error:(NSError **)error; 13 | 14 | - (id)aspect_hookSelector:(SEL)selector 15 | withOptions:(AspectOptions)options 16 | usingBlock:(id)block 17 | error:(NSError **)error; 18 | ``` 19 | 20 | 最高のやつがある。 21 | 22 | `withOptions` に `AspectPositionBefore` とか付けると `block` が対象メソッドの前に呼ばれる。 `AspectPositionInstead` もある。 23 | 24 | `+aspect_hookSelector:withOptions:usingBlock:error;` はクラスメソッドを hook するように見えるけど、対象クラスのインスタンス全てのインスタンスメソッドを hook する。 25 | 26 | メソッドが呼ばれる前に Log をつけるようにする 27 | --- 28 | 29 | ```objc 30 | [object aspect_hookSelector:@selector(method:) withOptions:AspectPositionBefore usingBlock: ^(id aspectInfo) { 31 | NSLog(@"%@ %@", aspectInfo.instance, aspectInfo.arguments); 32 | }, error: NULL]; 33 | ``` 34 | 35 | とすることでメソッドが呼ばれる前に, インスタンスと引数配列の description が Log されるようになる. 36 | 37 | ちなみにメソッドの名前も欲しい場合は、`sel_getName(selector)` とすることで名前が得られる(`method:withHoge:` みたいな形式) 38 | 39 | Block には `id` が必ず最初の引数として入る。 40 | 41 | ```objc 42 | @protocol AspectInfo 43 | 44 | /// The instance that is currently hooked. 45 | - (id)instance; 46 | 47 | /// The original invocation of the hooked method. 48 | - (NSInvocation *)originalInvocation; 49 | 50 | /// All method arguments, boxed. This is lazily evaluated. 51 | - (NSArray *)arguments; 52 | 53 | @end 54 | ``` 55 | 56 | `originalInvocation` は `NSInvocation` であり、扱いがけっこうめどんくさい。 57 | 58 | メソッド呼び出し前後を計測したり返り値をログしたりしたい 59 | --- 60 | 61 | `aspectInfo.originalInvocation` をゴニョゴニョする。 62 | 63 | #### `NSInvocation` の扱い 64 | 65 | 1. `[invocation invoke];` でメソッドを実行 66 | 2. `[invocation getResult:&buffer]` で結果を `buffer` にぶち込む 67 | 68 | 実際はかなり扱いがめんどくさい。まず、`(void)` を返すメソッドの `getResult:` をやると落ちる。んで、 `buffer` も返ってくる大きさを見越した大きさを確保して宣言する必要ある。 69 | なので、 `[[invocation methodSignature] methodReturnType];` でまず型を知って…とかやる必要ある。 70 | 71 | めんどくさいので [kstenerud/Objective-Gems](https://github.com/kstenerud/Objective-Gems) を使う。 72 | 73 | これは、 `NSInvocation` に `-invokeAndReturn` とか生やしてくれて最高。 74 | 75 | 単に `id result = [invocation invokeAndReturn];` と出来る。 76 | 77 | ##### ただし 78 | 79 | 二重 free が発生するので, `NSInvocation+Simple.m` をこんな感じに改造する必要ある。 80 | 81 | ```objc 82 | NSUInteger length = [[self methodSignature] methodReturnLength]; 83 | NSMutableData * dat = [NSMutableData dataWithLength:length]; 84 | void * buffer = [dat mutableBytes]; 85 | [self getReturnValue:&buffer]; 86 | return (__bridge id)(buffer); 87 | ``` 88 | 89 | `NSMutableData` を使うのは、 http://stackoverflow.com/questions/9707233/free-and-malloc-with-nsvalue-and-nsinvocation を参照。 90 | 91 | 92 | かくして 93 | --- 94 | 95 | ```objc 96 | + (void)inspect:(SEL)selector of:(NSObject *)object { 97 | #ifdef DEBUG 98 | id insteadBlock = [self insteadBlock:selector]; 99 | [object aspect_hookSelector:selector withOptions:AspectPositionInstead usingBlock:insteadBlock error:NULL]; 100 | #endif 101 | } 102 | ``` 103 | 104 | ```objc 105 | + (id)insteadBlock:(SEL)selector { 106 | return ^(id aspectInfo) { 107 | [self logBeforeInvoke:aspectInfo ofSelector:selector]; 108 | NSDate *start = [NSDate date]; 109 | id result = [self invoke:aspectInfo.originalInvocation]; 110 | NSTimeInterval milliInterval = [self intervalInMilliSecond:start]; 111 | [self logAfterInvoke:aspectInfo ofSelector:selector withResult:result withInterval:milliInterval]; 112 | }; 113 | } 114 | ``` 115 | 116 | とすることが出来た。 117 | -------------------------------------------------------------------------------- /iOS--BLE.md: -------------------------------------------------------------------------------- 1 | - IoTの要(かなめ)!BLE通信をMacだけでデバッグできるようになる方法! - Qiita : http://qiita.com/kazuph/items/85ae7b350cd8a4209541 2 | - Core Bluetoothのハマりどころ逆引き辞典 - Qiita : http://qiita.com/shu223/items/f67f1b0fb1840cf0bd63 3 | -------------------------------------------------------------------------------- /iOS--BestPractices-Objective-C.md: -------------------------------------------------------------------------------- 1 | オレオレ Effective Objective-C 2 | === 3 | 4 | - public な Method, Property を減らす。 5 | - Interface を分割する(あるいはカテゴリでも良い。) 6 | - Instance variable ではなく無名カテゴリでの Property を使う 7 | - メソッドを細かく分ける 8 | - `#pragma mark` でメソッド群をこまめに区切る。 9 | - クラスを役割毎にカテゴリで分割する。 10 | - Collection クラスはコメントで中の型を明示する e.g. `NSArray /* */ *hogeArray;` 11 | - カテゴリで実装したメソッドには適切な prefix を付ける(「どのカテゴリのメソッドか」を明示化出来る) 12 | - KVO を利用する。(`KVOController`) 13 | - モジュール化し、CocoaPods で利用する 14 | - .h ではむやみに `#import` せず `@class` で前方宣言する 15 | - 循環参照は `libextobjc` で避ける 16 | - `NSNotificationCenter` を避ける。 17 | - appledoc, jazzy でドキュメンテーションする 18 | - 「継承より合成」 Category + `objc_setAssociatedObject` で出来る。 19 | * `UIView` 関連を拡張したい時などは特に。(Reference の "iOS UI Component API Design" を参照) 20 | * Options クラスを提供するのも良いデザインになりやすい 21 | 22 | 番外編 23 | 24 | - リソース 25 | - `R+String.m` で `NSLocalizedString()` をラップする 26 | - `R+Color.m` で `NSColor` をまとめる 27 | - `R+Number.m` で定数値をまとめる 28 | 29 | UI 編 30 | 31 | - `UIControl` はタップ認識領域を拡げる http://naoty.hatenablog.com/entry/2014/09/18/012246 32 | 33 | Friend Methods 34 | --- 35 | 36 | クラス間の連携で使うメソッドを protected っぽくしたい。 37 | 38 | Protocol を分けるか、Category を使えば良い。 39 | 40 | Category を使う場合は、`SomeClass+FriendMethods.h` とか。 41 | 42 | Discussions 43 | --- 44 | 45 | - view の取り扱い? 46 | * `Storybaord - instantiateViewControllerWithIdentifier:` は使う? 47 | * `.xib` は使う? 48 | * `.xib` からのロードはどうする? 49 | * `.xib` からロードしたとき、`IBAction` は? 50 | - Runtime Attributes の取り扱い 51 | * 良いけど、コード外の動作が増えてしまう。 52 | 53 | References 54 | --- 55 | 56 | - http://modocache.svbtle.com/ios-ui-component-api-design 57 | -------------------------------------------------------------------------------- /iOS--CommonErrors.md: -------------------------------------------------------------------------------- 1 | Common Errors in iOS Development 2 | === 3 | 4 | ``` 5 | レスポンスはキャッシュされる 6 | 7 | NSURLConnectionでもAFNetworkingでも、レスポンスは設定によってはキャッシュされます 8 | httpのレスポンスコードを正しく返す必要があります。 9 | サーバーからのjsonのレスポンス、画像のキャッシュの設定をしっかりみる必要があります 10 | 特に、普段返さないエラーページやメンテナンスページの設定を確認する必要あり 11 | バージョンコントロール 12 | 13 | 下位バージョンをサポートしないことで、インストールがかなり落ちます。 14 | 一度間違えて、7.1のときに7.0以降でなく7.1以降という設定でリリースして3割ほどインストールが落ちました 15 | cocoapodを利用している場合は、Podfileに書いているバージョンとprojectのバージョンに違いがあるかも注意する必要があります。 16 | 特定の7.0.2だけviewが崩れる問題などもありました 17 | iOSの細かい設定の違い 18 | 19 | カレンダーの設定の違い 20 | 21 | 和暦が存在します。 22 | 和暦の場合は2014年ではなく平成26年と書かれます 23 | キーボードのsplit keyboardの処理 24 | 25 | iPadの場合split keyboardというものがある。 26 | 他のキーボードとnotificationのタイミングなどが異なるので注意が必要 27 | 気づきにくいバグのポイント 28 | 29 | sharedInstanceやviewDidLoadでセットしているviewで問題が起きる 30 | 31 | sharedInstanceを利用してデータの受け渡しをしている場合、バグがあると、古いデータを利用して動作して問題が起きることが起きる。 32 | 例えば、Aさんにメッセージしようとすると、Bさんにメッセージしてしまう 33 | データの受け渡しはバグになりにくいように設計する。sharedInstanceを使った受け渡しはなるべくさける。notificationも常に使うことは絶対にしない。 34 | コミュニケーションパターンってのがある。これに従うとよい 35 | http://www.objc.io/issue-7/communication-patterns.html 36 | 異常系でクラッシュしやすいポイント 37 | 38 | NSDictonaryやNSNumberにnilが入る 39 | 40 | blockの中の変数など解放されてたまにnilが入るケースもある。 41 | viewのプロパティには注意が必要 42 | サーバーからのデータに必ず値が入るか、入っていなくても動作するようにするか、決める&テストを書いておく必要がある 43 | KVOでたまに落ちる 44 | 45 | 注意しないと結構クラッシュしやすい 46 | FacebookのKVOControllerがおすすめ 47 | https://github.com/facebook/KVOController 48 | ネットワークを接続中の操作 49 | 50 | 他のviewに移動する 51 | 他のアクションを実行するとか気をつける必要あり 52 | 新規ユーザのテスト 53 | 54 | データ依存の問題に最も気づきにくい 55 | 選択肢などなるべく一度はすべてのケースでテストしたほうがよい 56 | Crashlyticsは必ず入れておく 57 | 58 | 表示がおかしくなるポイント 59 | 60 | ScrollViewの上部の位置 61 | 62 | versionによっても問題起きやすい 63 | 複数配置していても問題起きやすい 64 | データが0件のときのテスト 65 | 66 | なにも表示されない問題が起きる 67 | 開発中に気づきにくいポイントになりやすい 68 | セルの再利用 69 | 70 | tableViewやcollectionViewではセルを再利用している 71 | データがない場合でもデータがないということを再代入する 72 | imageの読み込み中のcellを再利用してしまうのはよくしてしまう 73 | アプリの起動方法 74 | 75 | 通知から開く 76 | 77 | 通知から開く際に、アプリを起動してない・アプリを起動しているという二つのケースがある 78 | 特にアプリを起動しているときは、例えばモダルビューを開いているときに通知を開くなどのケースを忘れやすい 79 | ログインしてないユーザが通知からアクセスするとかも注意必要 80 | 起動中の通知もある 81 | url schemaから開く 82 | 83 | セキュリティ的にバグにならないか 84 | 当たり前だけど、APIとしても常にどういうデータがきても大丈夫なように設計する 85 | バックグラウンドフェッチから起動 86 | 87 | ライフサイクルが異なる 88 | iPhoneの機種 89 | 90 | 機種依存の問題もありえるためできるだけ機種ごとにテストするほうがいいです。 91 | ``` 92 | -------------------------------------------------------------------------------- /iOS--Concurrency.md: -------------------------------------------------------------------------------- 1 | UIKit 2 | --- 3 | 4 | メインでしか触れない。 5 | 6 | AsyncDisplayKit は UIKit を擬似的にバックグラウンドスレッドで扱うことが出来る。 7 | 8 | CoreData 9 | --- 10 | 11 | - A Guide to Core Data Concurrency : http://robots.thoughtbot.com/core-data 12 | - Touchwonders/CoreDataMultiThreading : https://github.com/touchwonders/CoreDataMultiThreading/ 13 | - Fast and non-blocking Core Data back-end programming | Touchwonders : http://www.touchwonders.com/fast-and-non-blocking-core-data-back-end-programming/ 14 | 15 | NSNotification 16 | --- 17 | 18 | スレッドを共有するので、基本 Main Thread で投げるべき。 19 | -------------------------------------------------------------------------------- /iOS--CoreData-Batch.md: -------------------------------------------------------------------------------- 1 | - New in Core Data and iOS 8: Batch Updating | Big Nerd Ranch : https://www.bignerdranch.com/blog/new-in-core-data-and-ios-8-batch-updating/ 2 | * 250,000 Objects のアップデートが `1.2 sec` で可能です (シミュレータ) 3 | * 従来のアップデートでは `16.5 sec` かかります(シミュレータ) 4 | * ![](https://www.bignerdranch.com/img/blog/2014/09/memory-results.png) 5 | - New in Core Data and iOS 8: Asynchronous Fetching | Big Nerd Ranch : https://www.bignerdranch.com/blog/new-in-core-data-and-iOS-8-asynchronous-fetching/ 6 | * スレッドをまたがずに、スレッドをブロックしない FetchRequest が可能です(素晴らしい) 7 | * Fetch の Progress を通知することができます。 8 | 9 | CoreData 関連つーる 10 | http://matthewmorey.com/tools-for-core-data/ 11 | -------------------------------------------------------------------------------- /iOS--Design--BestPractices.md: -------------------------------------------------------------------------------- 1 | iOS の設計 / クラス責務分担 2 | === 3 | 4 | 使えるの 5 | 6 | - Behavior クラス 7 | - APIClient の Service への分離. (NSNotificationCenter で Pub-Sub 的やり取り) 8 | * 何故か?ViewController は LifeCycle が複雑なため。短命。ViewController に View だけで閉じない操作(たとえば永続的な操作)を含めるのはダメ。 9 | - 独自 View への分離 (View に自分自身の面倒を見てもらう。Gesture とか。) 10 | - Datasource の分離 11 | - Delegate の分離 12 | - GestureDetector の分離 13 | - JLRoutes の導入 (ルーティング / パラメータ渡しの統一) 14 | - rdotm の導入 (まあ。typo によるミスの防止) 15 | - RAC の導入 (MVVM, Model-View binding) 16 | - Realm の導入 (Model) 17 | - コミュニケーションパターン (Communication Patterns - Foundation - objc.io issue #7 : http://www.objc.io/issue-7/communication-patterns.html) 18 | 19 | とにかく ViewController に全てを書くのをやめる。 20 | 21 | 妄想 22 | --- 23 | 24 | VIPER のやつを参考に。 25 | 26 | - `Router` - ViewController の instantiate と画面遷移 27 | - `Decorator` - View を Decoration する. (`view.layer.cornerRadius = 12.0f;`) 28 | - `ViewFactory` - View を作り、初期化する 29 | - `ViewController` - 30 | - `Interactor` - 操作を担当。「アルバムを作る」 => `AlbumInteractor` 31 | - `Presenter` - View を操作するロジック (DataSource も delegate もここが持つ。) 32 | - `Repository` - データを要求する。全てのデータはここを経由して取り出される。`NSNotification` で通知。 33 | - `Entity` - NSManagedObject 34 | - `Service` - ViewController のライフサイクルに依存しないサービス。Singleton である `ServiceLocator` を用いて retain される。サービスはビジネスロジックのことを知らずに、与えられた命令を只実行する。汎用コンポーネントでなければならない。 35 | * `Operation` - サービスが何かしらやる場合は、`NSOperation` を用いることが推奨される 36 | 37 | ### 命名規則 38 | 39 | - Storyboard は分割する 40 | - `SomeViewController` に対して Storybaord 名は `SomeViewController.storybaord` であり、 identifier は `SomeViewController` 41 | - `SomeView` に対して、`.xib` は `SomeView.xib` 42 | 43 | references 44 | --- 45 | 46 | - [Architecting iOS Apps with VIPER](http://www.objc.io/issue-13/viper.html) 47 | - [BehaviorクラスによるiOSアプリケーションの設計](http://tech.vasily.jp/ios_behavior_pattern) 48 | - [iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い](http://www.slideshare.net/mokemokechicken/iosandroidmodel) 49 | - [JLRoutes](https://github.com/joeldev/JLRoutes) 50 | - [Apple Templates Considered Harmful](http://modocache.svbtle.com/apple-templates-considered-harmful) 51 | -------------------------------------------------------------------------------- /iOS--DeviceAPI.md: -------------------------------------------------------------------------------- 1 | Device API 2 | --- 3 | 4 | Facebook iOS SDK すごい。`- canOpenURL:` を駆使して色んな API を実現している(`YES` or `NO` しか返せないけど…) 5 | 6 | 例えば、Like API も `- canOpenURL:` を駆使していて、`fblikecache://` みたいなスキームでアクセストークンとか付けてリクエストしてる。それで、Like の状況とか取るみたい。 7 | まじで App as an API 8 | -------------------------------------------------------------------------------- /iOS--LocalNotification.md: -------------------------------------------------------------------------------- 1 | http://qiita.com/caesar_cat/items/08018ab22bea27b55443 2 | -------------------------------------------------------------------------------- /iOS--MemoryLeak.md: -------------------------------------------------------------------------------- 1 | MemoryLeak 2 | --- 3 | 4 | `CGImage` は ARC 効かないので `CGImageRelease()` で開放してやる 5 | -------------------------------------------------------------------------------- /iOS--MemoryManagement.md: -------------------------------------------------------------------------------- 1 | iOS View Controllerプログラミングガイド : https://gist.github.com/shinyaohira/6482235#ios-6%E4%BB%A5%E9%99%8D%E3%81%AE%E5%A0%B4%E5%90%88view-controller%E3%81%AF%E5%BF%85%E8%A6%81%E3%81%AA%E3%81%A8%E3%81%8D%E3%81%ABview%E3%82%92%E3%82%A2%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B 2 | -------------------------------------------------------------------------------- /iOS--NSOperation.md: -------------------------------------------------------------------------------- 1 | NSOperation 2 | === 3 | 4 | イイ感じに Operation を動かしてくれる Queue 実装。同時実行数の制御などが出来る。 5 | 6 | 基本 7 | --- 8 | 9 | - FIFO である(Queue) 10 | - `NSOperationQueue` に対して `NSOperation` を `- addOperation:` することで Operation を start させることが出来る。 11 | - cancel をすることが出来る 12 | - 優先度を付けることが出来る 13 | - 実行精度を決めることが出来る(最悪 Operation が死んでもいいか) 14 | - 各 Operation に dependency を設定して走らせることが出来る。 15 | - completionBlock をとれる 16 | - 各 Operation 毎に勝手にメモリの許す限りスレッドを分ける 17 | - Async な Task にも使える 18 | 19 | 使い方 20 | --- 21 | 22 | `NSOperation` を継承し、 `- main` を実装する。 23 | 24 | その際、下の各 `keypath` を適切に管理する。 25 | 26 | * `isReady` 27 | * `isExecuting` 28 | * `isFinished` - 終了したときに `YES` にする。 29 | * `isCancelled` - キャンセルされたときに `YES` になっている。自前でキャンセルをする。 30 | 31 | Queue のスレッド 32 | --- 33 | 34 | ``` 35 | NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; 36 | ``` 37 | 38 | に突っ込めば Background Thread で 39 | 40 | ``` 41 | NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; 42 | ``` 43 | 44 | に突っ込めば Main Thread で動く。 45 | 46 | `NSOperationQueue` 47 | --- 48 | 49 | `maxConcurrentOperationCount` を弄ることで最大同時実行数を制御出来る。 50 | 51 | `[NSOperationQueue mainQueue]` に雑に突っ込むと、 `maxConcurrentOperationCount = 1` であり、かつ main thread で動く Operation になる。 52 | 53 | なので、自分で `[[NSOperationQueue alloc] init];` して持つ。持ち方は、Lifecycle に巻き込まれてはいけないので、`Manager` 的クラスを Singleton で持つのが良いと思う。 54 | 55 | Asynchronous Operation 56 | --- 57 | 58 | Synchronous Operation で雑にやる場合は、`- main` をオーバーライドするだけでよい。 `- main` の return で勝手に Operation を終わり、 dealloc まで済ませてくれる。 59 | 60 | ただし、Asynchronous Operation とか、色々非同期になっていて `- main` の return で死んでほしくない場合は、次のようにやる。 61 | 62 | #### `isFinished` をオーバーライドする 63 | 64 | 1. `@interface` で `isFinished` をオーバーライドする。 65 | 2. 処理を終了させたい所で、 `self.isFinished = YES` とする。 66 | 67 | これだけで Asynchronous Operation 対応できる。 68 | 69 | ```objc 70 | // KISomeOperation.h 71 | 72 | @interface KISomeOperation : NSOperation 73 | 74 | @property (nonatomic, assign) BOOL isFinished; 75 | 76 | @end 77 | ``` 78 | 79 | ```objc 80 | // KISomeOperation.m 81 | 82 | - (void)main { 83 | @weakify(self); 84 | [someThing doSomeThingAsynchronouslyWithBlock:^{ 85 | @strongify(self); 86 | self.isFinished = YES; 87 | }]; 88 | } 89 | ``` 90 | 91 | 注意点は、`@weakify` しないと循環参照して Operation が死なない。 92 | 93 | テスト 94 | --- 95 | 96 | [TODO] あとで書く 97 | 98 | 疑問 99 | --- 100 | 101 | - `NSOperationQueue` は誰が持てばいいんだろう?または Singleton 的に使う? 102 | * -> Model と同じく、Lifecycle に巻き込まれないために、`OperationManager` とか `OperationService` 的なクラスを Singleton で持つ。役割はただ `NSOperationQueue` を retain するだけ。 103 | 104 | References 105 | --- 106 | 107 | - http://stackoverflow.com/questions/19569244/nsoperation-and-nsoperationqueue-working-thread-vs-main-thread 108 | - http://nshipster.com/nsoperation/ 109 | - NSOperation Class Reference : https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html 110 | - Core Data Programming Guide: Concurrency with Core Data : https://developer.apple.com/library/mac/documentation/cocoa/conceptual/coredata/articles/cdConcurrency.html 111 | - Working with the NSOperationQueue Class - Tuts+ Code Tutorial : http://code.tutsplus.com/tutorials/working-with-the-nsoperationqueue-class--mobile-14993 112 | - もう怖くないCocoaの並列処理(GCD & NSOperation/NSOperationQueue) - $ cat /var/log/shin : http://shin.hateblo.jp/entry/2014/05/05/234912 113 | -------------------------------------------------------------------------------- /iOS--OverTheAir.md: -------------------------------------------------------------------------------- 1 | Over the Air 配信 2 | --- 3 | 4 | ベータテスト等に。 5 | 6 | http://joinswipe.com/producthunt/ 7 | 8 | ↑ リンクをタップして、OK を押すだけでアプリをインストール出来る。 9 | これは、Over the Air 配信と呼ばれる機能。 10 | 11 | Over the Air 配信の方法 12 | --- 13 | 14 | 1. SSL がある環境を用意する(Dropbox, S3 など) 15 | 2. `.ipa`, `.plist`, `index.html` をそれぞれ用意し、配置する。 16 | 3. `index.html` では上記 `.plist` を用いたリンクを貼る `itms-services://?action=download-manifest&url=https://dl.dropboxusercontent.com/u/xxx/xxx.plist` 17 | 4. `.plist` は以下の内容 18 | 19 | ```xml 20 | 21 | 22 | 23 | 24 | items 25 | 26 | 27 | assets 28 | 29 | 30 | kind 31 | software-package 32 | url 33 | #{URL_TO_IPA_FILE} 34 | 35 | 36 | metadata 37 | 38 | bundle-identifier 39 | #{BUNDLE_IDENTIFIER} 40 | kind 41 | software 42 | title 43 | #{SOFTWARE_NAME} 44 | 45 | 46 | 47 | 48 | 49 | ``` 50 | 51 | http://qiita.com/leznupar999/items/de7a53054d043ba19ead 52 | 53 | これで完了。 54 | 55 | ユーザはこれをタップすると、アプリのインストールされ、アプリを初めてタップした際に「許可しますか」等と出る。 56 | 57 | 参考文献 58 | --- 59 | 60 | - SSL契約いらず iOS7.1 AdHoc Dropboxからインストール - Qiita : http://qiita.com/leznupar999/items/de7a53054d043ba19ead 61 | - iOS7.1以降端末へのOTA配信 - Qiita : http://qiita.com/nofrmm/items/62f0adf0268b87e075e6 62 | - Digital publishing support, tablet publishing - Aquafadas : http://helpdesk.aquafadas.com/index.php?/Knowledgebase/Article/View/125/0/how-to-distribute-an-ad-hoc-or-in-house-app-over-the-air 63 | -------------------------------------------------------------------------------- /iOS--PHAsset,ALAssetのカメラロールへの書き込み時にメタデータを追記.md: -------------------------------------------------------------------------------- 1 | メタデータを書き込むことが、`PHAssetChangeRequest` の提供している方法を使うことで可能です。 2 | 3 | ```objc 4 | [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 5 | PHAssetChangeRequest *request = [PHAssetChangeRequest creationRequestForAssetFromImage:someImage]; 6 | request.creationDate = someDate; 7 | request.location = someLocation; 8 | } completionHandler:^(BOOL success, NSError *error) { 9 | completion(nil, error); 10 | }]; 11 | ``` 12 | 13 | ALAssetsLibrary は `NSDictionary` でメタデータ(撮影日時、場所)を指定します。ついでに、Orientation も正しく指定しておく必要があります。 14 | 15 | http://blog.codecropper.com/2011/05/adding-metadata-to-ios-images-the-easy-way/ が、metadata を簡単に扱うためのカテゴリを提供しています。 16 | 17 | ``` 18 | #import "NSMutableDictionary+ImageMetadata.h" 19 | 20 | NSMutableDictionary *metadata = [NSMutableDictionary dictionary]; 21 | [metadata setDateOriginal:someDate]; 22 | [metadata setLocation:someLocation]; 23 | [metadata setImageOrientation:someUIImageOrientation]; 24 | ``` 25 | 26 | ```objc 27 | [self.library writeImageDataToSavedPhotosAlbum:someImageData metadata:metadata.copy completionBlock:block]; 28 | ``` 29 | -------------------------------------------------------------------------------- /iOS--Perf.md: -------------------------------------------------------------------------------- 1 | Perf 2 | === 3 | 4 | キホン 5 | --- 6 | 7 | iPhone のリソースはかなり改善されてきた。 8 | キホンは、Main Thread で重い計算 / ブロックする処理を行わないだけ! 9 | `dispatch_async` で簡単にバックグラウンドスレッドにも持っていけるので、楽ちん。 10 | 11 | 画像 12 | --- 13 | 14 | ### 画像は GPU を使って縮小する 15 | 16 | CoreImage を使うと、GPU を使って画像をリサイズすることが出来る。 17 | 18 | - CoreImage - GPUを使って画像のリサイズ - Qiita : http://qiita.com/blurrednote/items/0d0c52a0d6c2bef1be72 19 | 20 | RecyclerView 関連 21 | --- 22 | 23 | ### UIImage を CALayer を使って描画する 24 | 25 | Control を扱わなくて良い部分(画像を表示するだけで良い)場合は、`CALayer` を使って描画したほうが速い。 26 | 27 | - A-Liaison BLOG: CALayer を使って UIImage を描画する : http://akisute.com/2010/08/calayer-uiimage.html 28 | 29 | ### Background Thread で画像を縮小してからメインスレッドに持ってくる 30 | 31 | `UIImageView - setImage:` で暗黙的に画像が縮小される。 32 | 33 | ```objc 34 | // image: UIImage 35 | 36 | dispatch_async(backgroundQueue, ^{ 37 | UIImage *resizedImage = [image your_resizedImage:CGSizeMake(100, 100)]; 38 | 39 | dispatch_async(dispatch_get_main_queue(), ^{ 40 | [cell.imageView setImage:resizedImage]; 41 | }); 42 | }); 43 | ``` 44 | 45 | リサイズは GPU で! 46 | 47 | ### AsyncDisplayKit を使う 48 | 49 | View の純計算部分を Background Thread で扱える。 50 | 既に計算が終わった View を Main Thread で突っ込むだけなので軽い。(Paper はコレ。) 51 | 52 | Core Data 関連 53 | --- 54 | 55 | ### Background Thread で動かす 56 | 57 | MagicalRecord を使えばイイ感じにつくれる。 58 | 59 | `contextForCurrentThread` を使う。 60 | -------------------------------------------------------------------------------- /iOS--Permissions.md: -------------------------------------------------------------------------------- 1 | Prepermissions & Rescue permissions 2 | --- 3 | 4 | iOS, 権限の認証が個別なのでうざいことになりやすい。ベストプラクティスをまとめたい。 5 | 6 | 1. 必要になったときに認証を要求する 7 | 2. 適切な文言を付ける 8 | 3. Per-permission する 9 | 4. Denied のときの Rescue をする 10 | 5. AniGIF て案内が提供されていれば尚良いと思う 11 | 12 | 13 | 14 | iOS8+ は 15 | --- 16 | 17 | - iOS8で復活した設定画面へのURLスキーム - Qiita : http://qiita.com/Night___/items/3d689d657ee691d2cabe 18 | 19 | iOS8 で「自分のアプリ」の設定への URL スキームが復活。コレを使うと「プライバシー」等とリンクがある設定ページに飛べる。 20 | 「プライバシー」から写真や通知等の Permission を弄れるので、iOS7 よりも Permission の復旧への導線を引きやすい。 21 | 22 | ### 参考 23 | 24 | https://vine.co/v/OZBY7mPw7ej 25 | 26 | トリビア 27 | === 28 | 29 | 文言を変える 30 | --- 31 | 32 | `-Info.plist` の `NSPhotoLibraryUsageDescription` を弄ることで、「カメラロールへのアクセスを許可しますか」の定型文の下に、自分の書いた文章を出せる。 33 | 34 | 何故アクセスが必要かの説明があれば、安心して許可しやすい。 35 | 36 | 37 | 38 | こんなかんじ 39 | 40 | Permission を何回もテストしたい 41 | -- 42 | 43 | Bundle Identifier をイイ感じに変えまくれば別アプリとして認識してくれる。 44 | 45 | Bundle Identifier を好きに変えてテスト出来ない通知だけはうまくいかないので、これを参照。 46 | 47 | http://kenmaz.hatenadiary.jp/entry/20110826/1314376887 48 | 49 | References 50 | --- 51 | 52 | - https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html 53 | - http://kenmaz.hatenadiary.jp/entry/20110826/1314376887 54 | - デバイスのアクセス許可を求めるUI | Reflection | UIデザイン会社Standard Incのブログ : http://www.standardinc.jp/reflection/article/ui-to-seek-the-permission-of-the-device/ 55 | -------------------------------------------------------------------------------- /iOS--PonyDebugger.md: -------------------------------------------------------------------------------- 1 | PonyDebugger 2 | === 3 | 4 | やばかった。 5 | 6 | CoreData: https://vine.co/v/OBVFZpg7QaX 7 | 8 | View Hierarchy: https://vine.co/v/OBVt1XZFYxd 9 | 10 | Installation 11 | --- 12 | 13 | https://github.com/square/PonyDebugger 14 | 15 | With Real Device 16 | --- 17 | 18 | `127.0.0.1` ではなく `0.0.0.0` でやる。 19 | 20 | Code 21 | --- 22 | 23 | ```objc 24 | PDDebugger *debugger = [PDDebugger defaultInstance]; 25 | [debugger enableCoreDataDebugging]; 26 | [debugger addManagedObjectContext:[[CoreDataManager sharedManager] managedObjectContext] withName:@"My MOC"]; 27 | [debugger enableNetworkTrafficDebugging]; 28 | [debugger enableRemoteLogging]; 29 | [debugger enableViewHierarchyDebugging]; 30 | [debugger autoConnect]; 31 | ``` 32 | 33 | こんなのを適当にぶち込む 34 | -------------------------------------------------------------------------------- /iOS--PrivatePod.md: -------------------------------------------------------------------------------- 1 | Private Pod 2 | --- 3 | 4 | #### 1.Private Repo を GitHub で作る 5 | 6 | 適当な名前で作る。 7 | 8 | #### 2.Repo を `pod repo add` する 9 | 10 | ```sh 11 | pod repo add REPO_NAME REPO_URL 12 | ``` 13 | 14 | でレポジトリを CocoaPods client に登録出来る 15 | 16 | #### 3.普通に podspec 作る 17 | 18 | LICENSE ファイルと、homepage の指定が必須で、かつ homepage はどこからでもアクセス出来なければならないことに注意。 19 | Google とか指定しとく。 20 | 21 | #### 4.`pod repo push` 22 | 23 | ```sh 24 | pod repo push REPO_NAME YOUR_POD.podspec 25 | ``` 26 | 27 | で push 出来る。 28 | 29 | #### 5.Podfile 30 | 31 | ```rb 32 | // Podfile 33 | 34 | source "https://github.com/TEAM/PATH.git" 35 | source "https://github.com/CocoaPods/Specs.git" 36 | ``` 37 | 38 | と `Podfile` に付けることで Pods をプライベートレポジトリからサーチすることが出来る 39 | -------------------------------------------------------------------------------- /iOS--ReactiveCocoa.md: -------------------------------------------------------------------------------- 1 | ReactiveCocoa 2 | === 3 | 4 | `RACSignal *` をイイ感じに弄るのが基本。 5 | 6 | ```objc 7 | [signal subscribeNext:^(id someSignal){ 8 | // Do something with someSignal 9 | }]; 10 | ``` 11 | 12 | Sources of `RACSignal` 13 | --- 14 | 15 | - `RACObserve(object, keypath)` - KVO の代わりに使える 16 | - `RAC(self.textEdit.text)` 17 | - `AFNetworking+RAC` の `- rac_GET:params:` - レスポンスをシリアライズした結果が value として流される。 18 | - `+ createSignal` で `RACSignal` を作ることが出来る。 19 | - あとは、デザインパターンがある https://github.com/tLewisII/RACExample/blob/master/Pods/ReactiveCocoa/ReactiveCocoaFramework/ReactiveCocoa/RACSignal.h 20 | 21 | `RACObserve(object, keypath)` は `object` の `keypath` の value を Observe して、変更されたらその value を signal として流す。 22 | 23 | e.g., 24 | 25 | ```objc 26 | [[RACObserve(dog, name) subscribeNext:^(id x) { 27 | NSLog(@"%@", x); 28 | }]; 29 | 30 | dog.name = @"Pochi"; 31 | dog.name = @"Tama"; 32 | 33 | // => Pochi 34 | // => Tama 35 | ``` 36 | 37 | 操作 38 | --- 39 | 40 | `- filter` で大体 OK. 41 | 基本的にリスト操作芸. 42 | 43 | References 44 | --- 45 | 46 | - http://qiita.com/ikesyo/items/ff0fdc179baa92a144ee - まとめリンク 47 | - Getting Started with ReactiveCocoa | Teehan+Lax : http://www.teehanlax.com/blog/getting-started-with-reactivecocoa/ 48 | - RACExample/RACSignal.h at master · tLewisII/RACExample : https://github.com/tLewisII/RACExample/blob/master/Pods/ReactiveCocoa/ReactiveCocoaFramework/ReactiveCocoa/RACSignal.h 49 | -------------------------------------------------------------------------------- /iOS--Resources.md: -------------------------------------------------------------------------------- 1 | Resources 2 | === 3 | 4 | - ダイナミック Objective-C http://news.mynavi.jp/column/objc/ 5 | - objc.io http://www.objc.io/ 6 | -------------------------------------------------------------------------------- /iOS--SQLite.md: -------------------------------------------------------------------------------- 1 | SQLite 2 | --- 3 | 4 | SQLite の COUNT は毎回フルスキャンする。ので、どうしても大きいテーブルをカウントしたい場合は、別テーブルに COUNT の数自体を持つ。 5 | 6 | - http://stackoverflow.com/questions/8988915/sqlite-count-slow-on-big-tables 7 | -------------------------------------------------------------------------------- /iOS--Safari-CreditCard.md: -------------------------------------------------------------------------------- 1 | http://qiita.com/okmr-d/items/c5c28117b999252e22ca 2 | -------------------------------------------------------------------------------- /iOS--SettingsBundle.md: -------------------------------------------------------------------------------- 1 | こんなんを入れることでライセンス表記を自動化出来る 2 | 3 | ```rb 4 | post_install do | installer | 5 | require 'fileutils' 6 | FileUtils.cp_r('Pods/Pods-acknowledgements.plist', 'film/Settings.bundle/Acknowledgements.plist', :remove_destination => true) 7 | end 8 | ``` 9 | 10 | これを入れなければ無理。(分かれた?) 11 | 12 | - https://github.com/CocoaPods/cocoapods-install-metadata 13 | 14 | なんか `0.34.0.rc2` では色々無理だった 15 | 16 | References 17 | --- 18 | 19 | - http://d.hatena.ne.jp/KishikawaKatsumi/20140211/1392111037 20 | -------------------------------------------------------------------------------- /iOS--Share-UIActivityViewController: -------------------------------------------------------------------------------- 1 | UIActivityViewController 2 | --- 3 | 4 | 事実上の標準 Share の規格。前まで、独自実装してた。 5 | 6 | - http://d.hatena.ne.jp/shu223/20121127/1354017518 - たった1行でWebサービスと連携!UIActivity のまとめリポジトリをつくりましたAdd Star 7 | - http://tech.kayac.com/archive/19_ios6uiacitivity_techkayaccom_advent_calendar_2012.html - #19 「iOS6のカスタムUIAcitivityのつくりかた」 tech.kayac.com Advent Calendar 2012Add Star 8 | - http://zutto-megane.com/objective-c/post-367/ - 写真を簡単にSNSに連携できる!UIActivityViewController 9 | 10 | 共有、アホらしいほどつらかったのが UIActivityViewController で公式サポートされた。 11 | 共有ビューはコレ使おう。 12 | -------------------------------------------------------------------------------- /iOS--Testing--TestDouble.md: -------------------------------------------------------------------------------- 1 | TestDouble 2 | == 3 | 4 | OCMock 5 | --- 6 | 7 | 基本の流れ 8 | 9 | ```objc 10 | SomeObject *objectMock = [OCMockObject niceMockForClass:[SomeObject class]]; 11 | 12 | // (1) 13 | [[objectMock expect] someMethod:[OCMArg any] withSomeArg:[OCMArg any]]; 14 | 15 | // (2) 16 | doSomeThingUsingMock(); 17 | 18 | // (3) 19 | [objectMock verify]; 20 | ``` 21 | 22 | 注意点は 23 | 24 | 1. 最初に `expect` を行う。 25 | 2. mock オブジェクトを用いた処理を行う。(ここで、`expect` したメソッドが呼ばれる) 26 | 3. 最後に `verify` を行う。 27 | 28 | 非同期テストの場合は、 29 | 30 | `[objectMock verityWithDelay:1.0]` などとする。 31 | 32 | Notification 33 | --- 34 | 35 | NSNotificationCenter part 3: Unit testing notifications with OCMock | Hermes Pique : http://www.hpique.com/2013/12/nsnotificationcenter-part-3/ 36 | 37 | ```objc 38 | - (void)testNotificationUserInfo 39 | { 40 | NSString *notificationName = @"someName"; 41 | id observerMock = [OCMockObject observerMock]; 42 | [[NSNotificationCenter defaultCenter] addMockObserver:observerMock name:notificationName object:_sender]; 43 | [[observerMock expect] 44 | notificationWithName:notificationName 45 | object:_sender 46 | userInfo:[OCMArg checkWithBlock:^BOOL(NSDictionary *userInfo) { 47 | id value = [userInfo objectForKey:@"someKey"]; 48 | STAssertEqualObjects(expectedValue, value, @""); 49 | return YES; 50 | } 51 | ]; 52 | 53 | [_sender doSomethingThatPostsTheNotification]; 54 | 55 | [observerMock verify]; 56 | [[NSNotificationCenter defaultCenter] removeObserver:observerMock]; 57 | } 58 | 59 | ``` 60 | 61 | OHHTTPStub 62 | --- 63 | 64 | HTTP request を Stub 出来る。 65 | 66 | ```objc 67 | [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { 68 | return YES; // 全てのリクエストを Stub する 69 | } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) { 70 | // 200 で `test_response.json` の中身を返す 71 | return [OHHTTPStubsResponse responseWithFileAtPath:@"test_response.json" statusCode:200 headers:nil]; 72 | }]; 73 | ``` 74 | 75 | 失敗させたいときは、Status コードを 400, 500 番台にすれば良い。 76 | 77 | ```objc 78 | [OHHTTPStubs stubRequestsPassingTest:^BOOL(NSURLRequest *request) { 79 | return YES; // 全てのリクエストを Stub する 80 | } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) { 81 | // 200 で `test_response.json` の中身を返す 82 | return [OHHTTPStubsResponse responseWithFileAtPath:@"500_response.json" statusCode:500 headers:nil]; 83 | }]; 84 | ``` 85 | 86 | References 87 | --- 88 | 89 | - Mocking Network Requests With OHHTTPStubs. - Adoption Curve Dot Net : http://adoptioncurve.net/archives/2012/10/mocking-network-requests-with-ohhttpstubs/ 90 | - Front Page · OCMock : http://ocmock.org/ 91 | - AliSoftware/OHHTTPStubs : https://github.com/AliSoftware/OHHTTPStubs 92 | -------------------------------------------------------------------------------- /iOS--Testing.md: -------------------------------------------------------------------------------- 1 | Testing 2 | === 3 | 4 | - Unit: `Specta`, `Expecta`, `OCMockito` 5 | - E2E: `KIF`, `Appium` 6 | 7 | ### `XCTest` で非同期 8 | 9 | ```objc 10 | - (void)testThatItAppendsAString; 11 | { 12 | NSString *s1 = @"Foo"; 13 | XCTestExpectation *expectation = [self expectationWithDescription:@"Handler called"]; 14 | [s1 appendString:@"Bar" resultHandler:^(NSString *result){ 15 | [expectation fulfill]; 16 | XCTAssertEqualObjects(result, @"FooBar"); 17 | }] 18 | [self waitForExpectationsWithTimeout:0.1 handler:nil]; 19 | } 20 | ``` 21 | 22 | ### `NSUserDefaults` をリセット 23 | 24 | ```objc 25 | NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier]; 26 | [[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain] 27 | ``` 28 | 29 | KIF 30 | --- 31 | 32 | ### Accessibility Label? 33 | 34 | 画面には出ないけれど、各 View に結びついている、アクセシビリティ用のラベル。 35 | 標準は画面に出てる文字列が設定されてる。 36 | たとえば「Start!」のボタンの Accessibility Label は `@"Start!"` 37 | 38 | Storyboard からは下記の場所で弄れる。 39 | 40 | ![](https://dl.dropboxusercontent.com/u/7817937/_github/__Film/accesibility_label.png) 41 | 42 | または、コード上でこれを変更することが出来る。 43 | 44 | ```objc 45 | view.accessibilityLabel = @"some_accessibility_label"; 46 | ``` 47 | 48 | ### `Photo Library` をテストする 49 | 50 | 方法は二つある。 51 | 52 | 1. `ALAsstesLibrary`, `PHAssetsLibrary` を mock する 53 | 2. Safari でひたすら画像を保存する 54 | 55 | 1.はなかなかの苦行なので、とりあえず2.でお茶を濁しておくのが良い。 56 | 57 | 実はシミュレータ上においても、Safari で画像を開き、ロングタップで画像を保存することが出来る。 58 | これは、もちろん `ALAssetsLibrary` などで読み取ることが出来る。 59 | 60 | 普通の iPhone で撮った写真を Dropbox でアップロードし、片っ端からダウンロードするのが良いと思う。 61 | 62 | ただし、シミュレータの端末種別を変えると、ライブラリの内容も変わるので注意。 63 | 64 | または、数が多ければ、zip を受け取って Photo Library に全てぶち込む専用のアプリを作って、シミュレータをセットアップするのが良い。 65 | 66 | ### `UICollectionView` の特定のセルをタップする 67 | 68 | ```objc 69 | // - _:cellForIndexPath: 70 | 71 | // For Testing 72 | cell.accessibilityLabel = [NSString stringWithFormat:@"kif_cell_%d", indexPath.row]; 73 | ``` 74 | 75 | ```objc 76 | // xxTests.m 77 | 78 | [tester tapViewWithAccessibilityLabel:@"kif_cell_1"]; // Taps second cell 79 | ``` 80 | 81 | References 82 | --- 83 | 84 | - Zillow: モバイルアプリの自動化テストフレームワーク - ワザノバ | wazanova : http://wazanova.jp/items/708 85 | - Etsy: モバイルアプリの継続的インテグレーション - ワザノバ | wazanova : http://wazanova.jp/items/1096 86 | -------------------------------------------------------------------------------- /iOS--Today-Extension.md: -------------------------------------------------------------------------------- 1 | 制限事項 2 | --- 3 | 4 | - パーミッションはアプリ側のパーミッションが継承される。 5 | - 画面サイズの制約 6 | * 1 スクロール大くらいの画面しか無理 7 | - 位置情報の制約 8 | * Today Extension で位置を取るには、アプリ側で「Allow Location Always」という強いパーミッションを取る必要が有る。これは、アプリが裏側で位置情報取る場合のパーミッション。 9 | - CALayer 弄れない 10 | * 角丸とかやりたいなら、GPUImage で強引にやる 11 | - メモリの制約 12 | * iPhone5 iOS8.0 の場合、メモリ 6MB くらいで死ぬ。画面に何も表示されない。 13 | * また、何もしなくても 3MB くらいいく 14 | * PhotoKit を動かしたら + 1.7MB くらい。 15 | - ジェスチャが取れない 16 | * TapGestureRecognizer は効く 17 | 18 | http://qiita.com/koogawa/items/994878047f76cf125b2d 19 | 20 | 注意すること 21 | --- 22 | 23 | - アプリと色々共有出来ない 24 | * `NSUserDefaults` はちょっとのコードで出来る `http://tapadoo.com/2014/sharing-nsuserdefaults-between-your-app-and-a-today-extension-on-ios-8/` 25 | * `UIPasteBoard` もちょっとのコードで出来る。 26 | 27 | NSUserDefaults の共有 28 | --- 29 | 30 | - AppGroup を作る 31 | - AppGroup の Certificate を登録する 32 | 33 | 通知情報 34 | --- 35 | 36 | http://hrk-ys.blogspot.jp/2014/06/whats-new-in-ios-notifications.html 37 | 38 | あと某氏から教えてもらった(一応 NDA で伏せておく) 39 | 40 | ``` 41 | 知見 42 | ・UIView ならだいたい何でも入る(なんでも出来る) 43 | ・タップはとれる。ジェスチャーは通知センターにとられる 44 | ・URL Request とか普通に出来る 45 | ・NSUserDefaults でアプリとデータ共有出来る 46 | 47 | kaiinui [11:32 PM] 48 | ・入力とかは出来ない(そもそも表示用だし) 49 | ・デバイスのセンサーとか(傾き・音声)とれるかは試してない 50 | 51 | kaiinui [11:32 PM] 52 | タッチとれるから単純な入力系ならいけそう 53 | 54 | kaiinui [11:32 PM] 55 | (初音ミクにタッチしたらおはようウィジェットとか) 56 | 57 | kaiinui [11:32 PM] 58 | あとタッチでしか入力出来ないけど zaim の入力とかできそう 59 | 60 | kaiinui [11:34 PM] 61 | 相当色んなこと出来るし、色んなアプリがここはいりそう(Gunosy, smartnews とかめっちゃやりたそう) 62 | 63 | kaiinui [11:34 PM] 64 | 音声いけるなら乗り換え案内アプリとかいけるかも 65 | 66 | kaiinui [11:34 PM] 67 | ・インストールされただけでは有効にならず、通知センターの「編集ボタン」で配置することで初めて表示されるようになる 68 | 69 | kaiinui [11:35 PM] 70 | ・(だから、こうやって配置するんだてきなインストラクションみたいなのは必要) 71 | 72 | kaiinui [11:35 PM] 73 | ・(ちなみに画面に飛ばす API はない) 74 | 75 | kaiinui [11:35 PM] 76 | ・(NSUserDefaults 共有出来るので、有効にしたかどうかはわかる。) 77 | 78 | ・高さはおおよそ画面いっぱい分(1 スクロール分)くらい。 79 | 80 | kaiinui [11:55 PM] 81 | サイズは 3.5 inch と 4 inch でそれぞれ決まってる。 82 | 83 | ``` 84 | 85 | -------------------------------------------------------------------------------- /iOS--Tools.md: -------------------------------------------------------------------------------- 1 | iOS 開発の便利ツールズ 2 | === 3 | 4 | - objClean : http://objclean.com/index.php 5 | - jfahrenkrug/StoryboardLint : https://github.com/jfahrenkrug/StoryboardLint 6 | - xcconfigs 7 | - mitmproxy 8 | - KILogInject 9 | - PonyDebugger 10 | - Injection for XCode 11 | - mergepbx (ヤバい!!!) 12 | - Reflector 13 | 14 | - CocoaPods から Settings.bundle に勝手に突っ込む http://mzgk.github.io/blog/2014/cocoapods-license-auto-make/ 15 | -------------------------------------------------------------------------------- /iOS--UICollectionView.md: -------------------------------------------------------------------------------- 1 | http://labs.gree.jp/blog/2013/12/9669/ 2 | -------------------------------------------------------------------------------- /iOS--UIWebView-Native.md: -------------------------------------------------------------------------------- 1 | UIWebView アレコレ 2 | === 3 | 4 | - `UIWebView` の `UIScrollView` は `webView.scrollView` で参照することが出来る 5 | - `UIWebView` のスクロールは標準で減速しやすいようになっている(WebView 特有のもっさり感の原因の一つ) 6 | * `.scrollView.decelerationRate` を `UIScrollViewDecelerationRateNormal` にすることでネイティブの速度に 7 | - `UIWebView` のページ領域外のグレーは `.backgroundColor` を弄ることで消せる 8 | - `-webkit-tap-highlight-color` を alpha 0 の色にすることで、タップ時のハイライトを消すことが出来る。 9 | - FastClick を使えばタップ時のディレイを無くすことが出来る 10 | 11 | 以上をやれば違和感は結構消える。 12 | あとは、ロードの遅さとかを上手く誤摩化す。 13 | 14 | References 15 | --- 16 | 17 | - (52) How do you make UIWebView behave like a native app? - Quora : http://www.quora.com/How-do-you-make-UIWebView-behave-like-a-native-app 18 | - ios - Remove gradient background from UIWebView? - Stack Overflow : http://stackoverflow.com/questions/3009063/remove-gradient-background-from-uiwebview 19 | -------------------------------------------------------------------------------- /iOS--WebView.md: -------------------------------------------------------------------------------- 1 | iOS - SwiftでNSURLProtocolを使ってUIWebViewの広告をブロックする - Qiita : http://qiita.com/shzero5/items/755fd80bc759a5460c43 2 | -------------------------------------------------------------------------------- /iOS--i18n.md: -------------------------------------------------------------------------------- 1 | iOS での i18n 2 | --- 3 | 4 | ベストプラクティスっぽいの。 5 | 6 | 1. `NSLocalizedString` をラップする 7 | 2. `.strings` は元ファイルをパースして生成する 8 | 3. 翻訳が出てるかテストする 9 | 4. Scheme を言語毎に作る 10 | 5. `.plist` の翻訳もテストする 11 | 6. View が崩れないか、または文字がはみ出ないかチェックする 12 | 13 | ### `NSLocalizedString` をラップする 14 | 15 | ```objc 16 | // R.m 17 | 18 | + (NSString *)string_hello_world { 19 | return NSLocalizedString(@"HELLO_WORLD", @""); 20 | } 21 | ``` 22 | 23 | pros: テストしやすい。キーがばらけない。リファクタリングしやすい。 24 | 25 | ### `.strings` は元ファイルをパースして生成する 26 | 27 | キーがとんでもなく間違えやすいので、元ファイルを一括してキー対応させて生成する方が良い 28 | 29 | ### 翻訳が出てるかテストする 30 | 31 | ```objc 32 | it(@"Label 'Hello World' should be translated.", ^{ 33 | expect([R string_hello_world]).notTo.contain(@"HELLO_WORLD"); 34 | expect([R string_hello_world]).notTo.contain(@"Hello World"); //if it is 'Hello World' in Base.strings 35 | }); 36 | ``` 37 | 38 | これで翻訳ちゃんと指定の場所に出てるかテスト出来る。 39 | また、UI が崩れないようにテストするの、ラベルの長さを指定して、このようにしてもよい思う。 40 | 41 | ```objc 42 | it(@"Label 'Hello World' should be not so long", ^{ 43 | expect([R string_hello_world]).to.shorterThan(20); 44 | }); 45 | ``` 46 | 47 | また、謝った翻訳ラベルを指定していないかテストが出来る。 48 | 49 | ``` 50 | it(@"Label 'Hello World' should be properly translated", ^{ 51 | expect(helper_isAllUpperCase([R string_hello_world])).to.equal(NO); 52 | }); 53 | ``` 54 | 55 | ここで、 `helper_isAllUpperCase()` は lowercase を含まないかどうかを返す関数である(e.g. `HELLO_WORLD` に対して `YES` を返す) 56 | 57 | ### Scheme を言語毎に作る 58 | 59 | 以上はテスト毎に言語を設定すると手間が死ぬので自動化する。 60 | 61 | Scheme を作り、`Arguments` を以下のように設定すればシミュレータがその言語で起動する 62 | 63 | ![](http://i.gyazo.com/f175f54ca1168b44e08a9c4923cb16f9.png) 64 | 65 | これを言語分つくりやる。 66 | 67 | ### `xcodebuild` で自動化する 68 | 69 | ``` 70 | xcodebuild -workspace Post.xcworkspace -scheme PostTests-ja -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' test 71 | xcodebuild -workspace Post.xcworkspace -scheme PostTests-en -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' test 72 | ... 73 | ``` 74 | 75 | 実際的には for 文で回す。 76 | 77 | ```sh 78 | #!/bin/sh 79 | 80 | for lang in ja en de da el en-GB es-MX es fr-CA fr id it ko ms nl pt-PT pt ru sv th tr vi zh-Hans zh-Hant 81 | do 82 | xcodebuild -workspace Post.xcworkspace -scheme "PostTests-$lang" -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' test 83 | done 84 | ``` 85 | 86 | みたいな感じ 87 | 88 | 表示が崩れないか、文字がはみ出ないかチェックする 89 | --- 90 | 91 | ギリシャ語などは異常に長いので、文字がはみ出ないかを気をつける。 92 | これは、前述のシナリオでスクショを撮りまくり見ると良い。 93 | 94 | `- setFontSizeAdjustToWidth` を使うと良い。指定は Font Scale が良い。 95 | UILabel は高さの Constraints だけ指定し、横は 20 くらいそれぞれ空けた 100% でセンタリングが良い。 96 | 97 | Line Break を word wrap に設定し、 Line count = 0 にすれば自動的に改行する 98 | -------------------------------------------------------------------------------- /iOS--pod-library.md: -------------------------------------------------------------------------------- 1 | CocoaPods で自分のライブラリを管理 2 | --- 3 | 4 | `#{NAME}.podspec` ファイルをルートに置けばOK 5 | 6 | ```rb 7 | Pod::Spec.new do |s| 8 | s.name = "KIIncam" 9 | s.version = "0.1.0" 10 | s.summary = "Inline camera. No modal to take a picture." 11 | s.description = "Inspired by Facebook messenger's inline camera UI. People might not need to open a modal to take a picture." 12 | s.homepage = "https://github.com/kaiinui/incam" 13 | s.license = "MIT" 14 | s.author = { "kaiinui" => "lied.der.optik@gmail.com" } 15 | s.source = { :git => "https://github.com/kaiinui/incam.git", :tag => "v0.1.0" } 16 | s.source_files = "incam/Classes/**/*.{h,m}" 17 | s.requires_arc = true 18 | s.platform = "ios", '7.0' 19 | end 20 | ``` 21 | 22 | 中身はこんな感じ。 23 | 24 | dependency は `s.dependency "AFNetworking", "~> 2.3"` みたいなのをどんどん足す。 25 | 26 | ##### `.xcdatamodeld` 27 | 28 | `.xcdatamodeld` は resource ではなく `source_files` に突っ込む。 29 | 30 | 利用 31 | --- 32 | 33 | `pod 'MyLibrary', :path => '../MyLibrary'` 34 | 35 | とかとすることでローカルの Pod を利用出来る。 36 | 37 | pod 'MyLibrary', :git => 'https://github.com/stevenpsmith/YahooWeatherService.git', :tag => 'v0.0.3' 38 | 39 | みたいにすれば git にあげてる Pod を利用出来る 40 | 41 | 参考 42 | --- 43 | 44 | - http://qiita.com/somtd@github/items/9386e2185adfff4c54bc 45 | - http://chariotsolutions.com/blog/post/using-cocoapods-to-manage-private-libraries/ 46 | -------------------------------------------------------------------------------- /iOS--workflow.md: -------------------------------------------------------------------------------- 1 | iOS workflow 2 | --- 3 | 4 | - Beta 5 | - mitmproxy 6 | - ikonica 7 | - travis 8 | 9 | Test 10 | --- 11 | 12 | - Specta & Expecta 13 | - KIF 14 | - Appium 15 | -------------------------------------------------------------------------------- /iOS-CI.md: -------------------------------------------------------------------------------- 1 | CI 2 | === 3 | 4 | iOS の CI やろうとして嵌ったのをメモ 5 | 6 | xctools 7 | --- 8 | 9 | なんか動かないし、`xcodebuild` で出来るので、 10 | 11 | ``` 12 | xcodebuild -workspace InPlaceEdit.xcworkspace -scheme InPlaceEditTests -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' test 13 | ``` 14 | 15 | 指定出来るリストは 16 | 17 | ``` 18 | OS:7.1, name:iPad 2 19 | OS:8.0, name:iPad 2 20 | OS:7.1, name:iPad Air 21 | OS:8.0, name:iPad Air 22 | OS:7.1, name:iPad Retina 23 | OS:8.0, name:iPad Retina 24 | OS:7.1, name:iPhone 4s 25 | OS:8.0, name:iPhone 4s 26 | OS:7.1, name:iPhone 5 27 | OS:8.0, name:iPhone 5 28 | OS:7.1, name:iPhone 5s 29 | OS:8.0, name:iPhone 5s 30 | OS:8.0, name:iPhone 6 Plus 31 | OS:8.0, name:iPhone 6 32 | OS:8.0, name:Resizable iPad 33 | OS:8.0, name:Resizable iPhone 34 | ``` 35 | 36 | 以下は古い情報。(iOS 7.1 と Xcode 5.1) 37 | 38 | ``` 39 | iPhone Retina (3.5-inch) 40 | iPhone Retina (4-inch) 41 | iPhone Retina (4-inch 64-bit) 42 | iPad 43 | iPad Retina 44 | iPad Retina (64-bit) 45 | ``` 46 | 47 | Scheme 48 | --- 49 | 50 | 左上の `プロジェクト名` を押して、`Manage Scheme` を押す。 51 | 52 | ![](https://dl.dropboxusercontent.com/u/7817937/_github/__Film/__train_activate_travis/1.png) 53 | 54 | `プロジェクト名` の Shared を ON にする。 55 | 56 | ![](http://i.gyazo.com/e8982094ab941bdcdde1153553a74895.png) 57 | 58 | 以下のようになっているのを確認。 59 | 60 | ![](http://i.gyazo.com/84ae618bcabe79d811cee39ebdfe00f4.png) 61 | 62 | .travis.yml 63 | --- 64 | 65 | ``` 66 | language: objective-c 67 | notifications: 68 | email: false 69 | 70 | before_install: gem install cocoapods 71 | 72 | script: 73 | - pod install 74 | - xcodebuild -workspace InPlaceEdit.xcworkspace -scheme InPlaceEditTests -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch 64-bit)' test 75 | ``` 76 | 77 | References 78 | --- 79 | 80 | - Debugging XCTool’s NSInternalInconsistencyException: Failed while trying to gather build settings for your scheme : http://code.dblock.org/debugging-xctools-nsinternalinconsistencyexception-failed-while-trying-to-gather-build-settings-for-your-scheme 81 | - Xcode5環境で、xcodebuildを使ってユニットテスト実行する方法 - Qiita : http://qiita.com/k_kinukawa/items/6c5ef09ad86ac9c75a8c 82 | - http://kaspermunck.github.io/2013/04/running-kiwi-specs-with-travis-ci/ 83 | - Etsy: モバイルアプリの継続的インテグレーション - ワザノバ | wazanova : http://wazanova.jp/items/1096 84 | -------------------------------------------------------------------------------- /iOSDev.md: -------------------------------------------------------------------------------- 1 | iOS Development 2 | === 3 | 4 | 色んな数値とか ⇒ http://qiita.com/mox2/items/d1d112faac644976791a 5 | 6 | 言語の基本仕様 7 | --- 8 | 9 | - Object の Messaging 教に入信した人が作った言語っぽい。どんなメソッド呼び出しも明示的にメッセージングである。self のメソッドも [self hogeMethod]; としないと呼べないあたりが特に。 10 | - nil receiver でのメソッド呼び出しは無視される 11 | - Key-value coding という仕組みがあって、静的言語なのに property が動的に弄れたりする 12 | - Messaging を forward 出来たりする(Ruby の `method_missing` 相当) 13 | - method を swizzling 出来る(メソッドの中身入れ替えられたりする。) 14 | - ARC (Automatic Reference Counting) を用いてのメモリ管理。明示的に `free` する必要は無い。 15 | * Android は GC 搭載!富豪的! 16 | - 全体的によく出来てる言語の気がするけど、メソッド名が長いのが嫌われる。どうせ補完するから書く分には困らないのだけど、確かに初見だと辛い。 17 | 18 | Blocks の循環参照 19 | --- 20 | 21 | Blocks, 簡単に循環参照を起こす。 22 | 23 | `self` を Block の中で使ってたら既に循環参照。weakify して `weakSelf` とかして頑張る必要ある。 24 | 25 | あるいは、 Block を使い終わった後すぐに nil で殺す。 26 | 27 | [TOOD] もうちょい調べる 28 | 29 | RAC 30 | --- 31 | 32 | ReactiveCocoa, iOS で Rx 出来る。 33 | 出来るのは 34 | 35 | - RACSignal で普通に Stream (AFNetworking とかも AF で promise チックなことが出来る) 36 | - Value observation (KVO よりも Stream の処理が楽) 37 | - Stream の map とか filter とか merge とかそういうの 38 | * Validation で云々とか楽々! 39 | 40 | ##### 参考 41 | 42 | * ReactiveCocoa勉強会関西を開催しました #rac_kansai http://ninjinkun.hatenablog.com/entry/2014/08/03/204348 43 | 44 | Data Store 45 | --- 46 | 47 | CoreData, 生で使うの相当だるいのでこのあたりを使う。 48 | 49 | - Realm 50 | - MagicalRecord 51 | 52 | ###Realm 53 | 54 | SQLite alternative な mobile-oriented database. 55 | 56 | 1 MB くらいの footprint で色々いい感じのデータベース使える。 57 | 58 | 1. ORM 59 | 2. Transaction 60 | 3. Thread Safe 61 | 62 | ORM が大変良く出来ている。 63 | 64 | ```objc 65 | // Model 66 | Dog *mydog = [[Dog alloc] init]; 67 | mydog.name = @"Rex"; 68 | 69 | // Save 70 | RLMRealm *realm = [RLMRealm defaultRealm]; 71 | [realm beginWriteTransaction]; 72 | [realm addObject:mydog]; 73 | [realm commitWriteTransaction]; 74 | 75 | // Query 76 | RLMArray *r = [Dog objectsWhere:@"age > 8"]; 77 | ``` 78 | 79 | KeyChain 80 | --- 81 | 82 | 安全にデータ保管するの KeyChain を使う。 `LUKeyChainAccess` が相当楽。 83 | 84 | http://qiita.com/kaiinui/items/e9bf25daed9bba46d8c7 85 | 86 | #### KeyChain Sharing 87 | 88 | 同じデベロッパーのアプリの間であれば KeyChain のデータを共有することが出来る。 89 | 90 | http://qiita.com/itoz/items/cac060f940e67d97ab9d 91 | 92 | こういうのはちゃんと使って認証を二度と入力させないようにしたい。 93 | 94 | .pbxproj merge 95 | --- 96 | 97 | .pbxproj がキチガイみたいにコンフリクトするのでこういうのを使う。 98 | 99 | https://github.com/simonwagner/mergepbx 100 | 101 | 導入 ⇒ http://qiita.com/gfx/items/9182b9591c1589153897 102 | 103 | R.m 104 | --- 105 | 106 | rdotm https://github.com/ksoichiro/rdotm 107 | 108 | を使うと Android ライクに [R strings_hoge]; で取れる。ミススペルで表示されないミスが無くなる。 109 | 110 | Test 111 | --- 112 | 113 | テスト、`Specta` と `Expecta` 使うとイイ感じに RSpec 風に出来る。大変黒魔術満載でよい。 114 | 115 | ```objc 116 | #import 117 | #define EXP_SHORTHAND 118 | #import 119 | 120 | SpecBegin(AQModel) 121 | 122 | describe(@"AQAquasyncModelRequirement", ^{\ 123 | describe(@"-aq_resolveConflict:delta;", ^{ 124 | NSDictionary *delta = @{ 125 | @"gid": @"aaaaaaaa-e29b-41d4-a716-446655dd0000", 126 | @"localTimestamp": @2000000000, 127 | @"deviceToken": [AQUtil getDeviceToken], 128 | @"isDeleted": @NO 129 | }; 130 | it(@"should update from delta", ^{ 131 | AQModel *model = [[AQModel alloc] init]; 132 | model.gid = @"aaaaaaaa-e29b-41d4-a716-446655dd0000"; 133 | [model save]; 134 | [model aq_resolveConflict:delta]; 135 | expect(model.localTimestamp).to.equal(2000000000); 136 | }); 137 | 138 | it(@"updated record should not be dirty", ^{ 139 | AQModel *model = [[AQModel alloc] init]; 140 | model.gid = @"aaaaaaaa-e29b-41d4-a716-446655dd0000"; 141 | [model save]; 142 | [model undirty]; 143 | [model aq_resolveConflict:delta]; 144 | expect(model.isDirty).to.equal(false); 145 | }); 146 | }); 147 | }); 148 | 149 | SpecEnd 150 | ``` 151 | 152 | Mock は `OCMockito`. 153 | 154 | 他参考 155 | --- 156 | 157 | - https://github.com/hatena/ios-Intern-Bookmark-2013 - はてなの iOS インターン向け研修 158 | - https://github.com/mixi-inc/iOSTraining/wiki/ - mixi の研修資料 159 | -------------------------------------------------------------------------------- /libGDX.md: -------------------------------------------------------------------------------- 1 | libGDX 2 | === 3 | 4 | チュートリアル 5 | --- 6 | 7 | http://www.gamefromscratch.com/page/LibGDX-Tutorial-series.aspx 8 | -------------------------------------------------------------------------------- /protocol-buffers.md: -------------------------------------------------------------------------------- 1 | Protocol Buffers 2 | --- 3 | 4 | エディタ? 5 | --- 6 | 7 | IntelliJ IDEA に Protocol Buffers Support がある。 8 | 9 | とりあえず入門 10 | --- 11 | 12 | ```proto 13 | package someproj; 14 | 15 | message Book { 16 | required string title = 1; 17 | required int32 page_number = 2; 18 | } 19 | ``` 20 | 21 | 1 とか 2 とかは、プロパティの ID みたいなん。 22 | プロパティを特定しているのは、`title` とかではなく `1`. 23 | これによって、`title` をやっぱり `name` にしたり出来る。 24 | 25 | 各言語の実装 26 | --- 27 | 28 | - Java, C++, Python: http://github.com/google/protobuf 29 | - Golang: goprotobuf 30 | - Objective-C: http://protobuf.axo.io/ 31 | 32 | `protoc` は `brew install protobuf` で入れられる模様。 33 | 34 | `protoc --go_out=. *.proto` とかでコンパイルする。 35 | 36 | Objective-C のコンパイルは 37 | 38 | `protoc --plugin=/usr/local/bin/protoc-gen-objc *.proto --objc_out="./"` 39 | 40 | ### 注意 41 | 42 | `protoc-gen-go` は `protoc` 無ければ何もないので注意必要 43 | 44 | とりあえず実装 45 | --- 46 | 47 | サーバ (Go) 48 | 49 | ```go 50 | func main() { 51 | m := martini.Classic() 52 | m.Get("/books/:id", book) 53 | m.Run() 54 | } 55 | 56 | func book(w http.ResponseWriter, r *http.Request) { 57 | book := &Book{ 58 | BookId: proto.String("1"), 59 | Title: proto.String("Harry Potter And Something!"), 60 | PageNumber: proto.Int32(322), 61 | } 62 | data, _ := proto.Marshal(book) 63 | 64 | _, _ = w.Write(data) 65 | } 66 | ``` 67 | 68 | クライアント (iOS) 69 | 70 | ```objc 71 | - (void)viewDidLoad 72 | { 73 | [super viewDidLoad]; 74 | 75 | NSData *bookData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://0.0.0.0:3000/books/somebook"]]; 76 | 77 | Book *book = [Book parseFromData:bookData]; 78 | 79 | NSLog(@"%@", book); 80 | 81 | // Do any additional setup after loading the view, typically from a nib. 82 | } 83 | ``` 84 | 85 | `.proto` 86 | 87 | ```proto 88 | package main; 89 | 90 | message Book { 91 | required string book_id = 3; 92 | required string title = 1; 93 | required int32 page_number = 2; 94 | } 95 | ``` 96 | 97 | データのアレコレを考えなくていいのは楽 98 | 99 | データ構造変えたらどうなるか? 100 | --- 101 | 102 | #### 項目の追加 103 | 104 | `required string author_name = 4;` を足して、 "foo" を入れてみた。 105 | 106 | ![](http://i.gyazo.com/bd0c3f874f1b5ebe57471d950a444856.png) 107 | 108 | シリアライズは問題なく出来る。 109 | 110 | ### プロパティ名の変更 111 | 112 | `page_number` -> `page_count` にしてみた。 113 | 114 | 上手く行く。クライアント側では `page_number` として解釈されている。 115 | 116 | やはり、プロパティ名に紐づいた id でプロパティの対応付けが管理されているようだ。 117 | 118 | ![](http://i.gyazo.com/e2a3997f0ed36ef09626cac34888a42a.png) 119 | 120 | レポジトリ 121 | --- 122 | 123 | - https://github.com/kaiinui/try-protobuf-ios 124 | - https://github.com/kaiinui/try-protobuf-go 125 | 126 | 今後の課題 127 | --- 128 | 129 | - `List` はどうするか? `BookCollection` という Message で reeatable な Book にしている? 130 | 131 | 参考資料 132 | --- 133 | 134 | - https://github.com/google/protobuf 135 | - http://protobuf.axo.io/#objc 136 | - https://code.google.com/p/goprotobuf/source/browse/README 137 | --------------------------------------------------------------------------------