Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Conversation

@HavenDV
Copy link
Contributor

@HavenDV HavenDV commented Sep 13, 2022

Checklist

  • I have included examples or tests
  • I have updated the change log
  • I am listed in the CONTRIBUTORS file
  • I have cleaned up the commit history (use rebase and squash)

Changes proposed in this pull request:

@oxyplot/admins

@VisualMelon
Copy link
Contributor

Sorry I've not got around to looking at this yet, I'll try to find time tomorrow to go through it properly.

Source/OxyPlot/Annotations/ImageAnnotation.cs Outdated Show resolved Hide resolved
Source/OxyPlot/Annotations/LineAnnotation.cs Show resolved Hide resolved
Source/OxyPlot/Annotations/PathAnnotation.cs Outdated Show resolved Hide resolved
Source/OxyPlot/Annotations/PathAnnotation.cs Outdated Show resolved Hide resolved
@VisualMelon
Copy link
Contributor

Main thing to work out, I think, is how we are going to signal properties that have no default but must be assigned, e.g. FunctionAnnotation.Equation (see above) and ImageAnnotation.Source: both in the documentation, and when we throw exceptions because they are not assigned by the time they are rendered etc. Any thoughts welcome: worth figuring this out now then we can apply it elsewhere.

Pinging @Jonarw because he reviewed my original attempts at this.

@HavenDV
Copy link
Contributor Author

HavenDV commented Sep 19, 2022

For now, I've just settled on simply throwing InvalidOperationException("{name} is null."). This is not the best solution, but it is much better than the possible NRE. I didn't bother to add a detailed description because the current code is working and well tested and these events most likely won't happen. In addition, I do not always understand the context of the code in order to make a clear description.

@VisualMelon
Copy link
Contributor

VisualMelon commented Sep 19, 2022

Context I'm imagining is a user who is assembling an object from different places (so can't just throw all the properties together at once without needing a builder or shadow type of some kind) who may fail to set the value of one of these required-but-with-no-default properties: they may either not realise that they are meant to assign the value, or it may not be assigning it without realising (or indeed may be assinging it null without realising). As you say, hopefully OxyPlot itself isn't going to assign e.g. FunctionAnnotation.Function to null unilaterally, so ideally we want an exception that makes it clear that it's user error. InvalidOperationException is the right type (if we don't want our own), but I just wonder if we can convey it more strongly in the message: this property is null, and shouldn't be null by the time the plot element is expected to do something (and it's your problem as the consumer). Like I said, I can't suggest a better wording off hand, but hopefully that explains where I'm coming from.

Copy link
Contributor

@VisualMelon VisualMelon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of small things, otherwise I think this is all good.

/// </summary>
/// <value>The text.</value>
public string? Text { get; set; }
public string Text { get; set; } = string.Empty;
Copy link
Contributor

@VisualMelon VisualMelon Sep 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should remain as string? Text initialised to null

(Sorry, my original comment wasn't very clear: with it nullable we need to add checks when calling into MathRenderingExtensions)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will entail a whole series of checks during the rendering stage.
image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that might be inevitable. I'll take a closer look now, but I don't think we can change the default to non-null in a hurry.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only see problems with this if users with Nullable disable can sometimes have null instead of this value. But this will result in an NRE for them anyway.
While exceptions will let the user know that they forgot to set the Text property, the very use of TextualAnnotation implies this.

Copy link
Contributor

@VisualMelon VisualMelon Sep 20, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same problem as ImageAnnotation.ImageSource etc.: it has to be set, but there's almost 10 years of code that might not be initialising the object all at once, and may even be using null to signal to different parts of code that it needs to be changed: changing the default at this point will cover-over failing to assign the value, and be a silent code-breaking change for some users. Perhaps we can try to gauge how big a deal this will be?

Regarding the last point, PointAnnotation and friends don't actually require the text property to be set; however, the behaviour won't change for PointAnnotation with your proposal, but it may change the behaviour of consuming code. It may just be the old versions of everything we're using, but I'm surprised by the error in that case, as the usage is within an if (!String.IsNullOrEmpty) check.

Looking back at old posts, I think my previous remarks express my current feelings rather well:

I think the main benefit we might see from this will just be in informing us where we should be throwing more helpful errors. Short of breaking every plot element in two, I don't think there is too much we can achieve to tighten the API, so it will mostly be limited to expressing which things may be null, which dilutes the meaning for those which are expected to be null.

The problem is that OxyPlot is basically a bundle of mutable objects without defaults (which means that null signals something to the consumer). This (TextualAnnotation.Text) is obviously a case where I'm advocating for making something nullable because it might happen to be null, rather than because it is intended to be null.

@Jonarw has previously described the possibility of just leaving nullable off for certain types; I'm going to do some reading/experimentation to see if this might be a possibility in these cases. I've previously been opposed to this, but I could certainly buy the benefit of having nullable annotations on all methods but omitting it on a class of properties if it's not too misleading for the consumer. In particular, we could leave these unannotated now, and then annotate them e.g. when we have required: benefit of required is that it expresses the intention well, means simple and correct code will continue to work fine, and will noisily break old code, so is OK for a major release.

I'm torn between respecting the type system - which tells me to keep these nullable and use documentation to talk to the user instead - and trying to express the intention that these should be initialised to a non-null value by the user - which tells me to make these non-null and just initialise them to null anyway (is there any precedent for this in other libs?). I'm definitely opposed to adding non-null defaults for everything at the moment, though in this specific case, perhaps string.Empty would be OK..

Sorry, no decisions in there... I'd like to take a bit more time to think about this. My instinct still is to keep them nullable, and add more useful exceptions and inline documentation. Feel free to dump any vaguely relevant thoughts you might have here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinging @Jonarw again should be want to jump in on this

@VisualMelon
Copy link
Contributor

VisualMelon commented Sep 20, 2022

@HavenDV thanks for pushing that (if nothing else makes it easier to talk about): what's your reckoning? (NotNullWhen appears in netstandard2.1)

@HavenDV
Copy link
Contributor Author

HavenDV commented Sep 20, 2022

@HavenDV thanks for pushing that (if nothing else makes it easier to talk about): what's your reckoning? (NotNullWhen appears in netstandard2.1)

Sorry, I didn't understand what you mean, English is not my native language

@VisualMelon
Copy link
Contributor

Sorry, I'm not sure that's even good English to be honest.

Just wanted to know your opinion on your latest commit; obviously it's not pretty, but I don't think we can do better while continuing to support netstandard1.0 if we do make Text nullable.

@HavenDV
Copy link
Contributor Author

HavenDV commented Sep 20, 2022

I've been doing this since the early days of nullable enable and I'm already used to it, so it looks ok to me.

@VisualMelon
Copy link
Contributor

Cool; I suspect most other strings where we'll need these checks will be left as nullable, so shouldn't be wide-spread.

@VisualMelon
Copy link
Contributor

I've not done a complete review again, but I think if you're happy with the current state of this PR, then I am also happy. If so, will merge once 2.1.1 is out of the way (so hopefully next weekend).

@HavenDV
Copy link
Contributor Author

HavenDV commented May 4, 2023

Hi. Any news?

@VisualMelon
Copy link
Contributor

2.1.1 became 2.1.2 when I made a mistake, but let's ignore that and merge this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.