CleanCode TIL (2022.02.20)

Henry ChoΒ·2022λ…„ 2μ›” 20일
0

λ…Έκ°œλΆ

λͺ©λ‘ 보기
26/31

DAY 28

πŸ”–Β μ˜€λŠ˜ 읽은 λ²”μœ„ : 14. 점진적인 κ°œμ„ (246~270p)


πŸ€“Β μ±…μ—μ„œ κΈ°μ–΅ν•˜κ³  싢은 λ‚΄μš©

λͺ…λ Ήν–‰ 인수 ꡬ문뢄석기 사둀 연ꡬ

public static void main(String[] args) {
    try {
        Args arg = new Args("l,p#,d*", args);
        boolean logging = arg.getBoolean('l');
        int port = arg.getInt('p');
        String directory = arg.getString('d');
        executeApplication(logging, port, directory);
    } catch (ArgsException e) {
        System.out.printf("Argument error: %s\n", e.errorMessage());
    }
}
  • Args μƒμ„±μžμ— 인수 λ¬Έμžμ—΄κ³Ό ν˜•μ‹ λ¬Έμžμ—΄μ„ λ„˜κ²¨ Args μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•œ ν›„ Args μΈμŠ€ν„΄μŠ€μ— 인수 값을 질의

Args κ΅¬ν˜„

μ–΄λ–»κ²Œ μ§°λŠλƒκ³ ?

  • ν”„λ‘œκ·Έλž˜λ°μ€ 과학보닀 κ³΅μ˜ˆμ— 가깝닀 β†’ μ΄ˆμ•ˆλΆ€ν„° μž‘μ„±ν•˜κ³  μ •λ¦¬ν•˜μž
import java.text.ParseException;
import java.util.*;
public class Args {
    private String schema;
    private String[] args;
    private boolean valid = true;
    private Set < Character > unexpectedArguments = new TreeSet < Character > ();
    private Map < Character, Boolean > booleanArgs =
        new HashMap < Character, Boolean > ();
    private Map < Character, String > stringArgs = new HashMap < Character, String > ();
    private Map < Character, Integer > intArgs = new HashMap < Character, Integer > ();
    private Set < Character > argsFound = new HashSet < Character > ();
    private int currentArgument;
    private char errorArgumentId = '\0';
    private String errorParameter = "TILT";
    private ErrorCode errorCode = ErrorCode.OK;
    private enum ErrorCode {
        OK,
        MISSING_STRING,
        MISSING_INTEGER,
        INVALID_INTEGER,
        UNEXPECTED_ARGUMENT
    }
    public Args(String schema, String[] args) throws ParseException {
        this.schema = schema;
        this.args = args;
        valid = parse();
    }
    private boolean parse() throws ParseException {
        if (schema.length() == 0 && args.length == 0)
            return true;
        parseSchema();
        try {
            parseArguments();
        } catch (ArgsException e) {}
        return valid;
    }
    private boolean parseSchema() throws ParseException {
        for (String element: schema.split(",")) {
            if (element.length() > 0) {
                String trimmedElement = element.trim();
                parseSchemaElement(trimmedElement);
            }
        }
        return true;
    }
    private void parseSchemaElement(String element) throws ParseException {
        char elementId = element.charAt(0);
        String elementTail = element.substring(1);
        validateSchemaElementId(elementId);
        if (isBooleanSchemaElement(elementTail)) parseBooleanSchemaElement(elementId);
        else if (isStringSchemaElement(elementTail)) parseStringSchemaElement(elementId);
        else if (isIntegerSchemaElement(elementTail)) {
            parseIntegerSchemaElement(elementId);
        } else {
            throw new ParseException(
                String.format("Argument: %c has invalid format: %s.", elementId, elementTail), 0);
        }
    }
    private void validateSchemaElementId(char elementId) throws ParseException {
        if (!Character.isLetter(elementId)) {
            throw new ParseException(
                "Bad character:" + elementId + "in Args format: " + schema, 0);
        }
    }
    private void parseBooleanSchemaElement(char elementId) {
        booleanArgs.put(elementId, false);
    }
    private void parseIntegerSchemaElement(char elementId) {
        intArgs.put(elementId, 0);
    }
    private void parseStringSchemaElement(char elementId) {
        stringArgs.put(elementId, "");
    }
    private boolean isStringSchemaElement(String elementTail) {
        return elementTail.equals("*");
    }
    private boolean isBooleanSchemaElement(String elementTail) {
        return elementTail.length() == 0;
    }
    private boolean isIntegerSchemaElement(String elementTail) {
        return elementTail.equals("#");
    }
    private boolean parseArguments() throws ArgsException {
        for (currentArgument = 0; currentArgument < args.length; currentArgument++) {
            String arg = args[currentArgument];
            parseArgument(arg);
        }
        return true;
    }
    private void parseArgument(String arg) throws ArgsException {
        if (arg.startsWith("-"))
            parseElements(arg);
    }
    private void parseElements(String arg) throws ArgsException {
        for (int i = 1; i < arg.length(); i++)
            parseElement(arg.charAt(i));
    }
    private void parseElement(char argChar) throws ArgsException {
        if (setArgument(argChar))
            argsFound.add(argChar);
        else {
            unexpectedArguments.add(argChar);
            errorCode = ErrorCode.UNEXPECTED_ARGUMENT;
            valid = false;
        }
    }
    private boolean setArgument(char argChar) throws ArgsException {
        if (isBooleanArg(argChar))
            setBooleanArg(argChar, true);
        else if (isStringArg(argChar))
            setStringArg(argChar);
        else if (isIntArg(argChar))
            setIntArg(argChar);
        else
            return false;
        return true;
    }
    private boolean isIntArg(char argChar) {
        return intArgs.containsKey(argChar);
    }
    private void setIntArg(char argChar) throws ArgsException {
        currentArgument++;
        String parameter = null;
        try {
            parameter = args[currentArgument];
            intArgs.put(argChar, new Integer(parameter));
        } catch (ArrayIndexOutOfBoundsException e) {
            valid = false;
            errorArgumentId = argChar;
            errorCode = ErrorCode.MISSING_INTEGER;
            throw new ArgsException();
        } catch (NumberFormatException e) {
            valid = false;
            errorArgumentId = argChar;
            errorParameter = parameter;
            errorCode = ErrorCode.INVALID_INTEGER;
            throw new ArgsException();
        }
    }
    private void setStringArg(char argChar) throws ArgsException {
        currentArgument++;
        try {
            stringArgs.put(argChar, args[currentArgument]);
        } catch (ArrayIndexOutOfBoundsException e) {
            valid = false;
            errorArgumentId = argChar;
            errorCode = ErrorCode.MISSING_STRING;
            throw new ArgsException();
        }
    }
    private boolean isStringArg(char argChar) {
        return stringArgs.containsKey(argChar);
    }
    private void setBooleanArg(char argChar, boolean value) {
        booleanArgs.put(argChar, value);
    }
    private boolean isBooleanArg(char argChar) {
        return booleanArgs.containsKey(argChar);
    }
    public int cardinality() {
        return argsFound.size();
    }
    public String usage() {
        if (schema.length() > 0)
            return "-[" + schema + "]";
        else
            return "";
    }
    public String errorMessage() throws Exception {
        switch (errorCode) {
            case OK:
                throw new Exception("TILT: Should not get here.");
            case UNEXPECTED_ARGUMENT:
                return unexpectedArgumentMessage();
            case MISSING_STRING:
                return String.format("Could not find string parameter for -%c.",
                    errorArgumentId);
            case INVALID_INTEGER:
                return String.format("Argument -%c expects an integer but was '%s'.
                    errorArgumentId, errorParameter);
            case MISSING_INTEGER:
                return String.format("Could not find integer parameter for -%c.", errorArgumentId);
        }

        return "";
    }
    private String unexpectedArgumentMessage() {
        StringBuffer message = new StringBuffer("Argument(s) -");
        for (char c: unexpectedArguments) {
            message.append(c);
        }
        message.append(" unexpected.");
        return message.toString();
    }
    private boolean falseIfNull(Boolean b) {
        return b != null && b;
    }
    private int zeroIfNull(Integer i) {
        return i == null ? 0 : i;
    }
    private String blankIfNull(String s) {
        return s == null ? "" : s;
    }
    public String getString(char arg) {
        return blankIfNull(stringArgs.get(arg));
    }
    public int getInt(char arg) {
        return zeroIfNull(intArgs.get(arg));
    }
    public boolean getBoolean(char arg) {
        return falseIfNull(booleanArgs.get(arg));
    }
    public boolean has(char arg) {
        return argsFound.contains(arg);
    }
    public boolean isValid() {
        return valid;

    }
    private class ArgsException extends Exception {}
}
  • λ¦¬νŒ©ν† λ§μ„ μœ„ν•΄ 인수λ₯Ό μΆ”κ°€ν•  수둝 더 엉망이 λ˜μ–΄λ²„λ¦Ό

κ·Έλž˜μ„œ λ©ˆμ·„λ‹€

  • 인수 μœ ν˜•μ€ λ‹€μ–‘ν•˜μ§€λ§Œ λͺ¨λ‘κ°€ μœ μ‚¬ν•œ λ©”μ„œλ“œ μ œκ³΅ν•˜λ―€λ‘œ ArgumentMarshaler 클래슀 생성

μ μ§„μ μœΌλ‘œ κ°œμ„ ν•˜λ‹€

  • κ°œμ„ μ΄λΌλŠ” μ΄λ¦„μœΌλ‘œ ꡬ쑰λ₯Ό 크게 λ’€μ§‘μœΌλ©΄ μ•ˆλœλ‹€
  • TDD: μ–Έμ œ μ–΄λŠ λ•ŒλΌλ„ μ‹œμŠ€ν…œμ΄ λŒμ•„κ°€μ•Ό ν•œλ‹€
  • μžλ™ν™”λœ ν…ŒμŠ€νŠΈμŠˆνŠΈλ₯Ό JUnit으둜 μž‘μ„± ν›„ μž‘μ€ 변경을 μ°¨λ‘€λ‘œ μˆ˜ν–‰

πŸ€”Β λ– μ˜€λ₯΄λŠ” 생각

  • 본격적으둜 μ½”λ“œ μœ„μ£Όμ˜ λ‚΄μš©μ΄ μ‹œμž‘λ˜μ—ˆλ‹€. 직접 μˆ˜ν–‰ν•΄λ³΄κ³  λ‚΄μš©μ„ λ³΅μŠ΅ν•˜μž

πŸ”ŽΒ μ§ˆλ¬Έ

πŸ“Β μ†Œκ° 3쀄 μš”μ•½

  • ν”„λ‘œκ·Έλž˜λ°μ€ 과학보닀 κ³΅μ˜ˆμ— 가깝닀 β†’ μ΄ˆμ•ˆλΆ€ν„° μž‘μ„±ν•˜κ³  μ •λ¦¬ν•˜μž
  • κ°œμ„ μ΄λΌλŠ” μ΄λ¦„μœΌλ‘œ ꡬ쑰λ₯Ό 크게 λ’€μ§‘μœΌλ©΄ μ•ˆλœλ‹€
  • TDD: ν…ŒμŠ€νŠΈ μš°μ„  μž‘μ„± ν›„ μ μ§„μ μœΌλ‘œ κ°œμ„ 
profile
Full stack tech visionary

0개의 λŒ“κΈ€