2012-04-30 125 views
0

由於性能差(高複雜度),我在一個大型java項目(移動應用程序)上工作,並得到了「感謝」的工作來審查和優化/重構代碼。 注:我對Java完全陌生(我的背景是C/C++),因此我爲任何愚蠢的問題applogize。 我做的第一件事就是使用Findbugs並修復所有報告的問題。之後,我使用了公制工具Understand來獲得概述,其中方法具有較高的圈複雜度。不幸的是,有很多方法的複雜度在2^20範圍以內: - ( 其中之一是我需要一些幫助或好點子...減少Cyclometic複雜性的方法

簡短說明: 對於與因此,編寫所有代碼的同事(單獨)實現了一個Serializable接口,其中包含一個名爲toByteArray()的方法。 例如,class Customerclass Customer

class Customer 
{ 
    Address address; 
    AttributeCollection attributes; 
    LocationCollection locations; 
    int recId; 
    int recStatus; 
    DateTime recCreated; 
    String recCreatedBy; 
    String recCreatedByProg; 
    DateTime recChanged; 
    String recChangedBy; 
    String recChangedByProg; 
    int refAddressesId; 
    int refMandatorsId; 
    CustomerPropertyUsage usage; 

    /** 
    * Serialize the properties of a class into a byte array. 
    * @param destData Byte array, where the serialized data should be stored. Minimum 2 bytes. 
    * @param serializationIndex Offset within the passed byte array, from which the serialized data of the class 
    * should be entered. The offset is increased by the registered number of bytes so that after this method the 
    * next call points to the serialized data subsequent byte. 
    */ 
    void toByteArray(byte[] destData, IntClass serializationIndex) 
    { 
     if (this.address == null) 
      this.usage.value &= ~CustomerPropertyUsage.ADDRESS; 
     if (this.attributes == null) 
      this.usage.value &= ~CustomerPropertyUsage.ATTRIBUTES; 
     if (this.locations == null) 
      this.usage.value &= ~CustomerPropertyUsage.LOCATIONS; 

     this.usage.toByteArray(destData, serializationIndex); 

     CatrString catrString = null; 

     if ((this.usage.value & CustomerPropertyUsage.RECORD_HEADER) != CustomerPropertyUsage.NONE) 
     { 
      // Call static method getBytes from SerializationHelper class 
      SerializationHelper.getBytes(this.recId, 4, destData, serializationIndex.value); 
      serializationIndex.value += 4; 

      SerializationHelper.getBytes(this.recStatus, 4, destData, serializationIndex.value); 
      serializationIndex.value += 4; 

      // recChanged is a DateTime object. For the serialization we need minimum a 7 bytes array, 
      // Call method toByteArray() from DateTime class. 
      this.recChanged.toByteArray(destData, serializationIndex); 

      // call toByteArray of CatrString class 
      catrString = new CatrString(this.recChangedBy); 
      catrString.toByteArray(destData, serializationIndex); 

      catrString.setValue(this.recChangedByProg); 
      catrString.toByteArray(destData, serializationIndex); 

      // Same as recChanged 
      this.recCreated.toByteArray(destData, serializationIndex); 

      catrString = new CatrString(this.recCreatedBy); 
      catrString.toByteArray(destData, serializationIndex); 

      catrString.setValue(this.recCreatedByProg); 
      catrString.toByteArray(destData, serializationIndex); 

      SerializationHelper.getBytes(this.refAddressesId, 4, destData, serializationIndex.value); 
      serializationIndex.value += 4; 

      SerializationHelper.getBytes(this.refMandatorsId, 4, destData, serializationIndex.value); 
      serializationIndex.value += 4; 
     } 

     if (next property...) 
     { 
      ... Serialization ... 
     } 

     if (next property...) 
     { 
      ... Serialization ... 
     } 
    } 
} 

爲了保持GPRS會費低,t他的服務器在this.usage.value中設置了一個值,因此只有一個特定的屬性會被序列化並傳回服務器 - > 傳輸的消息很小。 這種方法會創建大量if-cases,具體取決於類中的屬性數量,因此路徑數量越來越高。 我認爲這不是一個美麗的解決方案,但它沒關係。我想要改變的是if內的序列化調用。 目前,他們是這樣的:

---- class SerializationHelper ---- 

    static void getBytes(long valueToConvert, int numOfBytesToConvert, byte[] destinationBytes, int destinationBytesOffset) 
    { 
     destinationBytes[destinationBytesOffset] = (byte)(valueToConvert & 0x000000FF); 
     destinationBytes[destinationBytesOffset + 1] = (byte)((valueToConvert & 0x0000FF00) >> 8); 

     if (numOfBytesToConvert > 2) 
     { 
      destinationBytes[destinationBytesOffset + 2] = (byte)((valueToConvert & 0x00FF0000) >> 16); 
      destinationBytes[destinationBytesOffset + 3] = (byte)((valueToConvert & 0xFF000000) >> 24); 

      if (numOfBytesToConvert > 4) 
      { 
       destinationBytes[destinationBytesOffset + 4] = (byte)((valueToConvert & 0x000000FF00000000L) >> 32); 
       destinationBytes[destinationBytesOffset + 5] = (byte)((valueToConvert & 0x0000FF0000000000L) >> 40); 
       destinationBytes[destinationBytesOffset + 6] = (byte)((valueToConvert & 0x00FF000000000000L) >> 48); 
       destinationBytes[destinationBytesOffset + 7] = (byte)((valueToConvert & 0xFF00000000000000L) >> 56); 
      } 
     } 
    } 

---- class CatrString ---- 

    void toByteArray(byte[] destData, IntClass serializationIndex) 
    { 
     // Number of unicode characters 
     SerializationHelper.getBytes(this.textLength, 2, destData, serializationIndex.value); 
     serializationIndex.value += 2; 

     // Text UTF-16 unicode characters 
     for (int charIndex = 0; charIndex < this.textLength; charIndex++) 
     { 
      destData[serializationIndex.value] = (byte)(this.charCodes[charIndex] & 0x00FF); 
      serializationIndex.value++; 
      destData[serializationIndex.value] = (byte)((this.charCodes[charIndex] & 0xFF00) >> 8); 
      serializationIndex.value++; 
     } 

     // Code End of string as UTF-16 unicode character 
     destData[serializationIndex.value] = 0x00; 
     serializationIndex.value++; 
     destData[serializationIndex.value] = 0x00; 
     serializationIndex.value++; 
    } 

---- class DateTime ---- 

    void toByteArray(byte[] destData, IntClass serializationIndex) 
    { 
     destData[serializationIndex.value + 0] = (byte) (m_year % 0x0100); // year low-Byte. 
     destData[serializationIndex.value + 1] = (byte) (m_year/0x0100); // year high-Byte. 
     destData[serializationIndex.value + 2] = (byte) (m_month); 
     destData[serializationIndex.value + 3] = (byte) m_day; 

     destData[serializationIndex.value + 4] = (byte) m_hour; 
     destData[serializationIndex.value + 5] = (byte) m_minute; 
     destData[serializationIndex.value + 6] = (byte) m_second; 

     serializationIndex.value += 7; 
    } 

應該可以寫一個更「一般」類,做所有的東西,系列化,在這裏我說的序列化XY 字節,就是這樣。但我不明白的是什麼「特殊」toByteArray()方法像字符串(UTF-16編碼) 或日期和時間?如果我將它們包裝在課堂上,那是一個很好的解決方案嗎?我有什麼收穫嗎? Maintable代碼?高性能代碼? 你會怎麼做?

Thx

回答

1

也許最好爲每個類創建一個屬性的Map。默認情況下,該集合是空的,但在通話時setAddress(address)我們調用fieldsMap.put(ADDRESS_KEY_STRING,address)而不是分配給類的字段。

要存儲所有存取(現有)屬性,我們只需通過存儲每個條目的fieldsMap。