Парсер и поиск решения для проблемы расчета процент


Я работаю над проблемой кодирования, чтобы помочь с регулярными выражениями, и как лучше писать комментарии в мой код. Класс анализирует процент вопрос, и ответ.

Если у кого есть какие-либо отзывы об общей организации моего класса, имена переменных, или действительно ли мои комментарии могут быть улучшены, было бы желательно. Моя цель заключается в том, что кто-то читает мой код может ясно понять, что он делает и как он работает, держа программисту "обслуживания" в виду.

package com.percent.model;

import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Class represents a solver for a percentage question.
 * @author steve
 */
public class PercentageQueryPatternSolver {

    //? is x% of y
    private static final Pattern findIsPattern = Pattern.compile("(\\?) is (\\d+)% of (\\d+)");
    //x is ?% of y
    private static final Pattern findPercentPattern = Pattern.compile("(\\d+) is (\\?)% of (\\d+)");
    //x is y% of ?
    private static final Pattern findOfPattern = Pattern.compile("(\\d+) is (\\d+)% of (\\?)");

    /*Although the numeric values in the queryString passed to the constructor must be integers, we
     *store them as Doubles since the value that we are solving for may not be a whole number, and
     *we don't know which of the 3 values we are solving for in the beginning. When the query
     *is solved, we will remove any trailing .00 values to clean up the output.
     */
    private Double firstIsValue;
    private Double secondPercentValue;
    private Double thirdOfValue;

    //These are the valid forms that we expect the query string to take
    private Collection<Pattern> validQueryStringPatterns = Arrays.asList(findIsPattern,
                                                                         findPercentPattern,
                                                                         findOfPattern);

    /**
     *
     * @param queryString query to be parsed. must take one of the following forms:
     * ? is x% of y    (example: ? is 10% of 32)
     * x is ?% of y    (example: 12 is ?% of 62)
     * x is y% of ?    (example: 25 is 40% of ?)
     *
     * 'x' and 'y' must be whole numbers, and both values are required
     * '?' represents a value to be solved for, and must be entered as '?'
     *
     *  If the queryString does not take one of the above forms, an IllegalArgumentException is thrown
     */
    public PercentageQueryPatternSolver(String queryString){
        initialize(queryString);
    }

    //parses the queryString and populates the firstIsValue/secondPercentValue/thirdOfValue variables
    private void initialize(String queryString){
        boolean queryStringMatchesAValidQueryPattern = false;
        for(Pattern pattern : validQueryStringPatterns){
            final Matcher patternMatcher = pattern.matcher(queryString);
            if(patternMatcher.matches()){
                queryStringMatchesAValidQueryPattern = true;
                setQueryParameters(patternMatcher);
            }
        }
        if(!queryStringMatchesAValidQueryPattern) {
            throw new IllegalArgumentException(queryString + "does not match a known pattern.");
        }
    }

    //pulls the query parameters from the matcher and sets the respective attributes
    private void setQueryParameters(Matcher validatedPatternMatcher){
        firstIsValue = getDoubleValueOfGroupFromMatcher(validatedPatternMatcher, 1);
        secondPercentValue = getDoubleValueOfGroupFromMatcher(validatedPatternMatcher, 2);
        thirdOfValue = getDoubleValueOfGroupFromMatcher(validatedPatternMatcher, 3);
    }

    //returns the double value of a particular group from the matcher
    private Double getDoubleValueOfGroupFromMatcher(Matcher matcher, int groupNumber){
        String groupValue = matcher.group(groupNumber);
        return "?".equals(groupValue) ? null : Double.valueOf(groupValue);
    }

    //returns the inputDouble formatted for output purposes (remove trailing decimal if 0)
    private String getOutputFormattedDoubleValue(Double inputDouble){
        String output = String.valueOf(inputDouble);
        if (inputDouble == Math.floor(inputDouble)){
            output = String.valueOf(inputDouble.intValue());
        }
        return output;
    }

    /**
     *
     * @return the original queryString (used to construct this pattern) with the
     * missing value populated.
     */
    public String getSolvedPattern(){
        if(firstIsValue == null){
            firstIsValue = (thirdOfValue * secondPercentValue) / 100;
        }
        else if(secondPercentValue == null){
            secondPercentValue = (firstIsValue * 100) / thirdOfValue;
        }
        else if(thirdOfValue == null){
            thirdOfValue = (firstIsValue * 100) / secondPercentValue;
        }
        return getOutputFormattedDoubleValue(firstIsValue) + " is " +
               getOutputFormattedDoubleValue(secondPercentValue) + "% of " +
               getOutputFormattedDoubleValue(thirdOfValue);

        }

}


159
4
задан 3 февраля 2018 в 04:02 Источник Поделиться
Комментарии
1 ответ


    //? firstIsValue x% of y
private static final Pattern findIsPattern = Pattern.compile("(\\?) is (\\d+)% of (\\d+)");
//x firstIsValue ?% of y
private static final Pattern findPercentPattern = Pattern.compile("(\\d+) is (\\?)% of (\\d+)");
//x firstIsValue y% of ?
private static final Pattern findOfPattern = Pattern.compile("(\\d+) is (\\d+)% of (\\?)");

Первое правило написания хороших комментариев не сказать, что код делает, но зачем он делает это. Е. Г.

    // Define separate patterns depending on whether we are searching for 
// the subject,
// the subject's complement, or
// the object of the preposition.
private static final Pattern subjectFinder = Pattern.compile("(\\?) is (\\d+)% of (\\d+)");
private static final Pattern complementFinder = Pattern.compile("(\\d+) is (\\?)% of (\\d+)");
private static final Pattern objectFinder = Pattern.compile("(\\d+) is (\\d+)% of (\\?)");

Теперь мы можем легко увидеть, что причина, почему мы имеем три различных модели. Это потому, что мы могли бы искать три разные вещи.

Я не пытаюсь повторить то, что делает код. Это потому, что я понятия не имел, что ? firstIsValue x% of y имел в виду. Мне приходилось читать код, чтобы понять комментарий, который полностью назад. Предполагаем, что читатель знает достаточно, чтобы понять, что код делает напрямую. Комментарий к скажи им, что код делает косвенно.

Я изменил имена, чтобы те, которые я нашел яснее. Если вам нравится венгерская нотация, которая является общей в Java, вы можете добавить Pattern для каждого имени. Я обычно предпочитаю, чтобы оставить его, с исключениями, когда я нахожу его полезным. Если Вы читаете связанная статья, я бы предпочел приложения венгерские имена для систем Венгрии.

Новые имена описывают части "приговор", который с рисунком. Иногда это стоит делать небольшое исследование, чтобы придумать названия получше. Например, я не помню, что существительное после "это" (или другие связывающие глагол) называется дополнением предмета. Я просто вспомнил (смутно), что он назывался что-то другое со связующим глаголом, чем с активным глаголом. Google в помощь.

Хороший нейминг-это часто лучше, чем комментировать комментарии.

Еще лучше, считают модульные тесты. Имена и комментарии могут выпасть из синхронизации с кодом. Например, оригинальное название findOfPattern. Если вы изменить "на" на "в", код и название будет рассинхронизация.

С модульные тесты, они скажут вам, если код и тест не синхронизированы. Некоторые тесты не удастся. Затем вы можете либо сделать матч код тестов или в некоторых случаях, изменять тесты, чтобы соответствовать код.

Из-за этой особенности насильственных синхронность, модульные тесты часто делают лучше комментарии, чем комментарии.

Чтобы подтвердить, когда вы используете комментарии, пожалуйста, используйте их, чтобы рассказать читателю, почему вы делаете что-то. Вы должны очень редко имеют код обфусцирован, что вам нужно объяснять, что вы делаете. Сам код должен рассказать нам, что код делает. Комментарий должен только добавить, почему.

2
ответ дан 3 февраля 2018 в 07:02 Источник Поделиться