Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let GetOccurrences() et al return an IEnumerable rather than HashSet. #665

Merged

Conversation

minichma
Copy link
Collaborator

@minichma minichma commented Dec 7, 2024

This PR modifies Calendar.GetOccurrences() and related methods to return an ordered IEnumerable that generates the actual occurrences as they are enumerated, rather than returning a fully populated HashSet. When invoking GetOccurrences, the start- and endTime can now be omitted. The change brings several benefits:

  • Even a calendar with undefinite recurrences can be enumerated without specifying an endTime, which can be helpful, if the endTime isn't known.
  • A consumer of the lib can now easily find the first occurrence or the next after a certain date by calling something likeGetOccurrences(startTime: t).GetFirstOrDefault()
  • The occurrences are generated in ascending order
  • The number of generated occurrences can be reduced, if not all are enumerated.
  • The overall performance is increased, even if all occurrences are returned, because the implementation requires less sorting operations.

Modifications implemented:

  • Return IEnumerable from GetOccurrences and IEvaluator.Evaluate
  • Allow omitting startTime and endTime when calling GetOccurrences
  • Rename the overload of GetOccurrences that returns the occurrences of a single day to GetOccurrencesOfDay, to avoid ambiguities with the other overloads, now that start/end time can be omitted.

@minichma minichma marked this pull request as ready for review December 7, 2024 09:10
@minichma minichma requested a review from axunonb December 7, 2024 17:55
Ical.Net/Calendar.cs Outdated Show resolved Hide resolved
=> this
.Select(iCal => iCal.GetOccurrences<T>(startTime, endTime))
.ToArray()
.OrderedMergeMany();

private FreeBusy CombineFreeBusy(FreeBusy main, FreeBusy current)
Copy link
Collaborator

Choose a reason for hiding this comment

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

FreeBusy method are not referenced - do we still need them?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I have no idea, but as they are not related to this PR, I suggest to deal with that in a different PR (see above).

axunonb
axunonb previously approved these changes Dec 7, 2024
Copy link
Collaborator

@axunonb axunonb left a comment

Choose a reason for hiding this comment

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

See my remarks and decide how to deal with them.
Same with flags from SonarCloud .
Overall this is an amazing job, tnx!

@axunonb
Copy link
Collaborator

axunonb commented Dec 7, 2024

Does this PR make #641 redundant, and could we remove RecurrencePatternEvaluator.MaxIncrementCount = 1000?

}
return occurrences;
}
public IEnumerable<Occurrence> GetOccurrencesOfDay(DateTime dt)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would you like to keep the unused (and thus uncovered overloads)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I generally didn't remove any methods, because I don't want to change the API in this PR outside of what is related to the immediate topic. If we want to change it, I think we should do that in a separate PR, so we keep concerns separated. But this one indeed is a special case. Actually I don't think, we should have a separate method just for getting the occurrences for a single day, because it can easily be implemented with the other variants and its not obvious, why we wouldn't also add versions for ByWeek, ByHour, etc. So I'd certainly vote for removing them, but also the other overloads (i.e. GetOccurrencesOfDay(IDateTime)).

In this case we have another challenge. Due to the params of GetOccurrences(DateTime? = null, DateTime? = null) et al being optional now, a call like GetOccurrences(new DateTime(...)) would now invoke the overload with startTime, endTime, rather than the overload for getting the occurrences for a single day (which has been renamed). This could break existing code without being obvious. It will be introduced in v5, so we could argue that's ok (and I actually would do so), but we should be aware of it. And add a note to a potential migration guide. What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@axunonb I removed the versions of GetOccurrences(date) that were handling a single day altogether (see prev comment). Only two tests existed that tested any of them at all. I don't think, they will be missing. We should add some comment in a migration guide, should one be written, about the ambiguity due to the new nullable params in the other overloads.

@minichma
Copy link
Collaborator Author

minichma commented Dec 8, 2024

@axunonb Thank you for the review, glad you like the change. Appreciate your comments. My previous few PRs have been based on branches in the ical-org repo, this one is based on my minichma repo. When based on the ical-org, a code coverage report is automatically generated, but obviously not if based on a different one. Could we change that, so we get the report for every PR, also when based on an external repo?

@minichma
Copy link
Collaborator Author

minichma commented Dec 8, 2024

Does this PR make #641 redundant, and could we remove RecurrencePatternEvaluator.MaxIncrementCount = 1000?

Actually it doesn't, because MaxIncrementCount is related to the number of increments between recurrences and in this respect nothing changed. Actually the title of #641 is not fully precise on that.

@axunonb
Copy link
Collaborator

axunonb commented Dec 8, 2024

Could we change that, so we get the report for every PR, also when based on an external repo?

Unfortunately we can't, as GitHub secrets can't be applied to external PRs, Just continue with branches inside ical-org.

…ble`s, `OrderedMerge`, `OrderedMergeMany`, `OrderedDistinct`.
…etc. to return an ordered `IEnumerable` rather than a `HashSet` and modify the implementations to generate results on iteration rather than fully enumerating the full result set upfront.
@minichma minichma force-pushed the work/minichma/feature/evaluate_enumerable branch from 946b25b to a2ec4fa Compare December 8, 2024 21:37
@minichma
Copy link
Collaborator Author

minichma commented Dec 8, 2024

Comments related to the new issues identified by Sonarcloud:

Drop this useless call to 'ToList' or replace it by 'AsEnumerable' if you are using LINQ to Entities.

They aren't useless, because they cause an intended iteration. The reason is mentioned in the code comments.

Add the default parameter value defined in the overridden method.

TBD. I actually left the default params out intentionally. In the interface they are there for the convenience of users, but internally I think we should be more verbose and explicitly specify the params.

Refactor this method to reduce its Cognitive Complexity from 39 to the 15 allowed.

Not a topic of this PR. Some simplification has already been implemented in the mentioned method though.

@minichma minichma requested a review from axunonb December 8, 2024 21:54
@axunonb
Copy link
Collaborator

axunonb commented Dec 8, 2024

Comments related to the new issues identified by Sonarcloud:

Yep, so we could mark the issues deliberately chosen as described in the comments with //NOSONAR (or a warning disable pragma, and leave the To-dos as issues to remember.
This helps to distinguish issues eventually to be fixed and others, which are accepted and won't appear on the SonarCloud list.
Cognitive Complexity level of 15 is low, I have 20 in other projects. We could adjust for ical.net, too.

@minichma minichma force-pushed the work/minichma/feature/evaluate_enumerable branch from 9505ff2 to 2449741 Compare December 9, 2024 07:30
Copy link

sonarcloud bot commented Dec 9, 2024

@minichma
Copy link
Collaborator Author

minichma commented Dec 9, 2024

Comments related to the new issues identified by Sonarcloud:

Yep, so we could mark the issues deliberately chosen as described in the comments with //NOSONAR (or a warning disable pragma, and leave the To-dos as issues to remember. This helps to distinguish issues eventually to be fixed and others, which are accepted and won't appear on the SonarCloud list. Cognitive Complexity level of 15 is low, I have 20 in other projects. We could adjust for ical.net, too.

Tweaked a little. Not too convinced this is helpful for the overall code quality. I'm not the biggest fan of cluttering code with 'disable' comments, so I undid a few changes. We might want to reconsider some of the rules over time.

Copy link
Collaborator

@axunonb axunonb left a comment

Choose a reason for hiding this comment

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

Tnx, excellent PR

@axunonb
Copy link
Collaborator

axunonb commented Dec 9, 2024

We might want to reconsider some of the rules over time.

Absolutely, we're currently using the default "Sonar Way" rules.

@minichma minichma merged commit 1330b86 into ical-org:main Dec 9, 2024
4 checks passed
@minichma minichma deleted the work/minichma/feature/evaluate_enumerable branch December 9, 2024 08:36
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