欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java開發(fā)技巧代碼寫的快且bug少的原因分析

 更新時間:2022年12月13日 08:38:19   作者:leobert-lan  
這篇文章主要為大家介紹了java開發(fā)中代碼寫的快且bug少的原因分析及技巧詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

讀者諸君,今日我們適當(dāng)放松一下,不鉆研枯燥的知識和源碼,分享一套高效的摸魚絕活。

我有一位程序員朋友,當(dāng)時在一個團(tuán)隊(duì)中開發(fā)Android應(yīng)用,歷經(jīng)多次考核后發(fā)現(xiàn):

在組內(nèi)以及與iOS團(tuán)隊(duì)的對比中:

  • 他的任務(wù)量略多
  • 但他的bug數(shù)量和嚴(yán)重度均低
  • 但他加班的時間又少于其他人

不禁令人產(chǎn)生好奇,他是如何做到代碼別的又快,質(zhì)量又高的

經(jīng)過多次研究我終于發(fā)現(xiàn)了奧秘。

為了行文方便我用"老L"來代指這位朋友。

最常見的客戶端bug

  • "老L,聽說昨晚上線,你又坐那摸魚看測試薅別人,有什么秘訣嗎?"
  • 老L:"秘訣?倒也談不上,你這么說,我倒是有個問題,你覺得平日里最常見的bug有哪些?"
  • "emm,編碼上不健壯的地方,例如NPE,IndexOutOfBoundsException,UI上的可就海了去了,文本長度不一導(dǎo)致顯示不下,間距問題,亂七八糟的一大堆"
  • 老L:"哈哈,都是些看起來很幼稚、愚蠢的問題吧?是不是測試掛嘴邊的那句:' 你就不能跑一跑嗎,你又不瞎,跑兩下不就看到了,這么明顯!??!' "
  • 我突然來了興致,"你是說我們有必要上 TDD(test-driven-develop),按照DevOps思想,在CI(Continuous Integration)的時候,順帶跑自動化測試用例發(fā)現(xiàn)問題?"
  • 老L突然打斷了我:"不要拽你那些詞了,記住了,事情是要人干的,機(jī)器只能替代可重復(fù)勞動,現(xiàn)在還不能替代人的主觀能動性,拽詞并不能解決問題。我們已經(jīng)找到了第一個問題的答案,現(xiàn)在換個角度"

平日里最常見的bug有哪些?

  • 編碼不健壯, 例如NPE,IndexOutOfBoundsException
  • UI細(xì)節(jié)問題, 例如文本長度不一導(dǎo)致顯示不下,間距,等

為什么很淺顯的問題沒有被發(fā)現(xiàn)

老L:"那么問題來了,為什么這些淺顯的問題,在交測前沒有被發(fā)現(xiàn)呢?"

我陷入了思考...

是開發(fā)們都很懶嗎?也不至于啊!

是時間很緊來不及嗎?確實(shí)節(jié)奏緊張,但也不至于不給調(diào)試就拿去測了!

"emm, 可能是迭代的節(jié)奏的太頻繁,壓力較大,并沒有整塊的時間用來自測聯(lián)調(diào)"

老L接過話茬,"假定你說的是正確的,那么就有兩種可能。"

"第一種,自測與聯(lián)調(diào)要比開發(fā)還要耗費(fèi)心思的一件事情。但實(shí)際上,你我都知道,這一點(diǎn)并站不住腳!"

"而第二種,就是在開發(fā)階段無法及時測試,拖到開發(fā)完,簡單測測甚至被催促著就交差了"

仔細(xì)的思考后

  • 業(yè)務(wù)逐步展開,無法在任意時間自由地進(jìn)行有效的集成測試
  • 后端節(jié)奏并不比前端快多少,在前端的開發(fā)階段,難以借助后端接口測試,也許接口也有問題

"確實(shí),這是一個挺麻煩的問題,聽你一說,我感覺除了多給幾天,開發(fā)完集中自測一波才行" 我如是說到。

"NO NO NO",老L又打斷了我:"你想的過多了,你想借助一個可靠的、已經(jīng)完備的后端系統(tǒng)來進(jìn)行自測。對于你的需求來說,這個要求過高了,你這是準(zhǔn)備干QA的活"

"我?guī)湍懔信e一下情況"

  • 一些數(shù)據(jù)處理的算法,這種沒有辦法,老老實(shí)實(shí)寫單元測試,在開發(fā)階段就可以做好,保障可靠性
  • UI呢,我們現(xiàn)在寫的代碼,基本都做到了UI與邏輯分層,只要能模擬數(shù)據(jù),就能跑起來看頁面
  • 業(yè)務(wù)層,后端邏輯我們無法控制,但 Web-API 調(diào)用的情況可以分析下并做一下測試,而對于返回?cái)?shù)據(jù)的JSON結(jié)構(gòu)校驗(yàn)、約束性校驗(yàn)也可以考慮做一下測試

總而言之,我們只需要先排除掉淺顯的錯誤。而這些淺顯的錯誤,屬于情況2、3

老L接著說道:"你先歇歇吧,我來說,你再插嘴這文章就太長了!"

接下來就可以實(shí)現(xiàn)矛盾轉(zhuǎn)移:"如何模擬數(shù)據(jù)進(jìn)行測試",準(zhǔn)確的說,問題分成兩個子問題:

  • 如何生成模擬數(shù)據(jù)
  • 如何從接縫中塞入數(shù)據(jù),讓系統(tǒng)得以使用

可能存在的接縫

先看問題2:"如何從接縫中塞入數(shù)據(jù),讓系統(tǒng)得以使用"

腦暴一下,可以得出結(jié)論:

應(yīng)用內(nèi)部

  • 替換調(diào)用web-api的業(yè)務(wù)模塊,使用假數(shù)據(jù)調(diào)用業(yè)務(wù)鏈,一般替換Presenter、Controller實(shí)例
  • 替換Model層,不調(diào)用web-api,返回假數(shù)據(jù)或用假數(shù)據(jù)調(diào)用回調(diào)鏈
  • 侵入網(wǎng)絡(luò)層實(shí)現(xiàn),不進(jìn)行實(shí)際網(wǎng)絡(luò)層交互,直接使用假數(shù)據(jù)
  • 遵循切面,向緩存等機(jī)制模塊中植入假數(shù)據(jù)

應(yīng)用外部

  • 使用代理,返回假數(shù)據(jù)
  • 假數(shù)據(jù)服務(wù)器

簡單分析:

  • "假數(shù)據(jù)服務(wù)器" ,并且使用邏輯編造假數(shù)據(jù)的代價太大,過。
  • "使用代理,返回假數(shù)據(jù)",可以用于特定問題的調(diào)試,不適用廣泛情況,過。
  • "替換調(diào)用web-api的業(yè)務(wù)模塊",成本過大,過。
  • "替換Model層",對項(xiàng)目的依賴注入管理具有較大挑戰(zhàn),備選,可能帶來很多冗余代碼。
  • "侵入網(wǎng)絡(luò)層實(shí)現(xiàn)",優(yōu)選。
  • "向緩存等機(jī)制模塊中植入假數(shù)據(jù)",操作真實(shí)的緩存較復(fù)雜,但可以考慮增加一個 Mock緩存實(shí)現(xiàn)模塊,基于SPI等機(jī)制,可以解決冗余代碼問題,備選。

得出結(jié)論:

  • 方案1:"侵入網(wǎng)絡(luò)層實(shí)現(xiàn)",優(yōu)選
  • 方案2:"替換Model層",(項(xiàng)目的依賴注入做得很好時)作為備選,可能帶來冗余代碼
  • 方案3:"向緩存等機(jī)制模塊中植入假數(shù)據(jù)",增加一個 Mock緩存實(shí)現(xiàn)模塊,備選。(基于SPI等機(jī)制,可以解決冗余代碼問題)

再仔細(xì)分析: 方案1和方案3可以合并,形成一個完整的方案,但未必需要限定在緩存機(jī)制中

OK 我們先擱置一下這個問題,看前一個問題。

創(chuàng)造假數(shù)據(jù)

簡單腦暴一下,無非三種:

人工介入,手動編寫 -- 成本過大

  • 可能在前期準(zhǔn)備好,基本是純文本
  • 可能使用一個交互工具,在需要數(shù)據(jù)時介入,通過圖形化操作和輸入產(chǎn)生數(shù)據(jù)

人工介入,邏輯編碼

  • 基于反射等自省機(jī)制,并完全隨機(jī)或者基于限制生成數(shù)據(jù)

"第一種代價過大,暫且拋棄"

"第二種可以采用,但是人力成本不容忽視! 一個可以說服我使用它的理由是:"可以精心設(shè)計(jì)單測數(shù)據(jù),針對性的發(fā)現(xiàn)問題"

"第三種很輕松,例如使用Mockito,但生成合適的數(shù)據(jù)需要花費(fèi)一定的精力"

我們來扒一扒第三種方式,其核心思想為:

獲取類信息,得到屬性集

遍歷屬性填充 >

  • 基礎(chǔ)類型、箱體類型,枚舉,確定取值范圍,使用Random取值,賦值
  • 普通類、泛型類,創(chuàng)建實(shí)例,回歸步驟1
  • 集合、數(shù)組等,創(chuàng)建實(shí)例,回歸步驟1,收集填充

不難得出結(jié)論,這一方法雖然很強(qiáng)大,但 創(chuàng)建高度定制化的數(shù)據(jù) 是一件有挑戰(zhàn)的事情。

舉個例子,模擬字符串時,一般會使用語料集作為枚舉,進(jìn)行取值。要得到“地址”、“郵箱”等特定風(fēng)格的數(shù)據(jù),需要結(jié)合框架做配置,客觀上存在較高地學(xué)習(xí)、使用門檻。

你也知道,前幾年我圖好玩,寫了個 mock庫 。

必須強(qiáng)調(diào)的一點(diǎn):“我并不認(rèn)為我寫的庫比Mockito等庫強(qiáng)大,僅僅是在我們開發(fā)人員夠用的基礎(chǔ)上,做到盡可能簡單!”

所以,我能使用它便捷的生成合適的假數(shù)據(jù),在開發(fā)階段及時的進(jìn)行 “偽集成”

此刻,我再也忍不住要發(fā)言了:“且慢,老L,你這個做法有一定的侵入性吧。而且,如果數(shù)據(jù)類在不同業(yè)務(wù)下復(fù)用的話,是否存在問題呢?”

老L頓了頓,“確實(shí),google的annotations是源碼級注解,并不是運(yùn)行時,我為了保持簡單,使用了運(yùn)行時反射而非代碼生成。所以確實(shí)存在一定的代碼侵入性”。

但是,我們可以基于此建立一套簡單的MOCK-API,這樣就不存在代碼侵入了。

另外,也可以增加一套Annotation-Processor 實(shí)現(xiàn)方案,這樣就可以適當(dāng)沿用項(xiàng)目中的注解約束了,但我個人認(rèn)為華而不實(shí)。

看你的第二個問題,Mocker一開始確實(shí)存在這個問題,有一次從Spring的JSR380中得到靈感,我優(yōu)化了注解規(guī)則,這個問題已經(jīng)被解決了。得空你可以順著這個圖看看:

或者去看看代碼和使用說明:github.com/leobert-lan…

再次審視如何處理接縫

此時我已經(jīng)有點(diǎn)云里霧里,雖然聽起來很牛,如何用起來呢?我還是很茫然,簡直人麻了!不得不再次請教。

老L笑著說:“你問的是一個實(shí)踐方案的問題,而這類問題沒有銀彈.不同的項(xiàng)目、不同的習(xí)慣都有最適宜的方法,我只能分享一下我的想法和做法,僅做參考”

在之前的項(xiàng)目中,我自己建了一個Mock-API,利用我的Mocker庫,寫一個假數(shù)據(jù)接口就是分分鐘的事情。

測試機(jī)掛上charles代理,有需要的接口直接進(jìn)行mapping,所以在客戶端代碼中,你看不到我做了啥。

當(dāng)然,這個做法是在軟件外部。

如果要在軟件內(nèi)部做,我個人認(rèn)為這也是一個華而不實(shí)的事情。不過不得不承認(rèn)是一件好玩的事情,那就提一些思路。

基于Retrofit的CallAdapter

public interface CallAdapter<R, T> {
    Type responseType();
    T adapt(Call<R> call);
    abstract class Factory {
        public abstract @Nullable
        CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
                              Retrofit retrofit);
        protected static Type getParameterUpperBound(int index, 
                                                     ParameterizedType type) {
            return Utils.getParameterUpperBound(index, type);
        }
        protected static Class<?> getRawType(Type type) {
            return Utils.getRawType(type);
        }
    }
}

很明顯,我們可以追加注解,用以區(qū)分是否需要考慮mock;

可選:對于有可能需要mock的接口,可以繼續(xù)追加切面,實(shí)現(xiàn)在軟件外部控制使用 mock數(shù)據(jù) 或 真實(shí)數(shù)據(jù)

而Retrofit已經(jīng)使用反射確定了方法的 return Type ,在Mocker中也有適應(yīng)的API直接生成假數(shù)據(jù)

基于Retrofit的Interceptor

相比于上一種,攔截器已經(jīng)在Retrofit處理流程中靠后,此時在 Chain 中能夠得到的內(nèi)容已經(jīng)屬于Okhttp庫的范疇。

所以需要一定的前置措施用于確定 "return Type"、"是否需要Mock" 等信息??梢越柚鶷ag機(jī)制:

@Documented
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Tag {
}
@GET("/")
Call<ResponseBody> foo(@Tag String tag);

最終從 Request#tag(type: Class<out T>): T? 方式獲取,并接入mock,并生成 Response

其他針對Okhttp的封裝

思路基本類似,不再展開。

寫在最后

聽完老L的思路,我若有所思,若有所悟。他的方案似乎很有效,而且直覺告訴我,這些方案中還有很多留白空間,例如:

  • 借用SPI等技術(shù)思路,可以輕易的解決 "Mock 模塊集成與移除" 的問題
  • 提前外部控制是否Mock的接縫,可以在加一個工具APP、或者Socket+網(wǎng)頁端工具 用以實(shí)現(xiàn)控制

但我似乎遺漏了問題的開始

是否原意做 用于約束假數(shù)據(jù)生成規(guī)則的基礎(chǔ)建設(shè)工作呢??? 例如維護(hù)注解

事情終究是人干的,人原意做,辦法總比困難多。

以上就是java開發(fā)中代碼寫的快且bug少的原因分析的詳細(xì)內(nèi)容,更多關(guān)于java開發(fā)代碼快bug少的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot中@Transiactional注解沒有效果的解決

    SpringBoot中@Transiactional注解沒有效果的解決

    這篇文章主要介紹了SpringBoot中@Transiactional注解沒有效果的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 詳解java迭代器模式

    詳解java迭代器模式

    這篇文章主要介紹了java迭代器模式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Spring?Boot應(yīng)用打WAR包后無法注冊到Nacos的問題及解決方法

    Spring?Boot應(yīng)用打WAR包后無法注冊到Nacos的問題及解決方法

    當(dāng)我們將?Spring?Boot?應(yīng)用打包成?WAR?并部署到外部?Tomcat?服務(wù)器時,可能會遇到服務(wù)無法注冊到?Nacos?的情況,其原因主要是應(yīng)用獲取不到正確的服務(wù)器端口,下面給大家介紹Spring?Boot?應(yīng)用打?WAR?包后無法注冊到?Nacos的問題及解決方法,感興趣的朋友跟隨小編一起看看吧
    2024-06-06
  • Java+Eclipse+Selenium環(huán)境搭建的方法步驟

    Java+Eclipse+Selenium環(huán)境搭建的方法步驟

    這篇文章主要介紹了Java+Eclipse+Selenium環(huán)境搭建的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-06-06
  • Java中string和int的互相轉(zhuǎn)換問題

    Java中string和int的互相轉(zhuǎn)換問題

    本文通過實(shí)例代碼給大家詳細(xì)介紹了Java中string和int的互相轉(zhuǎn)換問題,感興趣的朋友一起看看吧
    2017-10-10
  • Eclipse Debug模式的開啟與關(guān)閉問題簡析

    Eclipse Debug模式的開啟與關(guān)閉問題簡析

    這篇文章主要介紹了Eclipse Debug模式的開啟與關(guān)閉問題簡析,同時向大家介紹了一個簡單的debug模式啟動不起來的解決方法,希望對大家有所幫助。
    2017-10-10
  • 通過volatile驗(yàn)證線程之間的可見性

    通過volatile驗(yàn)證線程之間的可見性

    這篇文章主要介紹了通過volatile驗(yàn)證線程之間的可見性,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • Java中Calendar類用法實(shí)例詳解

    Java中Calendar類用法實(shí)例詳解

    這篇文章主要給大家介紹了關(guān)于Java中Calendar類用法的相關(guān)資料,Calendar類是Java.util包中提供的一個抽象類,該類從JDK1.1開始出現(xiàn),作為Date類的替代方案,Calendar類中包含了對不同國家地區(qū)日歷的處理,需要的朋友可以參考下
    2023-09-09
  • Java并發(fā)之Phaser的全面解析詳解

    Java并發(fā)之Phaser的全面解析詳解

    Phaser是Java中一個靈活的同步工具,其優(yōu)點(diǎn)在于支持多階段的任務(wù)拆分與同步,并且能夠動態(tài)地注冊與注銷參與者,下面我們就來深入了解一下Phaser的應(yīng)用吧
    2024-02-02
  • Java線程池execute()方法源碼全面解析

    Java線程池execute()方法源碼全面解析

    這篇文章主要介紹了Java線程池execute()方法源碼全面解析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論