Java 降低拟环复杂度的方法
我在一个大型java项目(移动应用程序)上工作,由于性能差(高复杂性),我得到了审查和优化/重构代码的“谢天谢地”工作。 注意:我对Java完全是新手(我的背景是C/C++),因此我会申请任何愚蠢的问题。 我做的第一件事是使用Findbugs并修复所有报告的问题。之后,我使用metric工具Understand获得了一个概述 方法具有很高的圈复杂度。不幸的是,有许多方法的拟环复杂度高于2^20范围:-( 其中之一就是我需要一些帮助或好主意 简要说明: 对于与服务器的通信,必须序列化数据。此移动框架上没有可序列化的接口。 因此,编写所有代码的同事(单独)实现了一个可序列化接口,其中包含一个名为Java 降低拟环复杂度的方法,java,cyclomatic-complexity,Java,Cyclomatic Complexity,我在一个大型java项目(移动应用程序)上工作,由于性能差(高复杂性),我得到了审查和优化/重构代码的“谢天谢地”工作。 注意:我对Java完全是新手(我的背景是C/C++),因此我会申请任何愚蠢的问题。 我做的第一件事是使用Findbugs并修复所有报告的问题。之后,我使用metric工具Understand获得了一个概述 方法具有很高的圈复杂度。不幸的是,有许多方法的拟环复杂度高于2^20范围:-( 其中之一就是我需要一些帮助或好主意 简要说明: 对于与服务器的通信,必须序列化数据。此移动框
toByteArray()
的方法。
例如,类客户
:
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费用,服务器在this.usage.value中设置一个值,因此只有特定的属性将被序列化并传输回服务器-->
传输的信息很小。
这种方法会根据类中的属性数量创建很多if情况,因此路径计数会越来越高。
我认为这不是一个很好的解决方案,但没关系。我想改变的是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;
}
---class SerializationHelper----
静态void getBytes(long valueToConvert,int numobytestoconvert,byte[]destinationBytes,int destinationbytescoffset)
{
destinationBytes[destinationBytesOffset]=(字节)(值转换&0x000000FF);
destinationBytes[destinationBytesOffset+1]=(字节)((valueToConvert&0x0000FF00)>>8);
如果(numobytestoconvert>2)
{
destinationBytes[destinationBytesOffset+2]=(字节)((值转换&0x00FF0000)>>16);
destinationBytes[destinationBytesOffset+3]=(字节)((valueToConvert&0xFF000000)>>24);
如果(numobytestoconvert>4)
{
destinationBytes[destinationBytesOffset+4]=(字节)((转换值&0x000000FF00000000L)>>32);
destinationBytes[destinationBytesOffset+5]=(字节)((转换值&0x0000FF0000000000L)>>40);
destinationBytes[destinationBytesOffset+6]=(字节)((转换值&0x00FF000000000000L)>>48);
destinationBytes[destinationBytesOffset+7]=(字节)((转换值&0xFF00000000000000L)>>56);
}
}
}
----类CatrString----
无效toByteArray(字节[]destData,IntClass序列化索引)
{
//unicode字符数
SerializationHelper.getBytes(this.textLength,2,destData,serializationIndex.value);
serializationIndex.value+=2;
//文本UTF-16 unicode字符
for(int charIndex=0;charIndex>8);
serializationIndex.value++;
}
//将字符串结尾编码为UTF-16 unicode字符
destData[serializationIndex.value]=0x00;
serializationIndex.value++;
destData[serializationIndex.value]=0x00;
serializationIndex.value++;
}
----类日期时间----
无效toByteArray(字节[]destData,IntClass序列化索引)
{
destData[serializationIndex.value+0]=(字节)(m_year%0x0100);//年份低位字节。
destData[serializationIndex.value+1]=(字节)(m_year/0x0100);//年高位字节。
destData[serializationIndex.value+2]=(字节)(m_月);
destData[serializationIndex.value+3]=(字节)m_天;
destData[serializationIndex.value+4]=(字节)m_小时;
destData[serializationIndex.value+5]=(字节)m_分钟;
destData[serializationIndex.value+6]=(字节)毫秒;
serializationIndex.value+=7;
}
应该可以编写一个更“通用”的类来完成所有的序列化工作,我说的是SerializeXY
但我不明白的是,像字符串(UTF-16编码)这样的“特殊”toByteArray()
或者日期和时间?如果我将它们打包到一个类中,这是一个好的解决方案吗?我从中获得了什么吗?可维护代码?高性能代码??
你的方法是什么
Thx可能是最好为每个类创建属性映射。默认情况下,该集合为空,但在调用时,例如setAddress(地址),我们称为fieldsMap.put(地址\键\字符串,地址),而不是分配给类的字段
要存储所有Acess(现有)属性,我们只需通过存储每个条目的fieldsMap