在构造函数中尝试/捕获 - 推荐的做法?

时间:2013-05-28 15:38:13

标签: java oop exception try-catch ooad

我一直对

感到好奇的事情
public class FileDataValidator {

private String[] lineData;

public FileDataValidator(String[] lineData){

    this.lineData = lineData;
    removeLeadingAndTrailingQuotes();

    try
    {
        validateName();
        validateAge();
        validateTown();
    }
    catch(InvalidFormatException e)
    {
        e.printStackTrace();
    }

}

//validation methods below all throwing InvalidFormatException

不建议在我的构造函数中包含try / catch块吗? 我知道我可以让Constructor将Exception抛回给调用者。你们在调用像我在构造函数中所做的方法时更喜欢什么?在调用类中,您更喜欢创建FileDataValidator的实例并在该实例上调用那里的方法吗?只是有兴趣听一些反馈!

3 个答案:

答案 0 :(得分:21)

在您显示的代码中,验证问题不会与创建此对象实例的代码进行通信。这可能不是一件好事。

变体1:

如果在方法/构造函数中捕获异常,请确保将某些内容传递回调用方。如果一切正常,您可以将字段isValid设置为true。这看起来像这样:

private boolean isValid = false;

public FileDataValidator(String[] lineData){

    this.lineData = lineData;
    removeLeadingAndTrailingQuotes();

    try
    {
        validateName();
        validateAge();
        validateTown();
        isValid = true;
    }
    catch(InvalidFormatException e)
    {
        isValid = false;
    }
}

public boolean isValid() {
    return isValid;
}

变体2:

或者你可以让异常或其他异常传播给调用者。我已将其显示为未经检查的异常,但根据您的异常处理宗教信息执行任何操作:

public FileDataValidator(String[] lineData){

    this.lineData = lineData;
    removeLeadingAndTrailingQuotes();

    try
    {
        validateName();
        validateAge();
        validateTown();
    }
    catch(InvalidFormatException e)
    {
        throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
    }

}

变体3:

我想提到的第三种方法有这样的代码。在调用代码中,您必须调用构造函数,然后调用build()函数,该函数将工作与否。

String[] lineData = readLineData();
FileDataValidator onePerson = new FileDataValidator();
try {
    onePerson.build(lineData);
} catch (InvalidDataException e) {
    // What to do it its bad?
}

这是类代码:

public FileDataValidator() {
    // maybe you need some code in here, maybe not
}

public void build(String[] lineData){

    this.lineData = lineData;
    removeLeadingAndTrailingQuotes();

    try
    {
        validateName();
        validateAge();
        validateTown();
    }
    catch(InvalidFormatException e)
    {
        throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
    }

}

当然,build()函数可以使用您调用的isValid()方法来查看它是否正确但异常对我来说是构建函数的正确方法。

变体4:

我想提到的第四种方法是我最喜欢的方法。它有这样的代码。在调用代码中,您必须调用构造函数,然后调用build()函数,该函数将工作与否。

这种方式遵循JaxB和JaxRS的工作方式,这与您的方式类似。

  1. 外部数据源 - 您有一个文件,他们有XML或JSON格式的传入消息。
  2. 用于构建对象的代码 - 您拥有代码,他们的代码库根据各种JSR中的规范工作。
  3. 验证与对象的构建无关。
  4. 主叫代码:

    String[] lineData = readLineData();
    Person onePerson = new Person();
    FileDataUtilities util = new FileDataUtilities();
    try {
        util.build(onePerson, lineData);
        util.validate(onePerson);
    } catch (InvalidDataException e) {
        // What to do it its bad?
    }
    

    以下是数据存在的类代码:

    public class Person {
        private Name name;
        private Age age;
        private Town town;
    ... lots more stuff here ...
    }
    

    用于构建和验证的实用程序代码:

    public FileDataValidator() {
        // maybe you need some code in here, maybe not
    }
    
    public void build(Person person, String[] lineData){
    
        this.lineData = lineData;
        removeLeadingAndTrailingQuotes();
        setNameFromData(person);
        setAgeFromData(person);
        setTownFromData(person);
    }
    
    public boolean validate(Person person) {
    
        try
        {
            validateName(person);
            validateAge(person);
            validateTown(person);
            return true;
        }
        catch(InvalidFormatException e)
        {
            throw new com.myco.myapp.errors.InvalidDataException(e.getMessage());
        }
    
    }
    

答案 1 :(得分:3)

您应该考虑静态工厂模式。使所有参数构造函数成为私有的。提供静态FileDataValidator(args ...)方法。这接受并验证所有参数。如果一切正常,它可以调用私有构造函数并返回新创建的对象。如果有任何失败,抛出一个Exception来通知调用者它提供了错误的值。

我还必须提到这一点: catch(例外e){ printSomeThing(E); }

你可以用例外来做最致命的反模式。是的,您可以在命令行上读取一些错误值,然后呢?调用者(提供错误值的人)没有得到错误值的通知,程序执行将继续。

答案 2 :(得分:2)

我倾向于通过知道如何处理它们的代码来处理异常。在这种情况下,我假设创建FileDataValidator的代码位知道如果文件数据无效将会发生什么,并且异常应该在那里处理(我主张传播给调用者)。

在讨论最佳实践时 - 类名FileDataValidator闻起来像我。如果您正在创建的对象存储文件数据,那么我将其称为FileData - 可能使用validate方法?如果您只想验证文件数据,那么静态方法就足够了。