在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ Omni 內(nèi)部
與四軸無(wú)人機(jī)的通訊
在沙盒中編寫(xiě)腳本
結(jié)構(gòu)體和值類(lèi)型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測(cè)試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動(dòng)開(kāi)發(fā)
Collection View 動(dòng)畫(huà)
截圖測(cè)試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個(gè)完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動(dòng)布局工具箱
動(dòng)畫(huà)
為 iOS 7 重新設(shè)計(jì) App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實(shí)例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類(lèi)
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動(dòng)畫(huà)解釋
響應(yīng)式 Android 應(yīng)用
初識(shí) TextKit
客戶(hù)端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項(xiàng)目介紹
Swift 的強(qiáng)大之處
測(cè)試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機(jī)制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計(jì)優(yōu)雅的移動(dòng)游戲
繪制像素到屏幕上
相機(jī)與照片
音頻 API 一覽
交互式動(dòng)畫(huà)
常見(jiàn)的后臺(tái)實(shí)踐
糟糕的測(cè)試
避免濫用單例
數(shù)據(jù)模型和模型對(duì)象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場(chǎng)
照片框架
響應(yīng)式視圖
Square Register 中的擴(kuò)張
DTrace
基礎(chǔ)集合類(lèi)
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點(diǎn)互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計(jì)的藝術(shù)
導(dǎo)航應(yīng)用
線(xiàn)程安全類(lèi)的設(shè)計(jì)
置換測(cè)試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無(wú)人機(jī)項(xiàng)目
Mach-O 可執(zhí)行文件
UI 測(cè)試
值對(duì)象
活動(dòng)追蹤
依賴(lài)注入
Swift
項(xiàng)目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測(cè)試 View Controllers
訪談
收據(jù)驗(yàn)證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場(chǎng)
游戲
調(diào)試核對(duì)清單
View Controller 容器
學(xué)無(wú)止境
XCTest 測(cè)試實(shí)戰(zhàn)
iOS 7
Layer 中自定義屬性的動(dòng)畫(huà)
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲(chǔ)
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺(jué)
Artsy
照片擴(kuò)展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫(kù)支持
Fetch 請(qǐng)求
導(dǎo)入大數(shù)據(jù)集
iOS 開(kāi)發(fā)者的 Android 第一課
iOS 上的相機(jī)捕捉
語(yǔ)言標(biāo)簽
同步案例學(xué)習(xí)
依賴(lài)注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識(shí)別
玩轉(zhuǎn)字符串
相機(jī)工作原理
Build 過(guò)程

Omni 內(nèi)部

Omni 集團(tuán)是一家屬于員工的公司,在這里,人們可以帶他們的狗來(lái)上班。

換句話(huà)說(shuō):當(dāng)你考慮如何管理大型項(xiàng)目時(shí),首先得考慮文化 ?!拔覀?nèi)绾谓M織項(xiàng)目?用什么樣的源代碼控制管理?” 文化并不糾結(jié)于這些細(xì)節(jié),一個(gè)優(yōu)秀的文化會(huì)形成一個(gè)快樂(lè)的團(tuán)隊(duì),他們將弄清楚如何一起工作。而 Omni 在文化建設(shè)上的成果可謂豐碩。

Omni 的文化可以另撰一篇長(zhǎng)文,但在這里不打算涉及太多。相反,這里是一次圍繞著技術(shù)的游歷,著重于討論我們?nèi)绾喂芾碜约旱?App。

組織扁平化

所有的工程師向 Tim Wood 進(jìn)行匯報(bào),他是 Omni 的 CTO 和創(chuàng)始人。每個(gè)產(chǎn)品都有一個(gè)項(xiàng)目經(jīng)理。

各個(gè) App 的項(xiàng)目組是流動(dòng)的。項(xiàng)目組本身不會(huì)經(jīng)常或隨意地變動(dòng),不過(guò)它們終究還是會(huì)變化。

內(nèi)部交流

因?yàn)榇蠹叶荚谵k公室工作,所以我們會(huì)面對(duì)面的溝通。有時(shí)會(huì)召開(kāi)會(huì)議,其中一些是提前安排好的,而另一些則是臨時(shí)決定的。每個(gè)人都會(huì)參加一周一次的全體員工大會(huì),時(shí)間大約是 20 分鐘。主要部門(mén)主管和項(xiàng)目經(jīng)理說(shuō)明接下來(lái)的工作方向。在之后還有每周的開(kāi)發(fā)會(huì)議,這也持續(xù)約 20 分鐘。討論一些大家普遍關(guān)心的開(kāi)發(fā)事項(xiàng) (用于規(guī)避逐個(gè)找人溝通,雖然有時(shí)還是不得不這樣做)。

面對(duì)面的交流得益于 Omni 的核心工作時(shí)間:人們希望每天早上11點(diǎn)到下午4點(diǎn)的時(shí)間都在辦公室內(nèi)度過(guò),所以你知道你可以在那個(gè)時(shí)間里找到想找的人。(不過(guò),你也可以來(lái)的或早或晚,隨你心意,只要你在工作上投入了一整周的時(shí)間。)

其它途徑的話(huà),包括 E-mail,包括一些郵件列表,和我們內(nèi)部的聊天室加上私信。(我們最近將 Message 和 Jabber 替換為了一套可以保存歷史記錄的系統(tǒng),它還可以播放 GIF。)

Bug

每一個(gè)開(kāi)發(fā)組織都有至少一個(gè)人負(fù)責(zé)解決 Bug 追蹤系統(tǒng)中反饋的問(wèn)題。Omni 使用了一個(gè)內(nèi)部的 Mac 應(yīng)用 OmniBugZapper (OBZ) ,它具有那些你期望擁有的功能。它不像一些公開(kāi)應(yīng)用那樣矚目,但它卻是一個(gè)很有用的工具。

(在OmniBugZapper中的) 一個(gè)典型的工作流是:你在當(dāng)前階段發(fā)現(xiàn)了一個(gè) Bug,將它的優(yōu)先級(jí)調(diào)為高,然后打開(kāi)它,使其他人可以看見(jiàn)你正在解決這個(gè) Bug。

一旦問(wèn)題解決,你在這個(gè) Bug 上添加一條筆記說(shuō)明你做了什么來(lái)搞定它,或許也會(huì)說(shuō)明如何去測(cè)試,然后你寫(xiě)上了版本管理系統(tǒng)中的版本號(hào)。

你將 Bug 的狀態(tài)切換為“驗(yàn)證”,然后一位測(cè)試接收并確定 Bug 是否真的被修復(fù)了。如果沒(méi)有被解決,它可能會(huì)重新被打開(kāi)。如果修復(fù)衍生出了一個(gè)新的 Bug,一個(gè)新的 Bug 會(huì)被添加至 OmniBugZapper。

一旦處于“驗(yàn)證”狀態(tài)的 Bug 通過(guò)了測(cè)試,它會(huì)被標(biāo)記為“已解決”。

(前方高能:開(kāi)發(fā)者與測(cè)試者之間的關(guān)系并非敵對(duì),雖然我已經(jīng)在幾家公司聽(tīng)說(shuō)過(guò)類(lèi)似的事情。有些時(shí)候當(dāng)你覺(jué)得測(cè)試的工作就是折磨你,但這才該是常態(tài)。這意味著他們做了了不起的工作,我們都有著同樣的目標(biāo),那就是做一個(gè)棒棒的應(yīng)用出來(lái)。)

有一些 Bug 的修復(fù)需要工程師來(lái)驗(yàn)證,但這比較少見(jiàn)。大部分 Bug 是通過(guò)測(cè)試來(lái)驗(yàn)證的。(驗(yàn)證的工程師與修復(fù)的工程師不可以是同一個(gè)人。)

有些 Bug 是永遠(yuǎn)不會(huì)被修復(fù)或者驗(yàn)證的。它們包括討論型 Bug 和參考型 Bug:我們通過(guò)在的前者基礎(chǔ)上進(jìn)行討論來(lái)決定某個(gè)功能的改變或者增加,而后者可以用來(lái)對(duì)某個(gè)特性的行為或者出現(xiàn)做一些注解。

階段 (里程碑) 管理

OmniBugZapper 有階段管理 (milestones) 的概念,自然,它有一個(gè)階段監(jiān)視器窗口,我們可以看到當(dāng)前階段的進(jìn)度和狀態(tài)。

每一個(gè)階段都劃分為分析、計(jì)劃和驗(yàn)證。Bug 會(huì)經(jīng)過(guò)分析變?yōu)橛?jì)劃,或者留至以后解決。

決定一個(gè) Bug 或者功能的開(kāi)發(fā)階段與發(fā)布版本是合作式的,每一個(gè)想要參與的人都可以參加。通常,項(xiàng)目經(jīng)理會(huì)做大部分的決定。在比較大的問(wèn)題上,通常會(huì)進(jìn)行更多的討論,我們一般會(huì)達(dá)成共識(shí),不過(guò)我們不會(huì)通過(guò)投票決定設(shè)計(jì)問(wèn)題,我們的 CEO,Ken Case,有最終決定權(quán)。Ken 負(fù)責(zé)規(guī)劃未來(lái)。

譯者注:Milestones 可被翻譯為里程碑圖,是項(xiàng)目管理中的一種工具。為明確其功能,此處翻譯為階段管理,而每一個(gè) Milestone 則被翻譯為階段。

源代碼控制管理

我們使用 SVN。所有的應(yīng)用與網(wǎng)站都在一個(gè)巨型的代碼倉(cāng)庫(kù)中。我絲毫不驚訝于每個(gè)人的開(kāi)發(fā)副本只是其中的一部分,而非全部。

你可能會(huì)覺(jué)得 SVN 是一個(gè)還未封印的史前工程師產(chǎn)物,并好奇人們關(guān)于切換工具的考慮。不過(guò) SVN 干的還不錯(cuò),如何簡(jiǎn)化對(duì)一個(gè)大型倉(cāng)庫(kù)的管理,總有些值得討論的事情。

我們有很多個(gè)腳本幫助我們做這些工作。比如,當(dāng)我想得到 OmniFocus 的最后一次更改,我輸入./Update OmniFocus,然后它會(huì)更新我的開(kāi)發(fā)副本 (通常我每天第一件事就是做這個(gè))。我的開(kāi)發(fā)副本中沒(méi)有 OmniGraffle,只因?yàn)槲也恍枰P(guān)注它。但我也可以使用 ./Update OmniGraffle。

SVN 創(chuàng)建分支可能不像 Git 與 Mercurial 那樣方便,但也沒(méi)有那么困難。每當(dāng)我們的應(yīng)用接近發(fā)布時(shí),我們會(huì)建立一個(gè)分支,用于隔離其它的變動(dòng)。人們可以出于各種目的隨時(shí)創(chuàng)建私人分支與目錄。

提交信息通過(guò) E-mail 發(fā)送給工程師和其它關(guān)注項(xiàng)目的人。

崩潰

由于應(yīng)用被置于大量自身也有 Bug 的系統(tǒng)框架上面,而應(yīng)用也運(yùn)行在實(shí)際的用戶(hù)的電腦上而非理想運(yùn)行環(huán)境中,所以無(wú)法保證一個(gè)應(yīng)用從來(lái)不會(huì)崩潰。

不過(guò)確保我們自己的代碼不會(huì)崩潰是我們的職責(zé),如果我們發(fā)現(xiàn)系統(tǒng)框架中有一個(gè)會(huì)導(dǎo)致崩潰的 Bug,我們需要找到方法繞過(guò)它,以讓代碼正常工作。

我們使用了一些圖形化的統(tǒng)計(jì)來(lái)展示一個(gè)應(yīng)用在崩潰之前的平均運(yùn)行時(shí)間。我們還有一個(gè)內(nèi)部應(yīng)用叫做 OmniCrashSorter,我們可以看到一些被標(biāo)記出來(lái)的崩潰日志,包括異常的追蹤調(diào)用棧,以及一些用戶(hù)崩潰場(chǎng)景的記錄。

關(guān)于崩潰有這么一個(gè)掃興的問(wèn)題:崩潰永遠(yuǎn)不會(huì)在開(kāi)發(fā)時(shí)出現(xiàn) (這似乎是一個(gè)軟件開(kāi)發(fā)中的鐵律)。 這使得用戶(hù)的崩潰報(bào)告以及重現(xiàn)步驟非常重要。所以我們收集這些報(bào)告,并讓它們易于被查看。

有時(shí),我們會(huì)刻意使崩潰發(fā)生在異常中。因?yàn)槲覀兊膽?yīng)用使用自動(dòng)保存,崩潰會(huì)比可能出現(xiàn)的臟數(shù)據(jù)覆寫(xiě)更為安全。

代碼

我們?cè)趦?nèi)部的 Wiki 上有一個(gè)簡(jiǎn)單的代碼風(fēng)格規(guī)范,而我因?yàn)樵缫咽炀毜膽?yīng)用,反而忘了它說(shuō)的是什么。

除了一個(gè)事情之外,方法應(yīng)當(dāng)像這樣開(kāi)頭:

- (void)someMethod;
{

或許很多人并不知道,在 Objective-C 中允許這樣使用分號(hào)。沒(méi)錯(cuò),是允許的。

這種方式比較好的地方在于,它可以使我們很容易的將類(lèi)的聲明拷貝到頭文件或者類(lèi)的擴(kuò)展當(dāng)中。而且,你可以選擇一整行,Command+E,然后查找包含它的頭文件 (或者從頭文件查找回你實(shí)現(xiàn)它的 .m 文件)。

我不喜歡這個(gè)方式。對(duì)我這樣一個(gè)極簡(jiǎn)主義強(qiáng)迫癥來(lái)說(shuō),分號(hào)太多余了,而所有多余的事情都應(yīng)該被去掉。(想象我的 X-ACTO 刻刀慢慢的繞著一個(gè)分號(hào)刻上一圈,伴隨著一陣東北風(fēng),把它刮到空氣中,離開(kāi)我的桌子,然后散落進(jìn)垃圾桶里,真是說(shuō)不出的暢快。)

不過(guò)這只是我沒(méi)事兒時(shí)的抱怨。我想說(shuō)的重點(diǎn)在于,我們需要一個(gè)代碼規(guī)范,而且每個(gè)人都使用它。然后我們?cè)陂喿x彼此的代碼時(shí),就不會(huì)被引誘著去爭(zhēng)論關(guān)于分號(hào)的問(wèn)題。我們不應(yīng)該只為了比拼彼此的口味,把時(shí)間浪費(fèi)在重新格式化已經(jīng)寫(xiě)好的代碼上。

共享框架

Omni 所有的應(yīng)用在某種程度上是同一個(gè)大型應(yīng)用,因?yàn)樗鼈円蕾?lài)于很多個(gè)共享的框架。這些框架一部分是開(kāi)源的,你可以閱讀相關(guān)的信息,并在GitHub上獲取源碼。還有一些額外的內(nèi)部框架,一部分用在每一個(gè)應(yīng)用中,還有一些則只用在部分應(yīng)用里。

共享的框架使開(kāi)發(fā)一些不同的應(yīng)用變得更容易,而且開(kāi)發(fā)組的替換也變的方便,畢竟大部分框架都是相同的。

當(dāng)然,有一點(diǎn)不好的地方,是某個(gè)框架發(fā)生了變化可能一次性影響多個(gè)應(yīng)用。不過(guò)解決這個(gè)問(wèn)題的唯一方法就是解決它,Bug 就是 Bug。

(當(dāng)項(xiàng)目快要發(fā)布時(shí),我們會(huì)建立一個(gè)新分支,用來(lái)防止在接下來(lái)的幾周中框架開(kāi)發(fā)中產(chǎn)生的變化。)

ARC

新的代碼往往是基于 ARC 的。雖然有大量的舊代碼還未被轉(zhuǎn)換,但這也沒(méi)什么問(wèn)題。畢竟隨著運(yùn)行情況的變化,被調(diào)校的代碼只應(yīng)該是那些需要被校正的。不過(guò)有些時(shí)候它們依舊應(yīng)該被轉(zhuǎn)換。(我已經(jīng)做過(guò)一部分關(guān)于轉(zhuǎn)換的工作,以后還會(huì)做更多。我覺(jué)得使用 ARC 寫(xiě)出不會(huì)發(fā)生崩潰的代碼會(huì)更容易一些。)

Swift

雖然一批工程師已經(jīng)開(kāi)始編寫(xiě) Swift 的代碼,Swift 目前尚未出現(xiàn)在我們的任何應(yīng)用和框架中。

不過(guò)這也說(shuō)不準(zhǔn),或許在明天,或許在一兩年之后,又或許就在你閱讀本篇文章的當(dāng)下,改變就會(huì)發(fā)生。

測(cè)試

OmniFocus 中有覆蓋模型類(lèi)的單元測(cè)試;其他應(yīng)用也有差不太多的測(cè)試覆蓋率。我們與其他 OS X 和 iOS 開(kāi)發(fā)者面對(duì)面臨的問(wèn)題是相同的,每個(gè)應(yīng)用的 UI 元素都很多,而做自動(dòng)化的 UI 測(cè)試卻很困難。我們的 Mac 應(yīng)用的解決方案是基于 AppleScript 的測(cè)試。(這是確保應(yīng)用支持 AppleScript 的主要原因之一,而為了確保該支持的功能狀態(tài)正常,編寫(xiě)測(cè)試是一種很好的辦法)

對(duì)于 Cocoa 的開(kāi)發(fā)者來(lái)說(shuō),測(cè)試并不像在 Ruby,JavaScrpit 以及 Python 的開(kāi)發(fā)中那么重要,這主要是因?yàn)榫幾g器和靜態(tài)分析可以捕獲到很多腳本語(yǔ)言捕獲不到的問(wèn)題。

不過(guò)它們依舊很重要。

斷言

你可以在我們的代碼中看到我們正在使用的一些斷言:OBASSERT_NOT_REACHED, OBPRECONDITION, OBASSERT,等等。

我們使用這些斷言來(lái)表示一些推測(cè)和意圖。它們是為了我們自己的以及其它工程師開(kāi)發(fā)的后續(xù)版本中而編寫(xiě)的,我們大量的使用它們。

斷言太多的不好的地方在于你獲取到失敗的判定時(shí),你不得不找到原因。為什么代碼沒(méi)有按照期望運(yùn)行?是因?yàn)閿嘌允褂缅e(cuò)誤么,是不是斷言代碼需要被拓展或者修改?

我花了一段時(shí)間查看了許多的控制臺(tái)輸出記錄來(lái)確定這是不是個(gè)好方法,結(jié)論是,它是。

構(gòu)建

Xcode 結(jié)構(gòu)組織

每一個(gè) App 都有一個(gè) workspace 文件,里面包括了 OS X 和 iOS 的項(xiàng)目,并嵌入了許多項(xiàng)目中使用的框架。

配置文件

我們大量的使用 .xconfig 文件。你可以在我們的代碼中看到一大堆。

在 Omni 中,這是我之前沒(méi)有使用過(guò)的東西,甚至好幾個(gè)月都不曾看過(guò),只知道它們可以正常被使用就行了。

Debug Builds

調(diào)試構(gòu)建

OmniFocus 使用獨(dú)立的數(shù)據(jù)庫(kù)和一些偏好設(shè)置進(jìn)行調(diào)試版本的構(gòu)建,所以開(kāi)發(fā)者不需要擔(dān)心真實(shí)數(shù)據(jù)被調(diào)試數(shù)據(jù)污染。

(我們其它的應(yīng)用是基于文檔的應(yīng)用,所以并不完全適合上述方法,不過(guò) OmniFocus 之外的應(yīng)用也會(huì)使用獨(dú)立的 App ID 來(lái)構(gòu)建調(diào)試版本。)(譯者注:防止和線(xiàn)上版本沖突或者 iCloud Drive 污染)

靜態(tài)分析

靜態(tài)分析被設(shè)置為深度配置,包括調(diào)試版本的構(gòu)建。本應(yīng)如此。

自動(dòng)構(gòu)建

我們有一個(gè)用于構(gòu)建的服務(wù)器,當(dāng)然,我們會(huì)在構(gòu)建失敗的時(shí)候得到提醒。OmniAutoBuild 是另一個(gè)內(nèi)部使用的 Mac App,我們可以在軟件中查看是什么導(dǎo)致了構(gòu)建的失敗。

構(gòu)建完整的、可發(fā)布的程序是由腳本完成的。我們會(huì)設(shè)置標(biāo)記將構(gòu)建好的版本放在演示服務(wù)器上,所以外部的試用版測(cè)試者可以下載最新的測(cè)試版本。

iOS 的測(cè)試版則使用 TestFlight。

沒(méi)有魔法

真希望我可以說(shuō)自己有一些秘密咒語(yǔ),這樣我就可以把它們告訴你。

不過(guò),實(shí)際上,在 Omni 管理大型項(xiàng)目與你所想像的方式?jīng)]什么差別。詳細(xì)的溝通與定義 - 交流到人,聊天,使用 OmniBugZapper,使用斷言,做代碼審查,遵守編碼規(guī)范 - 這些都很重要。

接下來(lái)的事情是自動(dòng)化:讓電腦做它們最擅長(zhǎng)的事情。

不過(guò),回到最初,有一些事情是在選擇 Bug 追蹤系統(tǒng)、 代碼控制管理系統(tǒng)或者其它什么事情之前的,那就是公司文化。與優(yōu)秀的人一起建立一個(gè)基于信任、尊重的環(huán)境,他們會(huì)做出更好的決定,并從壞決定中吸取教訓(xùn)。

好消息是這些事情都在有條不紊地進(jìn)行中。

還有午餐,工作午餐。我們都在一起吃飯,這會(huì)產(chǎn)生一些區(qū)別。

P.S. Many thanks to the folks at Omni who read drafts of this article and provided feedback: Rachael Worthington, Curt Clifton, Jim Correia, Tim Ekl, Tim Wood, and Ken Case. Anything weird or wrong is my fault, not theirs.

另外,非常感謝 Omni 中閱讀過(guò)這篇文章草稿并提出反饋的人們,Rachael Worthington,Curt CliftonJim Correia,Tim EklTim WoodKen Case。如果有什么奇怪的錯(cuò)誤,一定是我犯了錯(cuò),不是他們。