12月日常開發小結

一、異常資訊

之前做了一個異常通知的需求,簡單來說就是程式執行異常了發送一封郵件和通知給指定的人員,我的做法也很簡單,在利用異常捕獲在catch中將捕獲到的異常發送.

上線之後有同事說異常了沒有發,我也不知道是不是真的異常了沒發,因為之前自己測了好多遍通過了的,抱著將信將疑的態度去結合日誌分析程式碼,後面發現確實是這樣.

程式碼如下:

public Task Execute()
{
    try
    {
        CalculationRawData();
    }
    catch (Exception ex)
    {
               PushException?.Invoke(this, new ExceptionResponse(Company, nameof(CalculationJob),ex));
    }
        return Task.FromResult(0);
}
            
 public void CalculationRawData()
 {
     try
     {
         //dosomthing
     }
     catch (Exception ex)
     {
         Logger.Writelog("ex.InnerException.Message");
     }
 }

為什麼沒有被發送?

根據上面2段程式碼分析出,在CalculationRawData方法中雖然捕獲了異常但是並沒有拋出,所以導致Execute沒有接收到異常,自然也不會調用發送介面.
所以日常開發中對異常的處理只用一個統一的入口,在業務中盡量不要對異常進行處理,因為處理不好會導致真正有用的問題資訊被吞了,增加排查成本.

二、implicit 和 explicit

講道理工作這些年,這2個關鍵字基本沒用過,應該不止我一個人吧!!

implicit 關鍵字用於聲明隱式的用戶自定義的類型轉換運算符。 如果可以確保轉換過程不會造成數據丟失,則可使用該關鍵字在用戶定義類型和其他類型之間進行隱式轉換。

explicit 關鍵字聲明必須通過顯示的調用用戶定義的類型轉換運算符來進行轉換。

1.implicit
 //自定義轉換類
 public struct TimeRange
 {
     public DateTime StartTime { get; set; }
     public DateTime EndTime { get; set; }
     public TimeRange(DateTime startTime, DateTime endTime)
     {
         StartTime = startTime;
         EndTime = endTime;
     }

     public static implicit operator double(TimeRange timeRange)
     {
         return (timeRange.EndTime - timeRange.StartTime).TotalHours; ;
     }
 }
static void Main(string[] args)
{
    DateTime star = DateTime.Now;
    DateTime end = DateTime.Now.AddDays(1);
    //根據起始日期和結束日期算出間隔時間,默認隱式轉換
    double result =  new TimeRange(star, end);
}
2.explicit
static void Main(string[] args)
{
    DateTime star = DateTime.Now;
    DateTime end = DateTime.Now.AddDays(1);
   //根據起始日期和結束日期算出間隔時間,必須顯示聲明轉換
    double result =  (double)new TimeRange(star, end);
}

三、快速轉換

1.快速將Int數組轉換為String數組
int [] arr = new int[] { 4,2, 4,6 };

string[] result = Array.ConvertAll(arr, Convert.ToString);
2.快速將List<string>轉換為List<int>
 List<string> list = new List<string>() { "1","2","3","1"};
 var result = list.ConvertAll(int.Parse);

四、這可能是真的

其實並不代表是這一個月的小結,有一部分其實也有挺長一段時間了,所以記錄一下。

1.為什麼會產生Bug

就我自己根據這些年的開發經驗和親身經歷和做過的項目,如果一旦程式出問題,無論是從承擔責任或者解決問題的角度來說,從設計>開發>測試>運維>實施>直到用戶,第一個祭天的永遠是開發人員,確實因為東西是你做的,設計人員會說已經跟你講清楚了,運維和測試人員會說誰知道你寫的什麼東西,Bug測都測不出來,最後連實施都會和用戶一起鄙視你” 這tm什麼垃圾軟體”。

首先我得闡明我的態度,這不是針對誰,因為每個人都很不容易,並且很努力,有些觀點可能不太容易被認可或者接受,但是確實是這麼回事,因為這個東西是見人見智的,胡說胡有理,如果有人真的很在意,可以當做一個吐槽來看.
現實雖然就是這麼無奈,但是我們必須去面對,因為只有剖析出問題所在,才能更清晰的看到本質,以至於得到實實在在的提高,在此作為一個開發總結了一下,產生Bug主要有以下幾大原因:

1. 模糊的需求

有時候有一個需求來了,並沒有仔細的去閱讀需求,也沒有仔細去和提出需求的人進行需求交底和反向交底,因為在普遍開發的認知里,寫需求的人都是不懂需求的人,加上在無數次的”這是哪個xx提的需求?”,”為什麼要這樣啊?”,”真tm xx”

經過了長時間歲月的打磨,導致大部分在閱讀需求時只是囫圇吞棗式的快速掃描一眼, 掃描過程中只摘取一些敏感字眼,然後全憑自己想當然,久而久之養成了一種先入為主的習慣,然後做出來的需求就是……額 ,不敢想像.

如何解決?

一定要仔細客觀的閱讀並核對用戶提出的需求,然後獨立分析進行反向交底,哪怕是一張很抽象的圖,或者幾行字都行,因為你說的話有可能在當時只是你自己認為自己講清楚了,恰恰並不是每個人都能明白你的意思,又或是你壓根就沒說清楚,就算多耗點時間也沒關係,磨刀不誤砍柴工,如果可能拉上測試,至於為什麼,那就是避免你後續做完之後,再講第二次,第三次,懂的都懂.

2. 超乎尋常的自信

我覺得作為開發自我認可的標準並開發不是寫程式碼多6,解Bug做需求多快,而是迷之自信,最騷的是不接受反駁,寫完就提測,不說單元測試,連基本的過一遍都沒有,恰恰這樣卻帶來了不少壞處,理想的情況就是在測試階段問題被發現了,然後一堆Bug,不太理想的情況就是測試也沒測出來,然後被用戶測出來了…

如何解決?

1.在寫完之後,自己先整體CodeReview一遍,通常可以發現一些寫法和設計缺陷並及時修改,然後最少測試3遍,測試3遍,測試3遍.

2.對於大的功能模組,寫出開發版本的測試用例,寫了你才能更好的進行單元測試.

3. 鍛煉自己的編碼內功

對API不熟悉,掌握程度不夠導致出現的比比皆是,所以在用任何一個自己感覺不熟悉的api時,一定要查清楚他的方法,例如獲取字典集合中取一個不存在的key “a1″對應的值,不熟悉的人經常寫出直接取keyValuePairs[“a1”]那就直接錯了,正確使用keyValuePairs.TryGetValue(“a1”,out int c),像這樣的細節還有很多,不一一列舉,只是想表達這個意思

 Dictionary<string, int> keyValuePairs = new Dictionary<string, int>();
 keyValuePairs.Add("a", 2);
 keyValuePairs.Add("b", 3);

4. 不及時復盤

為什麼說要及時復盤?可以將日常開發的一些小技巧,或者解決過的典型Bug和解決辦法,例如常見的

1.未將對象引用到實例.
2.參數長度超出資料庫可存儲的範圍.
3.索引越界.
4.某個特殊的業務導致需要特殊處理.

都記下來,然後定期或者不定期的拿出來複盤一下,或者在新需求做完之後,把記錄拿出來作為標準檢查一下,保證之前犯過的錯,和解決過的問題不會再出現。

5. 不要帶著情緒做事情

這個自行腦補吧,因為每個人都有自己的個性和脾氣,你可以不認可所有人,也可以認為所有人都是垃圾,但是在工作中不要表現出來帶著情緒做事,這樣會對你周圍,或者對你自己有很大影響,謹記”要麼忍,要麼滾”!

6. 測試不靠譜

為什麼說測試不靠譜,不是特意為鄙視或者挑起衝突而說的,也只是客觀的,因為在絕大部分的小公司中的測試都是針對業務線的,加上水平也層次不齊,遇到一個經驗相對豐富,會寫Sql或者對絕大部分測試工具或者性能測試熟悉的你就偷著樂吧,因為我遇到的有一部分連用例都不寫,我不知道是不會寫,還是說嫌太麻煩了,上來一通亂點,以至於連自己點到哪裡了都不清楚。

假如無法改變,又必須解決呢?

1.提高程式碼健壯性,減少bug把問題風險降到最小.

2.換個環境可能會好一點,但也有可能更糟糕…

Tags: