How much work should the constructor for an HTML p

2019-01-30 14:57发布

How much work is it reasonable for an object constructor to do? Should it simply initialize fields and not actually perform any operations on data, or is it okay to have it perform some analysis?

Background: I was writing a class which is responsible for parsing an HTML page and returning various information based on the parsed information. The design of the class is such that the class' constructor does the parsing, throwing an exception if an error occurs. Once the instance is initialized, the parsed values are available without further processing via accessors. Something like:

public class Parser {

    public Parser(final String html) throws ParsingException {
        /* Parsing logic that sets private fields */
        /* that throws an error if something is erroneous.*/
    }

    public int getNumOfWhatevers() { return private field; }
    public String getOtherValue()  { return other private field; }
}

After designing the class I started to wonder if this was correct OO practice. Should the parsing code be placed within a void parseHtml() method and the accessors only return valid values once this method is called? I feel as though my implementation is correct, but I can't help but feel that some OO purists might find it incorrect for some reason and that an implementation such as the following would be better:

public class Parser {

    public Parser(final String html) {
        /* Remember html for later parsing. */
    }

    public void parseHtml() throws ParsingException { 
        /* Parsing logic that sets private fields */
        /* that throws an error if something is erroneous.*/
    }

    public int getNumOfWhatevers() { return private field; }
    public String getOtherValue()  { return other private field; }
}

Are there instances where initialization code, such as parsing information, should not occur within the constructor, or am I just being silly and second-guessing myself?

What are the benefits/drawbacks of splitting the parsing from the constructor?

Thoughts? Insights?

19条回答
神经病院院长
2楼-- · 2019-01-30 15:15

You should try to keep the constructor from doing unnecessary work. In the end, it all depends on what the class should do, and how it should be used.

For instance, will all the accessors be called after constructing your object? If not, then you've processed data unnecessarily. Also, there's a bigger risk of throwing a "senseless" exception (oh, while trying to create the parser, I got an error because the file was malformed, but I didn't even ask it to parse anything...)

On second thought, you might need the access to this data fast after it is built, but you may take long building the object. It might be ok in this case.

Anyway, if the building process is complicated, I'd suggest using a creational pattern (factory, builder).

查看更多
啃猪蹄的小仙女
3楼-- · 2019-01-30 15:17

The constructor should create a valid object. If in your case that requires reading and parsing information, than so be it.

If the object can be used for other purposes without parsing the information first, than consider making two constructors, or a separate method.

查看更多
放荡不羁爱自由
4楼-- · 2019-01-30 15:17

A constructor should set up the object to be used.

So whatever that is. That may include taking action on some data or just setting fields. It will change from each class.

In the case you are speaking of an Html Parser, I would opt for creating the class, and then calling a Parse Html method. The reason for this is it gives you a furture opportunity to set items in the class for parsing the Html.

查看更多
小情绪 Triste *
5楼-- · 2019-01-30 15:19

In this particular case, I would say there is two classes here: A parser and a parse result.

public class Parser {
    public Parser() {
        // Do what is necessary to construct a parser.
        // Perhaps we need to initialize a Unicode library, UTF-8 decoder, etc
    }
    public virtual ParseResult parseHTMLString(final string html) throws ParsingException
    {
        // Parser would do actual work here
        return new ParseResult(1, 2);
    }
}
public class ParseResult
{
    private int field1;
    private int field2;
    public ParseResult(int _field1, int _field2)
    {
        field1 = _field1;
        field2 = _field2;
    }
    public int getField1()
    {
        return field1;
    }
    public int getField2()
    {
        return field2;
    }
}

If your parser could work on partial sets of data, I'd suspect it would be suitable to add another class into the mix. Possibly a PartialParseResult?

查看更多
Ridiculous、
6楼-- · 2019-01-30 15:19

In general, a constructor should:

  1. Initialize all the fields.
  2. Leave the resulting object in a valid state.

However, I would not use the constructor in the way you have. Parsing should be separated from using the parsing results.

Generally when I write a parser I write it as a singleton. I don't store any fields in the object except the single instance; instead, I only use local variables within the methods. Theoretically these could just be static (class-level) methods, but that would mean that I couldn't make them virtual.

查看更多
对你真心纯属浪费
7楼-- · 2019-01-30 15:24

A constructor should do whatever is necessary to put that instance into a runnable, valid, ready-to-use state. If that means some validation or analysis, I'd say it belongs there. Just be careful about how much the constructor does.

There might be other places in your design where validation fits as well.

If the input values are coming from a UI, I'd say that it should have a hand in ensuring valid input.

If the input values are being unmarshalled from an incoming XML stream, I'd think about using schemas to validate it.

查看更多
登录 后发表回答