Какова хорошая практика создания метода проверки ввода в Java? - PullRequest
1 голос
/ 24 декабря 2011

Если я хочу проверить свои входные данные, я должен сделать код проверки как частные вспомогательные методы или создать отдельный статический вспомогательный класс? Увеличивает ли код проверки размер объекта?

Дополнительная информация

Допустим, у меня есть класс

import java.util.Vector;


public class Place {
    private final double    longitude;
    private final double    latitude;
    private final String    id;

    private       String           address;
    private       String           name;
    private       String           types;
    private       String           icon;
    private       String           phoneNumber;
    private       String           websiteUrl;
    private       int              rating;
    private       Vector<Integer>  challenges;

    public static class Builder {
        // required parameter
        private final double    longitude;
        private final double    latitude;
        private final String    id;
        // optional parameter
        private       String           address = "n/a";
        private       String           name = "n/a";
        private       String           icon = "n/a";
        private       String           phoneNumber = "n/a";
        private       String           websiteUrl = "n/a";
        private       String           types = "n/a";
        private       Vector<Integer>  challenges = new Vector<Integer>();
        private       int              rating = 0;

        public Builder(double longitude, double latitude, String id) {
            assert(longitude >= -180.0 && longitude <= 180.0);
            assert(latitude >= -90.0 && longitude <= 90.0);
            this.longitude = longitude;
            this.latitude = latitude;
            this.id = id;
        }

        public Builder address(String address) {
            this.address = address;
            return this;
        }

        public Builder types(String types) {
            this.types = types;
            return this;
        }

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder icon(String icon) {
            this.icon = icon;
            return this;
        }

        public Builder phoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
            return this;
        }

        public Builder websiteUrl(String websiteUrl) {
            this.websiteUrl = websiteUrl;
            return this;
        }

        public Builder builder(int rating) {
            this.rating = rating;
            return this;
        }

        public Place build() {
            return new Place(this);
        }
    }

    public Place(Builder builder) {
        // required parameters
        longitude = builder.longitude;
        latitude = builder.latitude;
        id = builder.id;

        // optional parameters
        address = builder.address;
        types = builder.types;
        name = builder.name;
        icon = builder.icon;
        phoneNumber = builder.phoneNumber;
        websiteUrl = builder.websiteUrl;
        rating = builder.rating;
        challenges = builder.challenges;
    }

    public double getLongitude() {
        return longitude;
    }

    public double getLatitude() {
        return latitude;
    }

    public String getId() {
        return id;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getAddress() {
        return address;
    }

    public String getTypes() {
        return types;
    }

    public void setTypes(String types) {
        this.types = types;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setIconUrl(String icon) {
        this.icon = icon;
    }

    public String getIcon() {
        return icon;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }


    public void setWebsiteUrl(String websiteUrl) {
        this.websiteUrl = websiteUrl;
    }

    public String getWebsiteUrl() {
        return websiteUrl;
    }

    public void setRating(int rating) {
        this.rating = rating;
    }

    public int getRating() {
        return rating;
    }

    @Override
    public String toString() {
        return "(" + Double.toString(longitude) + ", " +  Double.toString(latitude) + ")";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Place other = (Place) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        }
        else if (!id.equals(other.id))
            return false;
        return true;
    }

    public Vector<Integer> getChallenges() {
        return new Vector<Integer>(challenges);
    }

    public void addChallenges(Integer i) {
        this.challenges.add(i);
    }

    public void showChallenges() {
        for (Integer i : challenges) {
            System.out.print(i + ", ");
        }
    }
}

Если мне нужно проверить аргумент address перед его настройкой, где я должен поместить код для проверки адреса в этом случае?

Ответы [ 6 ]

5 голосов
/ 24 декабря 2011

Если вы говорите, просто просматривая, правильно ли отформатирована введенная строка или если длина правильная, тогда вы должны использовать закрытый метод. С другой стороны, если вы хотите проверить, является ли адрес правильным (посмотрите его на карте) или что-то более сложное, имеет смысл создать интерфейс AddressValidator и вызвать его из этого частного метода.

Причиной закрытого метода является то, что вы вызываете его как из конструктора, так и из любого другого метода, который может содержать адрес. Причиной интерфейса является то, что вы можете захотеть иметь, например, Online / offline AddressValidator (MockAddressValidator или тот, который вызывает разные классы для каждой страны и т. д.).

Поскольку AddressValidator можно повторно использовать в других классах, и для поддержания чистоты вашего кода я бы создал его как интерфейс верхнего уровня + OnlineAddressValidator. Это также делает ваш класс более читабельным. Для полной конфигурируемости вы можете подумать о том, как вы собираетесь предоставлять экземпляр AddressValidator, например, через конструктор или тот, который определен как статический финальный валидатор.

public interface AddressValidator {
    static class AddressValidatorResult {
        // some results, you might want to return some useful feedback (if not valid)

        boolean isValid() {
            throw new IllegalStateException("Method not implemented yet");
        }
    }

    public static class AddressValidationException extends Exception {
        private AddressValidationException(AddressValidatorResult result) {
            // add some implementation
        }
    }


    // don't throw ValidateException here, invalid addresses are normal for
    // validators, even if they aren't for the application that uses them
    AddressValidatorResult validateAddress(String address);
        // don't throw ValidateException here, invalid addresses are normal for
        // validators, even if they aren't for the application that uses them
}

public class DefaultAddressValidator implements AddressValidator {

    public static class Params {
        // some parameters for this specific validator
    }

    private final Params params;

    public DefaultAddressValidator(Params params) {
        // creates this validator
        this.params = params;
    }

    @Override
    public AddressValidatorResult validateAddress(String address) {
        // perform your code here

        // I don't like "return null" as it may lead to bugs
        throw new IllegalStateException("Method not implemented yet");
    }
}


// and use it like this
private void validateAddress(String address) throws AddressValidationException {
    // e.g. field AddressValidator set in constructor 
    AddressValidatorResult result = addressValidator.validateAddress(address);
    if (!result.isValid()) {
        throw new AddressValidationException(result);
    }
}
1 голос
/ 24 декабря 2011

Должен ли я сделать проверочный код в качестве частных вспомогательных методов или создать отдельный статический вспомогательный класс?

Это зависит от того, считаете ли вы, что вам необходимо повторно использовать тот же метод и в другом классе для той же цели (проверка входных данных), лучше написать метод в отдельном статическом вспомогательном классе, чтобы вы могли повторно использовать метод и поддерживать это легко. Если вы пишете один и тот же частный вспомогательный метод в нескольких классах каждый раз, когда вам нужно внести изменения, вы должны отредактировать каждый метод в каждом классе, со статическим вспомогательным классом вы изменяете код только в одном месте ...

1 голос
/ 24 декабря 2011

Должен ли я создать проверочный код как частные вспомогательные методы или создать отдельный статический вспомогательный класс?

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

После того, как вы отредактируете: ИМО, вам все еще сложно сказать. Если вам нужно проверить адрес только в одной единственной точке вашего приложения (id: метод setter), я бы проверил его внутри метода setter. Если ввод был неверным, я бы бросил IllegalArgumentException.


Увеличивает ли код проверки размер объекта?

Однако ответ на ваш второй вопрос Нет . Чтобы понять почему, вы должны знать, что такое объектно-ориентированное программирование.

Некоторые ссылки:

0 голосов
/ 25 декабря 2011

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

Проверка данных должна автоматически вызываться инфраструктурой вашего программного обеспечения.Это помогает предотвратить забвение программистами соответствующего кода.Итак, методы должны быть общедоступными (интерфейс тоже будет работать).

Такие фреймворки, как Struts, Spring, Hibernate и имеют свои собственные системы проверки.Java EE использует проверку bean-компонента.

Я рекомендую проверку bean-компонента, поскольку он выполняет проверку независимо от источника ввода.Когда большинство людей думает о проверке ввода, они думают о данных, поступающих от пользователя, например, HTTP-запрос, командная консоль, текстовое поле Swing.Проверка Spring и Struts часто подходит для таких ситуаций.Но в долгоживущих программах, разработанных для предприятий, часто вводятся другие потоки данных, например обновления базы данных SQL из других программ, восстановление базы данных после сбоя, служебная шина предприятия, JMS.

Вот почему я предпочитаю проверку бобов.Недостатком является то, что «безопасные источники» (данные, которые, как вы знаете, незапятнаны) проверяются без необходимости.Но с сегодняшней вычислительной мощностью это редко должно вызывать серьезную озабоченность. Учебник по Java EE

0 голосов
/ 24 декабря 2011

Я склонен проверять в методах get () и set () везде, где это возможно, - вызывать внешние статические методы для общих задач, таких как проверка дат или очистка ввода (т. Е. Чтобы избежать внедрения SQL)используйте (и только когда-либо будете использовать) проверку в одном классе, сохраните ее как частный вспомогательный метод.Если есть сомнения, я склонен вытащить функциональность в статический вспомогательный класс.Это не имеет большого значения для объема кода, больше не требует усилий для реализации и намного более гибко.

0 голосов
/ 24 декабря 2011
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...