開發者也是用戶 — 第一部分:構建更具可用性的 UI 與 API 的 5 個方針

在前一篇文章中,咱們探討了 UI 可用性與 API 可用性的重要性,並說明了 UI 可用性原則能夠應用於 API。下面是前文連接:html

開發者也是用戶 - 簡介 可用性 - 學於 UI,用於 API前端

在本文中,咱們將具體討論前 5 條可用性方針:android

  1. 系統狀態的可見性
  2. 讓系統符合真實世界
  3. 爲用戶提供自由的操做方式
  4. 一致性與標準
  5. 預防錯誤的發生

1. 系統狀態的可見性

系統應當在合理的時間,經過合適的反饋,讓用戶瞭解它正在作什麼。ios

**UI:**當用戶進行一項須要耗費較長時間的操做時,應告知用戶操做的進度。例如,在加載圖片時顯示一個進度條,在上傳下載文件時顯示百分比。應當讓用戶知道正在讓他們等待的是什麼,須要花多長時間。git

上圖:告知用戶當前狀態。圖片來源github

**API:**API 應當提供某種能夠查詢當前狀態的方式。例如,AnimatedVectorDrawable 類提供了一個方法來檢查動畫是否正在運行:數據庫

boolean isAnimationRunning = avd.isRunning();
複製代碼

API 能夠採用回調機制來給出反饋,讓 API 用戶知道對象在什麼時候改變了狀態 —— 相似於動畫開始與結束時的通知。例如,AnimatedVectorDrawable 對象能夠 registering 一個 AnimationCallback 來完成上述操做。後端

2. 讓系統符合真實世界

應用程序應當「說」用戶的語言,使用用戶熟悉的短語和概念,而不該該使用面向系統的術語。bash

上圖:使用用戶熟悉的概念。圖片來源app

類與方法的命名應符合用戶的預期

**API:**當在一個新的 API 中查找類時,用戶可能無從下手,於是依賴以前使用相似 API 的經驗,或者依賴在 API 領域通用的觀念。例如,當使用 Glide 或者 Picasso 下載並展現圖片時,用戶極可能會去查找名爲「load」或「download」的方法。

3. 爲用戶提供自由的操做方式

爲用戶提供撤銷操做的機會。

**UI:**某些用戶發起的操做可能含有歧義,例如「刪除」或「存檔」郵件。此時應顯示一條消息讓用戶確認,並容許用戶撤銷此操做。

上圖:容許用戶撤銷當前操做。圖片來源

API 應容許中斷或重置操做,並能簡單地將 API 恢復到正常狀態

**API:**例如,Retrofit 提供了一個 Call#cancel 的方法,此方法會嘗試取消飛行模式下的 call 調用,以及取消還未被 execute 執行的 call 調用,讓其以後也再也不會執行。此外,若是你在使用 NotificationManager,你會發現既能夠建立通知也能夠取消(cancel)通知。

4. 一致性與標準

你的應用程序的用戶不該該去思考不一樣的文本、情景或者操做是否有着一樣的意義。

**UI:**與你的 app 進行交互的用戶在此以前已經經過與其它 app 交互獲得了訓練,他們會但願各個應用的可交互元素的樣式與行爲都相同。若是偏離了這些慣例,那麼用戶就會更容易出錯。

所以,UI 須要與平臺保持一致,並使用用戶熟悉的 UI 控件,以方便用戶快速識別並使用它們。此外,一致性應當貫穿你的整個應用。在 app 的不一樣界面中,使用相同的文字與圖表來表示相同的東西。例如,在你的 app 中用戶能夠修改多個元素,那麼請使用相同的修改圖標。

上圖:對話框應該與平臺保持一致。圖片來源

**API:**全部的 API 設計都應遵循一致性原則。

各個方法應保持命名的一致性

請參考下面的例子。假設咱們有一個 interface 暴露了兩個設置不一樣類型 observer 的方法:

public interface MyInterface {
    
    void registerContentObserver(ContentObserver observer);
    void addDataSetObserver(DataSetObserver observer);
}
複製代碼

使用它的用戶可能會思考:register…Observeradd…Observer 究竟有什麼區別呢?是否一個方法一次接受一個 observer,另外一個方法一次能夠接受多個 observer 呢?開發者要麼去認真閱讀文檔,要麼去查找 interface 的實現,來研究兩個方法的行爲是否相同。

private List<ContentObserver> contentObservers;
private List<DataSetObserver> dataSetObservers;
public void registerContentObserver(ContentObserver observer) {
    contentObservers.add(observer);
}
public void addDataSetObserver(DataSetObserver observer){
    dataSetObservers.add(observer);
}
複製代碼

所以,請爲作一樣事情的方法進行 相同的命名

能夠在命名時考慮使用反義詞,例如:get - set,add - remove,subscribe - unsubscribe,show - dismiss。

各個方法應保持參數順序的一致性

在重載方法時,須要確保在新舊方法中都存在的參數的順序保持一致。不然,你的 API 用戶將要花更多的時間來理解重載與被重載方法的區別。

void setNotificationUri( ContentResolver cr,
                         Uri notifyUri);
void setNotificationUri( Uri notifyUri,
                         ContentResolver cr,
                         int userHandle);
複製代碼

避免在函數中使用連續的、同類型的參數

雖然在 Android Studio 中,使用連續的多個相同類型的參數是件簡單的事情,可是這樣作很容易致使參數順序出錯,而且很難找到這種錯誤。參數的順序應當儘量與參數的邏輯順序一致。

當這些參數的類型都相同時,用戶很容易犯錯。例如上圖中 county 和 country 就弄反了。

爲了解決這種問題,你可使用建造者模式,或者應用 Kotlin 的 命名參數(named parameters)

方法的參數應不大於 4 個

參數越多,意味着方法越複雜。用戶須要理解每一個參數在方法中起到的做用以及與其它參數的關係,也就是說每增長一個參數都會致使方法的複雜度呈指數形式增長。當一個方法的參數超過 4 個時,就能夠考慮將其中一些參數封裝在其它類中或使用構造器了。

返回值會影響方法的複雜度

當一個方法返回某個值時,開發者須要知道這個值表明着什麼,如何存儲它等。若是不須要用到這個值,那麼它也不該當對方法的複雜度形成影響。

例如,當向數據庫插入一個元素時,Room 既能夠返回 Long 也能夠返回 void。如用戶須要使用返回值時,首先須要瞭解此返回值的意義,以及如何存儲它。而在不須要返回值時,用戶可使用 void 類型方法。

@Insert
Long insertData(Data data);
@Insert
void insertData(Data data);
複製代碼

所以,你應當容許 API 用戶本身決定是否須要返回值。若是你正在開發一個基於代碼生成器的庫,應該容許其生成返回多種可選類型的方法。

5. 預防錯誤的發生

建立防範於未然的設計。

**UI:**用戶常常會一心多用,所以你應當防止用戶在無心識下形成的錯誤,減小用戶「翻車」的機會。比方說你能夠在毀滅性操做前彈框要求確認,或者提供正確的缺省值。

好比,Google Photos 應用會彈出一個確認框來確保你刪除相冊不是誤操做;而 Inbox 的「郵件稍後提醒」功能僅需一鍵操做。

上圖:Google Photo 在毀滅性操做前彈出確認框;Inbox 在暫停收件操做時提供方便選擇的缺省值。

API 應該引導用戶正確地使用 API。儘量使用缺省值。

API 應當易於使用,且能防止誤用。經過提供缺省值能夠幫助用戶正確使用 API。例如,當建立 Room 數據庫時,有一個缺省值能夠確保在升級數據庫版本時數據不丟失。因爲數據庫版本對用戶來講是透明的,又由於升級時數據會保持,因此使用 Room 的應用程序對用戶來講易用性更好。

與此同時,Room 也提供了一個方法 fallbackToDestructiveMigration 用於改變這種行爲,若是沒有提供遷移方法,那麼在數據庫版本改變時會銷燬並從新建立數據庫。


深刻了解另外 5 條原則請訪問: 讓用戶認知,而不是回憶 彈性、高效的使用方式 優雅、極簡的設計 幫助用戶認識、判斷、改正錯誤 提供幫助與文檔


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索