工作六年 我终于学会了这项技能 可惜晚了!!!
在程序員的生涯中,無論是在跳槽還是晉升的時候都有遇到各種各樣被考察的情況,隨著軟件開發(fā)工作資歷不斷積累,這些考察要求和條件逐漸變高。
不會單純用工作年限來判斷候選人是否合格,因為畢竟寫三年 CRUD 純業(yè)務(wù)和做三年系統(tǒng)研發(fā)的工作經(jīng)歷和工作質(zhì)量是大不相同的,這樣會存在不小的問題,尤其是在招聘高級開發(fā)工程師時。而算法題面試也一樣,跳槽必刷題,已經(jīng)很難分辨候選人是當場想出來的,還是刷題記住的答案。傳統(tǒng)的八股文、算法、前沿技術(shù)源碼等知識內(nèi)容已經(jīng)不再新鮮,而一些"軟技能"像系統(tǒng)設(shè)計面試將會考察環(huán)節(jié)中較為重要的一環(huán)。
為了能讓面試更有效,采用系統(tǒng)設(shè)計題來考察高級開發(fā)工程師就是很好的選擇。因為系統(tǒng)設(shè)計題覆蓋面廣,不像算法題那樣在網(wǎng)上四處流傳,候選人想刷也沒法刷,只能拼技術(shù)。
這些軟技能并不會直接考察所了解到的某個知識點或者是某一片知識點所連接起來的部分知識面,而是去查看一位工程師在整體層面和理解應(yīng)用程序設(shè)計上的功底是否深厚;這類問題不像算法題那樣在網(wǎng)上四處流傳,想刷題也沒法刷,只能拼技術(shù)。雖然不會牽扯到某個知識點,比如某個控件是如何實現(xiàn)并說出內(nèi)部實現(xiàn)原理,但是會讓談下這個控件的優(yōu)點有哪些或如何在原有的基礎(chǔ)上進行改進;
這樣能讓整個考察環(huán)節(jié)變得更加有效,面試官就能準確地判斷出候選人的技術(shù)實力,同時從而給到合適的待遇和定級。
在面試系統(tǒng)設(shè)計題時,又該怎么評價候選人呢?對此,大家可以參考下圖的總結(jié)。
在本文中,我將分享移動端中關(guān)于如果被問及到如何設(shè)計一個系統(tǒng)的設(shè)計問題該如何進行回答,以及我是如何去解決系統(tǒng)設(shè)計問題的秘訣。聽起來很有趣?…… keep reading
?
系統(tǒng)設(shè)計問題涉及的問題
Eason去觀看了很多不同類型的系統(tǒng)設(shè)計教程視頻,并做了一些關(guān)于這方面的總結(jié),我覺得這些總結(jié)不僅僅是適用于系統(tǒng)設(shè)計,也是另一種對自己技術(shù)棧的要求和查漏補缺的方式;下面是羅列出來程序設(shè)計中必須要考慮到的方面:
1.功能需求——首先需要定義應(yīng)用的用例和一些功能。
2.非功能性要求——定義性能、經(jīng)驗和規(guī)模要求。
3.假設(shè)——定義問題的邊界、任何規(guī)模約束、特征等。
4.客戶端-服務(wù)器通信——定義連接選項,如 HTTP 請求、輪詢、服務(wù)器端事件。
5.API 設(shè)計——定義所構(gòu)建的功能端點。
6.數(shù)據(jù)模型——定義對象的數(shù)據(jù)模型字段。
7.應(yīng)用流程(用例流程) ——定義并執(zhí)行正在設(shè)計的功能的用戶流程。
8.性能和工具——定義大家將如何收集數(shù)據(jù)和指標以查看應(yīng)用程序的性能包括內(nèi)存利用率、CPU 利用率等。
9.ADA — 確保大家定義了輔助功能以及應(yīng)用程序的可訪問性。
10.國際化——隨著應(yīng)用程序在國際上的發(fā)展,需要處理這款系統(tǒng)應(yīng)用的國際適配。
11.安全性——定義如何去保護應(yīng)用程序。
?
具體實現(xiàn)
現(xiàn)在,讓我們通過一個例子來說明設(shè)計一個系統(tǒng)為何需要以上的這些結(jié)構(gòu):假設(shè)題目是被要求設(shè)計一個能展現(xiàn)出日常生活中的趣聞趣事App;
? ?
1. 功能需求
顯示我周圍有趣的地方列表。
向下滾動時加載更多
2. 非功能性需求
該列表應(yīng)該加載非常快或具有低延遲
滾動性能
數(shù)據(jù)異步加載且顯示不應(yīng)錯位
列表不應(yīng)抖動
3.假設(shè)
每天有多少活躍用戶?用戶量級多少?
API 是否可用?我們需要明智地使用它們
4.客戶端-服務(wù)器通信
常規(guī) HTTP 請求——這是客戶端向服務(wù)器請求數(shù)據(jù)/資源的最通用用例場景。例如,獲取提要中提要項目的列表一般會采用哪些輪詢方式?
定期輪詢- 客戶端可以不斷向服務(wù)器發(fā)出請求以獲取最新信息,但很多時間服務(wù)器可能沒有任何更新可提供。這不僅導(dǎo)致大部分時間響應(yīng)為空,而且在多次設(shè)置 HTTP 連接時會浪費資源。
長輪詢——如果我們有一個用例,我們知道內(nèi)容不會從服務(wù)器頻繁更新。在這種情況下,我們可以做的就是使用長輪詢。客戶端會與服務(wù)器建立 HTTP 連接,并保持與服務(wù)器的連接打開,以便服務(wù)器可以在有任何推送時向客戶端推送更新。這樣我們就節(jié)省了打開和關(guān)閉與服務(wù)器連接的無用工作。并需要記住,這個長輪詢連接也可能超時,因此在這種情況下需要重新啟動連接。
WebSockets——在客戶端和服務(wù)器都可以發(fā)起通信并且客戶端和服務(wù)器之間不斷來回的情況下,我們可以使用 WebSockets。這個用例的一個很好的例子是聊天應(yīng)用程序。
服務(wù)器端事件 (SSE) —客戶端與服務(wù)器建立持久性和長期連接。服務(wù)器使用此連接發(fā)送數(shù)據(jù)。客戶端處于偵聽模式,因為只有服務(wù)器才能與客戶端通信。如果客戶端需要與服務(wù)器通信,則需要使用不同的協(xié)議。這個用例是說,我們有一個社交媒體應(yīng)用程序,列出了朋友的提要。但是現(xiàn)在,如果在我們使用應(yīng)用程序時剛剛發(fā)生了更新,客戶端可以通過服務(wù)器端事件 (SSE) 協(xié)議輕松獲取這些更新。
5. API 設(shè)計
API 通過協(xié)議相互通信。常見的協(xié)議有 SOAP、REST 和 GraphQL。有關(guān)這些的詳細信息雖然并不是本文的一部分,不過大家感興趣可以自己去拓展一下。對于我們這個展示感興趣內(nèi)容的App,REST 應(yīng)該沒問題,它基本適用于大多數(shù)的場景。根據(jù)我們的要求,需要設(shè)計以下類型的Api:
a) 我們需要一個地點列表
b) 由于我們列出了附近的地點,因此我們想到的一件事是 API 調(diào)用需要某種位置信息來返回數(shù)據(jù),且可以是我們的查詢參數(shù)。
c) 分頁處理。考慮到這是一個移動應(yīng)用程序,我們沒有像臺式機或筆記本電腦那樣的無限資源,如計算/連接和電源,我們需要小心獲取的數(shù)據(jù)量,不能同時一次性全部加載出來或者把數(shù)據(jù)下拉下來。因此,最好分塊獲取數(shù)據(jù)并在需要時獲取更多數(shù)據(jù)。所以我們需要有能力分頁請求數(shù)據(jù),這就是分頁的用武之地。Offset、KeySet 和 Cursor Based 是不同類型的分頁服務(wù)器支持。對于我們的用例,我們可以選擇其中任何一個。但我個人更偏向喜歡用偏移分頁。所以我們會有一個頁碼和頁數(shù)限制來限制資源的數(shù)量。考慮到這一點,我們的 API 可能看起來像這樣?
GET — /places?lat={}&long={}&page={}&pageLimit={}
6. 數(shù)據(jù)模型
在設(shè)計某個系統(tǒng)模型的時候,得把基礎(chǔ)架構(gòu)給先定好,好比系統(tǒng)應(yīng)用是高樓,數(shù)據(jù)模型則是地基;在本文中,將向大家介紹如何是高效并有意義的潛在數(shù)據(jù)模型。考慮到整個需求涉及到的功能,所以將數(shù)據(jù)模型設(shè)計成下述圖表(簡化后的模型)👇
7. 應(yīng)用流程
以下是我們可以可能需要用到的任何設(shè)計架構(gòu)模式。
可以是:
MVC——模型視圖控制器
MVVM——模型視圖視圖模型
MVP——模型視圖Presenter
VIPER等
對于一般較為簡單的用例,我采用比較多的是MVVM。大家平時應(yīng)該使用常用并有意義的模式,并且在工作上也同樣可以采取照搬的方式套用過去,從而提高工作效率,減少造輪子的時間。
8. 性能
這節(jié)本來是可以放在解決非功能性需求和任何其他與性能相關(guān)部分,因為是考察環(huán)節(jié)中比較重要的一點所以再次拿出來展開和大家聊一下,App設(shè)計中有哪些方法可以用來提高應(yīng)用程序性能?
布局優(yōu)化:
刪除布局中無用的控件和層次,其次有選擇地使用性能比較低的ViewGroup。
采用標簽,標簽,ViewStub.
避免過度繪制
繪制優(yōu)化:
onDraw中不要創(chuàng)建新的局部對象。
onDraw方法中不要做耗時的任務(wù),循環(huán)執(zhí)行方法后十分搶占CPU的時間片,這會造成View的繪制過程不流暢
內(nèi)存泄漏優(yōu)化:
在開發(fā)過程中避免寫出有內(nèi)存泄漏的代碼
通過一些分析工具比如MAT來找出潛在的內(nèi)存泄露,然后解決。
響應(yīng)速度優(yōu)化:響應(yīng)速度優(yōu)化的核心思想就是避免在主線程中做耗時操作。
ListView/RecycleView及Bitmap優(yōu)化
使用ViewHolder模式來提高效率
異步加載:耗時的操作放在異步線程中
ListView/RecycleView的滑動時停止加載和分頁加載
對加載圖片進行壓縮,避免加載圖片多大導(dǎo)致OOM出現(xiàn)。
線程優(yōu)化:線程優(yōu)化的思想就是采用線程池,避免程序中存在大量的Thread。
其他性能優(yōu)化的建議
① Show Skeleton - 某種東西正在加載的感知概念讓用戶感覺數(shù)據(jù)加載速度更快。在加載數(shù)據(jù)時顯示一些 Skeleton 會對感知的用戶體驗產(chǎn)生巨大影響
② 使用具有適當尺寸的圖像。如果 API 支持高度和寬度作為查詢參數(shù),那么大家將能拿到對圖片顯示有意義的結(jié)果。用戶的眼睛無法分辨圖像大小之間的差異,但它因為加載的數(shù)據(jù)較少從而對應(yīng)用程序的性能產(chǎn)生巨大影響。
③ 使用內(nèi)容交付網(wǎng)絡(luò) (CDN)進行靜態(tài)圖像緩存,以幫助更快地交付內(nèi)容。在我們的App中,將 CDN 用于圖像和靜態(tài)內(nèi)容,將地點描述文本和圖像緩存至云端。
④ 在后臺線程上加載數(shù)據(jù),這樣主線程永遠不會被阻塞,UI 永遠不會卡住。
以上是一些常見優(yōu)化性能的做法,大家也可以在面試期間去主動深入了解其他的方法。
9.可訪問性和動態(tài)性
我們始終希望每個人都使用我們的應(yīng)用程序。為了讓它真正具有包動態(tài)性,我們需要在我們的應(yīng)用程序中處理可訪問性。以下是我們可以做的一些事情來解決可訪問性問題:
確保顏色對比度正確
每個目標尺寸至少為 44pt
為可訪問性標注添加自定義調(diào)用
使用適當?shù)呐渖桨?/p>
支持動態(tài)字體類型
對例如GTXilib 的庫使用自動檢查,以便他們可以確保每個 UI 元素都有一個標簽、適當?shù)奶卣鳌撕灢皇嵌嘤嗟摹?/p>
上面提到的做法可以應(yīng)用于任何移動應(yīng)用程序。大家也可以在 Google 和Apple網(wǎng)站上閱讀有關(guān)可訪問性的更多信息。
10. 國際化/本地化
應(yīng)用程序的國際化為其用戶提供了本地和個人體驗,這對應(yīng)用程序的使用和采用很有幫助。通常,我們可以通過為應(yīng)用程序中的內(nèi)容/文本使用不同的本地化字符串文件 strings.xml 來支持這一點。
大家還可以使用高級技術(shù),例如將設(shè)備區(qū)域設(shè)置發(fā)送到服務(wù)器,然后服務(wù)器返回本地化文件。根據(jù)需要,大家可以采取不同的路線來實現(xiàn)本地化,這也是Goolge 官方對于本地化的指南。
11. 安全
安全是一個非常廣泛和復(fù)雜的話題。作為移動應(yīng)用程序的開發(fā)人員,大家需要在平時日常工作中學(xué)會并遵循一些提示和技巧:
使用簽名和加密數(shù)據(jù)
編譯與反編譯
NDK與反匯編
加殼與脫殼
?
結(jié)論
系統(tǒng)設(shè)計的重點是考察我們作為工程師從整體層面來看待/理解應(yīng)用程序設(shè)計的能力,而不僅僅是單個部分知識點或知識面的細節(jié)。關(guān)于系統(tǒng)設(shè)計的答案,從來就不存在最優(yōu)解,畢竟世上本來就沒有完美的答案
有道無術(shù),術(shù)可成;有術(shù)無道,止于術(shù)
歡迎大家關(guān)注Java之道公眾號
好文章,我在看??
總結(jié)
以上是生活随笔為你收集整理的工作六年 我终于学会了这项技能 可惜晚了!!!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学会了CopyOnWriteArrayL
- 下一篇: mysql忘记密码怎末版_mysql忘记