0

I'm trying to add error handling to a function that reads data from a DataSource (which performs all the parsing etc. required). Unfortunately (due to a lack of versioning until now) some of the values that I try to read from the DataSource may fail to parse (because they are malformed or simply missing), resulting into a default value being returned (at least until now).

I want to be able to detect such errors in the new (versioned) DataSets, but also still need to be backwards-compatible with the older DataSets (which rely on the default values).

class Foo {

    int value_1;
    int value_2;
    //...

    void loadDataFromSource(DataSource source)
    {
        value_1 = source.parseValue(1);
        value_2 = source.parseValue(2);
        //...
    }
}

The easiest way would be to have parseValue() throw an Exception if it fails to parse (instead of returning a default value as it does now), but that would make it necessary to duplicate the code in loadDataFromSource().

void loadDataFromSource(DataSource source)
{
    //Exceptions thrown by parseValue() are handled by the caller of this function
    value_1 = source.parseValue(1);
    value_2 = source.parseValue(2);
    //...
}

void loadDataFromSource_Legacy(DataSource legacySource)
{
    //Exceptions thrown by parseValue() are discarded and default values are used
    try { value_1 = legacySource.parseValue(1); }
    catch(...) { value_1 = 42; }
    try { value_2 = legacySource.parseValue(2); }
    catch(...) { value_2 = -7; }
    //...
}

But the duplicate code (especially) of the value_1 =... & value_2 =... feels somehow clunky and wrong.

I considered adding a flag and a default value to the parseValue() function, but that too does not feel quite right.

void loadDataFromSource(DataSource source)
{
    int revision = source.getRevision();
    bool useDefaultValueOnError = revision < 10;
    //Exceptions thrown by parseValue() - if any - are handled by the caller of this function
    value_1 = source.parseValue(1, useDefaultValueOnError, 42);
    value_2 = source.parseValue(2, useDefaultValueOnError, -7);
    //...
}

What is the best practice here? Optimally I'd like to have the ability to signal the user that default values had to be used (which can, but not must, happen when reading unversioned legacy data) while still permitting the data to be used. At the same time, any data failing to parse in the current (now versioned) DataSource needs to be considered an error (and unusable).

  • please don't cross-post: stackoverflow.com/questions/47926168/… "Cross-posting is frowned upon as it leads to fragmented answers splattered all over the network..." – gnat Dec 21 '17 at 16:06
  • @gnat: It's not cross-posting; he was told to move it here. – Nicol Bolas Dec 21 '17 at 16:09
  • @gnat You saw that I was referred here by another user? I am rather new here, I was not aware of the cross-posting rule, and I did not see any way to move my question, apologies for that. I must admit after such a welcome my enthusiasm has been rather curbed. – CharonX Dec 21 '17 at 16:42
  • 3
    @CharonX: Unfortunately, so many people do this that we can't afford to coddle them all. It is also unfortunate that you appear to have gotten bad advice at Stack Overflow; I'm a moderator there and your question seems perfectly on-topic to me. – Robert Harvey Dec 21 '17 at 17:20
  • 3
0

I cannot add comments to questions in either spot, where you have asked this question, but I did want to give some input on what you were asking and what appears to have happened in the comments of both sides. You do have a question that can have answers from both sites, but that should be dependent on the question provided and suggestions made through comments by you and other users.

Design

To me, design is not just the principles, practices, and concepts in software (these are normally stated as architectural things), and it is not just the low-level "tools" that the software is built upon. Design should encompass both levels to some degree. Otherwise, it would be like an engineer designing a structure of a multi-level office, then the person(s) that put it together using glue rather than bolts for a metal beam. (using term tools loosely as I am meaning that it could be anything like code, server, OS, or whatever you would consider a tool)

In looking at UML class diagrams, we can see a blueprint of the software in terms of objects associated with the business the application is being developed towards, but we also see the expected individual pieces that exist within the objects.

enter image description here

enter image description here

As seen in the above images, We can see named methods and properties with defined data types. When approaching the design of exception handling, it is no different than determining if you meet the standard when thinking of using certain joints, styles, or materials. ( i.e. Do you have the proper safeties in place to be allowed to use x?)

Original Question Assumptions and Suggestions

For your question, it appears to be worded to show that you, or the team, decided that there was a need to re-design the existing exception handling. The re-design would be the result of some business entity (DataSource in your case) was changed or is changing. Your issue then appears to be that there would still be a need to handle the previous version of the business entity in functionality, but the parse would need to be handled differently depending on version/value provided.

As far as the entities are concerned, there is still a need to discuss the low-level items associated with the entities, like why the entity/entities were designed previously, what safeties (exceptions) were used, what dependencies (lookup values, usage, etc.) are changing prior, or at the same time, with the entity/entities, and so on.

When approaching a solution to the issue, you have at least two perspectives to discuss.

From the architecture side, you have two business entities that are separated due to versioning and possibly conditional logic, so there would need to be a discussion about combining or splitting these entities. Do the entities have the same or different reasons to change? If they have the same reasons to change, then would splitting them up technically give you duplicated code?

From the development/programming side, the functionality lends itself to thinking in terms of creating a base class and deriving entities from it. Per version (I believe just two in your case), there could be shared functionality, but there are unique variations on how parsing values works (New version overrides the previous functionality).

  • Would there be a reason to continuously change how values are parsed over the life of the application?
  • Are there other past versions of this entity, and do they get used in the same manner as this entity that recently became a previous version?
    • If not, then what would need to be done to avoid the pitfall of over-engineering the entity/entities?
  • Could values in the new version become invalid in the same way with the previous version?
    • If so, then would you change the new version to the same functionality as the previous version?

Another perspective could be from your customer, since they could have a role in stating/defining their need. It could be worth discussing these questions with them, since the flow could make certain functionality valid/invalid to use. Why do they need the previous version? Is it just for viewing historical entries, or do they need to create new things in terms of that previous version?

Touching On Some Of The Comments

First, I agree with @RobertHarvey that it is unfortunate how the advice and discussion turned out, and no one should be coddled on either site.

I do think that there should be an attempt to provide something constructive, whether it is through the different flags available on the site (flags showing that either the OP is missing something, possibly not using the right words to look up their issue, or is not using the site for its purpose) or some comment/answer to get the OP in the right direction. (I think that part should fall more on other users in the community rather than moderators; the moderators have the ability for it but have many other things to keep up with)

For your question, I gathered that there were no indications that you were specifically looking for practices on multiple branches of code/workflow. There is a method that needs to be used in different ways. While the multiple branches comment could be valid, this suggestion does not change the question to only consider any answers to be derived from the software engineering site. Since the idea of software is to be malleable, so should the questions, answers, and discussions to a certain degree.

To a certain degree, that for some question, if there is a direction defined for the requested answer (usually from the OP), then answers should follow suit. The exceptions would be what falls under some of the flags, where the OP may not know a direction or does not understand the direction the question may lend itself to go for some given information.

So, there is counter-point that shows there could be an answer in terms of having a coding deficit. One of the more popular discussion points would be the Square Rectangle problem, where it could be seen as a high-level discussion about structure, but there is also a low-level code discussion, when the existing code begins to take the form of the problem (gains a code smell).

I hope that this helps with re-asking that question and asking future questions. And, I hope that I answered in a way that is more constructive for you as a developer. (Edits to get that point across are appreciated)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.