2012-04-30 3 views
0

성능이 좋지 않아 (복잡성이 높음) 큰 자바 프로젝트 (모바일 애플리케이션)에서 작업하고 코드를 검토하고 최적화/리팩토링하는 "감사"작업을 얻었습니다. 참고 : 저는 Java에 완전히 익숙합니다 (제 배경은 C/C++입니다). 그러므로 나는 바보 같은 질문에 대해 사과합니다. 내가 한 첫 번째 일은 Findbugs를 사용하여보고 된 모든 문제를 해결하는 것이 었습니다. 그 다음에는 메트릭 도구 인 Understanding을 사용하여 순환 정확도가 높은 메소드의 개요를 가져 왔습니다. 불행히도 2^20 범위 이상으로 순환 복잡도를 가진 많은 메소드가있었습니다 :-( 그리고 그 중 하나는 제가 도움이나 좋은 아이디어가 필요한 곳입니다 ...순환 복잡도를 줄이기위한 접근법

간단한 설명 : 따라서 모든 코드를 작성한 동료 (단독)는 toByteArray()이라는 메서드 하나를 포함하는 Serializable 인터페이스를 구현했습니다. : 예를 들어,이 모바일 프레임 워크에서 사용할 수있는 직렬화 가능한 인터페이스가 없습니다.

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-case를 생성하므로 경로 수가 더 높아지고 높습니다. 그게 멋진 솔루션은 아니지만 괜찮아요. 내가 바꾸고 싶은 것은 if-case 내부의 직렬화 호출이다.

---- 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 code? 고성능 코드 ?? 당신의 접근 방법은 무엇입니까?

Thx

답변

1

각 클래스에 대한 속성 맵을 만드는 것이 더 좋을 수도 있습니다. 기본적으로 세트는 비어 있지만 통화 중입니다. setAddress (address) 클래스의 필드에 할당하는 대신 fieldsMap.put (ADDRESS_KEY_STRING, address)을 호출합니다.

모든 acesses (기존) 속성을 저장하려면 각 항목을 저장하는 fieldsMap을 선택하면됩니다.