(사용자 정의 형식) 텍스트 파일로 Java 내보내기 데이터
-
13-11-2019 - |
문제
나는 일부 고객 데이터(전자상거래 DB에서)를 사용자 정의 형식 텍스트 파일로 내보내는 이 백엔드 예약 작업을 수행하라는 요청을 받았습니다.다음 코드는 내가 찾은 것입니다.
그냥 다 삭제하고 싶은데 그럴 수가 없어요.크게 바꾸지 않고도 이 부분을 개선할 수 있을까요?
public class AConverter implements CustomerConverter {
protected final Logger LOG = LoggerFactory.getLogger(AConverter.class);
private final static String SEPARATOR = ";";
private final static String CR = "\n";
public String create(Customer customer) {
if (customer == null)
return null;
LOG.info("Exporting customer, uidpk: {}, userid: {}", customer.getUidPk(), customer.getUserId());
StringBuilder buf = new StringBuilder();
buf.append("<HEAD>");
buf.append(SEPARATOR);
buf.append(String.valueOf(customer.getUidPk()));
buf.append(SEPARATOR);
byte[] fullName = null;
try {
fullName = customer.getFullName().getBytes("UTF-8");
} catch (UnsupportedEncodingException e1) {
fullName = customer.getFullName().getBytes();
}
String name = null;
try {
name = new String(fullName, "UTF-8");
} catch (UnsupportedEncodingException e) {
name = customer.getFullName();
}
buf.append(limitString(name, 40));
buf.append(SEPARATOR);
final CustomerAddress preferredShippingAddress = customer.getPreferredShippingAddress();
if (preferredShippingAddress != null) {
final String street1 = preferredShippingAddress.getStreet1();
if (street1 != null) {
buf.append(limitString(street1, 40));
}
} else {
buf.append(" ");
}
buf.append(SEPARATOR);
final String addressStr = buildAddressString(customer);
buf.append(limitString(addressStr, 40));
buf.append(SEPARATOR);
buf.append(limitString(customer.getEmail(), 80));
buf.append(SEPARATOR);
if (preferredShippingAddress!=null && preferredShippingAddress.getStreet2() != null) {
buf.append(limitString(preferredShippingAddress.getStreet2(), 40));
} else {
buf.append(" ");
}
buf.append(SEPARATOR);
buf.append(limitString(customer.getPhoneNumber(), 25));
buf.append(SEPARATOR);
if (preferredShippingAddress!=null) {
if(preferredShippingAddress.getCountry()!=null) {
buf.append(preferredShippingAddress.getCountry());
} else {
buf.append(" ");
}
} else {
buf.append(" ");
}
buf.append(SEPARATOR);
if (preferredShippingAddress!=null) {
if(preferredShippingAddress.getCountry()!=null) {
buf.append(preferredShippingAddress.getCountry());
} else {
buf.append(" ");
}
} else {
buf.append(" ");
}
buf.append(SEPARATOR);
String fodselsnummer = " ";
try {
Map<String, AttributeValue> profileValueMap = customer.getProfileValueMap();
AttributeValue attributeValue = profileValueMap.get("CODE");
fodselsnummer = attributeValue.getStringValue();
} catch (Exception e) {
}
buf.append(fodselsnummer);
buf.append(CR);
final String string = buf.toString();
return string;
}
private String buildAddressString(Customer customer) {
final CustomerAddress preferredShippingAddress = customer.getPreferredShippingAddress();
if (preferredShippingAddress != null) {
final String zipOrPostalCode = preferredShippingAddress.getZipOrPostalCode();
final String city = preferredShippingAddress.getCity();
if (zipOrPostalCode != null && city != null) {
return zipOrPostalCode + " " + city;
} else if(zipOrPostalCode == null && city != null) {
return city;
} else if(zipOrPostalCode != null && city == null) {
return zipOrPostalCode;
}
}
return " ";
}
private String limitString(String value, int numOfChars) {
if (value != null && value.length() > numOfChars)
return value.substring(0, numOfChars);
else
return value;
}
}
해결책
개선하고 싶다고, 삭제하고 싶은데 그럴 수가 없잖아요.왜 할 수 없는지 잘 모르겠습니다.삭제하려는 이유도 이해가 되지 않습니다.하지만 내 생각엔 내가 책을 읽기 전에 가졌던 태도와 비슷한 것 같아 리팩토링 마틴 파울러 지음.아직 읽지 않았다면 그 책을 읽어보실 것을 강력히 권합니다.
이 코드(또는 모든 코드)를 모두 다시 작성하지 않고도 개선하는 것은 확실히 가능합니다.가장 확실한 개선점은 다음과 같은 반복적인 코드 중 일부를 제거하는 것입니다. create
몇 가지 유틸리티 메소드를 생성한 후 create
메소드를 여러 개의 작은 메소드(템플릿 메소드)로 나눕니다.
또한, create
고객의 이름을 UTF-8 바이트 스트림으로 변환한 다음 다시 문자열로 변환하는 메서드입니다.그게 무엇을 위한 것인지 상상할 수 없습니다.마지막으로 고객이 null인 경우 null을 반환합니다.그것은 필요하지도 현명하지도 않을 것입니다.
재미삼아 이 코드에 대해 약간의 리팩토링을 수행하기로 결정했습니다.(적절한 리팩토링에는 단위 테스트가 포함됩니다.이 코드에 대한 테스트는 없으며 아래 코드를 컴파일하지도 않았고 테스트도 하지 않았습니다.) 다음은 이 코드를 다시 작성할 수 있는 한 가지 방법입니다.
public class AConverter implements CustomerConverter {
protected final Logger LOG = LoggerFactory.getLogger(AConverter.class);
private final static String SEPARATOR = ";";
private final static String CR = "\n";
public String create(Customer customer) {
if (customer == null) throw new IllegalArgumentException("no cust");
LOG.info("Exporting customer, uidpk: {}, userid: {}",
customer.getUidPk(), customer.getUserId());
StringBuilder buf = new StringBuilder();
doHead(buf, customer);
doAddress(buf, customer);
doTail(buf, customer);
return buf.toString();
}
private void doHead(StringBuilder buf, Customer customer) {
append(buf, "<HEAD>");
append(buf, String.valueOf(customer.getUidPk()));
append(buf, limitTo(40, customer.getFullName()));
}
private void doAddress(StringBuilder buf, Customer customer) {
append(buf, limitTo(40, street1of(customer)));
append(buf, limitTo(40, addressOf(customer)));
append(buf, limitTo(80, customer.getEmail()));
append(buf, limitTo(40, street2of(customer)));
append(buf, limitTo(25, customer.getPhoneNumber()));
append(buf, countryOf(customer));
append(buf, countryOf(customer));
}
private void doTail(StringBuilder buf, Customer customer) {
buf.append(fodselsnummerOf(customer));
buf.append(CR);
}
private void append(StringBuilder buf, String s) {
buf.append(s).append(SEPARATOR);
}
private String street1of(Customer customer) {
final CustomerAddress shipto = customer.getPreferredShippingAddress();
if (shipto == null) return " ";
if (shipto.getStreet1() != null) return shipto.getStreet1();
return " ";
}
private String street2of(Customer customer) {
final CustomerAddress shipto = customer.getPreferredShippingAddress();
if (shipto == null) return " ";
if (shipto.getStreet2() != null) return shipto.getStreet2();
return " ";
}
private String addressOf(Customer customer) {
final CustomerAddress shipto = customer.getPreferredShippingAddress();
if (shipto == null) return " ";
final String post = preferredShippingAddress.getZipOrPostalCode();
final String city = preferredShippingAddress.getCity();
if (post != null && city != null) return post + " " + city;
if (post == null && city != null) return city;
if (post != null && city == null) return post;
return " ";
}
private String countryOf(Customer customer) {
final CustomerAddress shipto = customer.getPreferredShippingAddress();
if (shipto == null) return " ";
if (shipto.getCountry() != null) return shipto.getCountry();
return " ";
}
private String limitTo(int numOfChars, String value) {
if (value != null && value.length() > numOfChars)
return value.substring(0, numOfChars);
return value;
}
private String fodelsnummerOf(Customer customer) {
try {
Map<String, AttributeValue> profileValueMap =
customer.getProfileValueMap();
AttributeValue attributeValue = profileValueMap.get("CODE");
return attributeValue.getStringValue();
} catch (Exception e) {
return " ";
}
}
}
또한 고객 데이터(예: 이메일 주소) 필드에 세미콜론이 있는 경우 사용자 정의 형식 텍스트 파일의 형식에 문제가 있다는 것을 알았습니다. 세미콜론이 구분 문자이기 때문입니다.나는 그것이 알려진 문제라고 믿습니다.