Ignore the fact that in this example this code is running on the server. It's irrelevant to the point of this video. It could be a CLI tool or a Blazor Server app that runs locally as a Dektop app with Electron. Focus on the Time point.
DateTimeOffset is an unambiguous point in time where DateTime combines with the Kind property. So if you are trying to do the right thing and always use UtcNow() but you store it in a Datetime and don't set the Kind to UTC, some date/time conversions (like serialization) might not give you the results you expect. I think DateTimeOffset is more precise than Datetime as well.
You can feed dates with a time zone offset into a DateTime just fine, It'll localise it to the same instant in the local timezone with the proper DateTimeKind set. Whether the respects the Kind is a different matter alltogether (usually the answer is no) When it comes to data structures, when you care for the TimeZone (e.g. for localisation), you will generally use DateTimeOffset over DateTime. Unfortunately it's not always the case.
Working in a company that employs employees in several timezones, having the timezone instead of using UTC built in could provide extra context. Is it created in the morning of creator's time? Is it edited in the afternoon of the editor's time? Without that, you have to lookup each users's timezone. Not very ideal if your employees crossing timezones frequently. And yes, it's not for everyone. If you are happy with UTC datetime, then use it.
I'd created a IDateTimeProvider very similarly to the ISystemClock as you've referenced. I really like how they've put some of the Stopwatch functionality in this new TimeProvider class; it should make asserting time differences easier in unit tests (E.g. when you log how long a service took to run)
It's good that they provide some framework-level time dependency like this. However, due to the issues that you just showed with setting up a mock, I'd rather stick to my custom IDateTimeProvider. What the team behind it should do is to provide an interface for the TimeProvider.
I treated DateTime variables as external dependencies (since they are when they are based on system time) and as consequence I would want to receive DateTime as a parameter. in the video example the endpoint would have a date parameter that then would be passed to the method
@@maxbradley9534 I am passing the responsibility to provide the date to the end user. That doesnt make the method non testable, on the contrary it makes the method that exists testable, because any unit test that uses DateTime.Now or other methods that rely on external resources should be considered failed tests . I can change the machine time and make it output whatever i want, thus the test is not consistent and is a bad test.
I went even further beyond and created a TimeProvider interface which provides an overridable definition of Delay() (to replace Task.Delay()) so I can do deterministic unit testing of time-dependent code - for example I can make a unit test for "does a token expire from the token cache after 24 hours" just by fast-forwarding simulated time
On the GitHub PR there's a link to a 1.5hr RUclips video that - somewhere in it - contains an argument as to why it's not. If you can find it, please link it to me :p.. I saw the PR yesterday during break and I forgot about it
I've implemented this before as ambient context with a good default, such as the one you're using there, given it's a cross cutting, basic concern. Still solves it but no need to inject it everywhere.
I believe AftercastGames is referring to this link? ruclips.net/video/WW65sGkDINQ/видео.html Edit: Seems this is a link to when the discussion was a bit older, but still relevant imo.
There's so much they can do with the built in DateTime object too with respect to its Kind, they could genuinely make it intuitive, but I don't expect them to because of legacy concerns. DateTime uses its Kind wrong in almost every single context; it cares about it when you don't, it disregards it when you care about it, and it makes ridiculous assumptions when you don't have one.
It's like you're reading my mind. I'm currently working with datetime logic and had to write a time wrapper so I can unit test it. Mind is also an abstract class..
This is pretty similar to what I do already. Although I take a much simpler approach and have one source class for all of my time related events, and I have multiple classes that listen to those events and then notify other classes that they need to perform specific functions. No interfaces necessary.
What we need now is a abstraction layer for file system, it would make possible some very interesting things like some tests for file system operations
Much ado about about the obvious. Over 30 years ago I was writing business programs in Fortran. It was clear then that the date and time printed on business reports sometimes need be independent of the current computer clock. Viola write a layer to provide times. I'm sure there is some "gang of four" jargon for this approach but it is something any decent programmer should know intuitively.
The main bug with time - it's how the time was implemented in real world. I mean timezones and local times. All of us have common time and we need to use one time for all areas of the world, then million of time issues will be solved. Morning, Day, Evening, Night will have own time range for each area, but time should be equal in any point of the Earth.
using an abstract class allows them to add more and more methods to the TimeProvider without breaking all existing software unlinke an interface. its the same with DbConnection vs IDbConnection.
@@nickchapsas default interface implementations allow for "multiple inheritance" and are limited to only function if the caller explicitly invokes the methods on the interface, you can't use them on the concrete types that implement the interface
I was using an interface with basically the same name of .NET 8, it was ITimeProvider, in general I think interfaces can be better but an abstract class is still valid
I generally prefer using minus operator for getting elapsed time so I’d like to see that with the timers but since c# requires operators be defined statically you wouldn’t be able to mock it ☹️
I had rather that they created their own nodatime variation. Even with a type to store time zone and version and hook it up with EF core to make some geolocation based time calculations. It’s quite a lot of work to maintain and a consistent code base with different time zones and versions.
They probably used an abstract rather than an interface with default implementations for backwards compatibility with netstandard2.0, which doesn't support default implementations for interfaces.
Please consider your (maybe our) wish for an ITimeProvider interface. If they do it, this will obsolete all our nice homebrew stuff. The timeprovider is nice, but I'll stay with my custom interface for now. At least we can note that they addressed the issue.
When it comes to DateTime, every language/Framework out there has it's own ups & downs. I usually depend on My won Custom Class/Interfaces/Services but it a bit confusing/Tidy/messy sometimes and When I opened this video I was honestly expecting an Interface(ITimeProvider) instead of an abstract class but hey it's a good progress still I guess and the team should be made aware of this.
That’s cool. But passing the frequency in, doesn’t that make it system dependent as well? Or did I did not understand that right? Awesome content. As always.
It feels that this provider lacks the interface segregation principle. It contains several different features that may be split into multiple interfaces. From the usage perspective it will be much more obvious, as now it looks similar to a service locator (anti-?)pattern.
I agree that it should be an interface. If the system doesn't provide it, for my own newly development projects, I would use a custom time provider interface.
ITimeProvider interface. Cool. Finally a standard one for basic uses. But I'm absolutely shocked that they introduced TimeProvider class (ok, let's have a handy default impl) with STATIC getters wired to system time AGAIN. Holy cow, what for? Those who currently use hard-wired system time, once they hear "the new TimeProvider is better, please do use it instead", they're going to use the static getters as they are accustomed to, gaining literally nothing. It's a goddamn FifthElement's BigRedDontPressMeButton. You just don't add old broken features under bunch of new names if you want to fix your library and want your users to learn to do better. D'oh!
Why is generate greeting not taking the date time as a parameter? I don't use DateTimeOffset because I convert all dates to UTC in my systems before storage and all processing and computation is done in UTC. Conversion to local time is only done during presentation in the UI. DateTimeOffset is only needed when you want to store time with an offset that is not zero. UTC's offset is zero.
So you don’t care about the user’s offset from utc? For example when you wanna email all users during their morning hours to improve email opening rates, how do you know what is "morning" for them when there is no UI or client? Storing everything is UTC out of context is naive
@@nickchapsas I store the user's actual desired timezone in a database field that they can always change later. That's what I use to accept datetime from them and convert to UTC using TimeZoneInfo.ConvertTimeToUtc() before saving. Also when displaying, or doing something like the email you talked about, I use their stored timezone to convert from UTC to their desired timezone. One major advantage of converting to UTC before saving in database is that you are never affected by daylight savings changes. Also computation or filtering data based on time is easier because they are all stored in UTC.
TBH this should be a standard thing to provide interface for a class. The hell, make it part of the language, like if I have class Foo, then I have e.g. Foo.interface. I can't even tell how much time I *wasted* (yes, it is a waste) to write those wrapper classes just to be able to abstract from framework or some referenced library logic.
let them fix/simplify that working with client(saved peer user/taken from request) timezone, instead relying on assumption that client cares if it's afternoon on server or not..
So, it looks like this would not stop someone on your project calling DateTime.Now. Are you aware of any analyzer, or similar, which could make sure everyone uses the new abstraction? I was thinking the other day about making an analyzer which can do that. Though its only the DateTime.Now and things like the methods on File which seem like clear targets for something like that.
I've been coding dotnet professionally since 1.1. In every one of my projects I've added an ITime with a default implementation returning utcnow. I've never understood why Microsoft refuse to provide this common mockable interface. It's simple...
They should make *ITimeProvider* a d have *TimeProvider* implement it. That way it would be easy to make a mocked implementation of the interface. This will be moot when roles and extensions/shapes get added though, since then you can just define the shape/interface you need after the fact. I *really* hope it's coming un 8.0, but I'm not holding my breath..
I've seen some ways to solve it by using MS test shims. Which is of course are working in enterprise environment. I usually use my own interface for DateTime... But the need to test such scenario with DateTime is happening not very often
I'm a total und utter noob in C# (and programming) and just starting to learn, but wouldn't the "dateTimeNow" object be 'tightly coupled' with GenerateGreetText, something one should avoid, and I should inject a DateTime object with the time of the greeting I want? So I can mock it in the test? Like I said, I just learn C# via RUclips and I have no idea what I'm doing.
Your instinct is correct. Logic that works on time should be separated from code that gets the time. In a more complex scenario, however, that does multiple steps with delays and timeouts, having a mockable time interface that speeds up time is helpful.
But yeah I’ve convinced every company I’ve worked in the past 10 years to used an IDateTimeProvider instead of DateTime static directly. Easy sell, there’s no other way to reliably unit test time dependent logic
This is the perfect example of something to never unit test at all. Very simple code that doesn't need testing. If you even did, you could have just passed in date times with specific times to test and never used a time provider.
@@nickchapsasI found Preview 1 and Preview 2 for Visual Studio 17.6, but I'm looking for a download link for Preview 4. Could you please provide a link or direct me to a trusted source where I can download it? Thank you.
@@nickchapsas I was able to find Preview 1,2 and Preview 3 for Visual Studio 17.6, but I'm looking for a download link for Preview 4. Could you please provide a link or direct me to a trusted source where I can download it? Thank you
Ugh. TBH this doesn't really change much for me, since I have a design rule to only ever mock interfaces and never concrete or abstract types. I know that sounds a bit dogmatic, but I'd rather have a slight bit of mess in a trivial wrapper than risk having weird test code.
@Nick, do you have plans just in case the AI takeover happens within the next couple of years? Like do you have an alternative career path or a lucrative non-tech side project in case this happens in the short term?
In complex scenarios the reason why Dapper is faster is because you are using SQL, a native language for your database engine - the example in video is where compiling a query takes more time than fetching data, in contrary, for complex queries the opposite happens: compilation of the query is fast, but the query itself is complex, so database engine takes time to process it, then other factors comes to place, mostly that you are using LINQ, so some things might be "lost in translation" when EF is compiling to SQL. I made this error only once, I spend enormous time to optimise LINQ for complicated query with some minor success and then I just downloaded Dapper, wrote it in SQL and it just worked few times faster (BTW, we were still using EF everywhere else, it's too convenient, Dapper was only for report-like complicated queries). My mistake was that I was using wrong tool to solve the problem - SQL is a language that was specifically designed to deal with querying data, there is no reason to make your life difficult for purity sake.
Sorry, someone is going to have to explain to me the difference between this video and just, in the tests, putting DateTime(2023, 01, 01, 8, 0, 0). I can’t see the difference because the video is not explaining in detail where it’s getting it’s time from.
If you decide to do a DateTime video please consider looking at something like NodaTime in that same video. Would be interesting to see if nodatime is really required.
Seems like interfaces are default and the most "expected" way to abstract things, espesially for external consumers. So I really dont uderstand why they "expose" abstract class, with this silly ticks parameter)
It looks to me like test induced design that offers no benefit for production code. Maybe someone can reply with an example of how this helps a real world scenario to change my mind.
I always dislike the fact there are no interfaces. I mean its 2022 decoupling is mandatory i never inject an intstance always an interface and the exception to the rule is third party instances only when i can mock them easily in unit test. If not they will get abstracted away behind a concrete implementation of own with an exclude from codecoverage attribute. Very bad but at least i control my own interaction with the 3rd party code.
sometime interfaces are useless - "abstraction hell" and errors in runtime, in most cases you have only one implementation and interface is only used for testing but it can be solved differently
@@adrian_franczak i get your point but it doesnt mean interfaces are a way to abstraction hell and not are useless when you only have one concrete class implementing the interface. If you want to swap out the old implementation for the new one you get rekt with your hard dependencies and your "ugly" way of testing your own implementation interacting with the 3rd party library
My IClock implementation is much better. Based on an interface, default service calls DateTime.* and if I want, I can TimeTravel in my unit tests in the TestableClock instance. Microsoft did it again, wrong.
If your constructor is taking a lot of dependencies, your class is probably doing too much. If your constructor is a mess, that also suggests that the constructor itself is doing too much. Ideally, a constructor should just get the object in a valid state so it can start taking method calls; often that just means assigning the dependencies to fields.
What's wrong with having DateTime as parameter and using DateTime new() or .Parse in test to run it? There you get consistent results. Omg what is this video even about...
Bullshit twice. TimeProvider is just mix everything in single interface, but them should not. Places where you need QPC is strictly not places where you need wall clock and measure units is different.
Ignore the fact that in this example this code is running on the server. It's irrelevant to the point of this video. It could be a CLI tool or a Blazor Server app that runs locally as a Dektop app with Electron. Focus on the Time point.
did you post the link you mention at 7:09?
DateTimeOffset vs DateTime has always confused me. Some teams have contracts with offset others with stock.
DateTimeOffset is an unambiguous point in time where DateTime combines with the Kind property. So if you are trying to do the right thing and always use UtcNow() but you store it in a Datetime and don't set the Kind to UTC, some date/time conversions (like serialization) might not give you the results you expect.
I think DateTimeOffset is more precise than Datetime as well.
You can feed dates with a time zone offset into a DateTime just fine, It'll localise it to the same instant in the local timezone with the proper DateTimeKind set.
Whether the respects the Kind is a different matter alltogether (usually the answer is no)
When it comes to data structures, when you care for the TimeZone (e.g. for localisation), you will generally use DateTimeOffset over DateTime. Unfortunately it's not always the case.
This. Please make a video on this.
Same
Can you please make a video about the datetimeoffset and why it's better over datetime?
@Dionte Smith in simple scenarios like you've just described it doesn't matter much.
Working in a company that employs employees in several timezones, having the timezone instead of using UTC built in could provide extra context. Is it created in the morning of creator's time? Is it edited in the afternoon of the editor's time?
Without that, you have to lookup each users's timezone. Not very ideal if your employees crossing timezones frequently.
And yes, it's not for everyone. If you are happy with UTC datetime, then use it.
I'd created a IDateTimeProvider very similarly to the ISystemClock as you've referenced. I really like how they've put some of the Stopwatch functionality in this new TimeProvider class; it should make asserting time differences easier in unit tests (E.g. when you log how long a service took to run)
It's good that they provide some framework-level time dependency like this. However, due to the issues that you just showed with setting up a mock, I'd rather stick to my custom IDateTimeProvider. What the team behind it should do is to provide an interface for the TimeProvider.
I treated DateTime variables as external dependencies (since they are when they are based on system time) and as consequence I would want to receive DateTime as a parameter. in the video example the endpoint would have a date parameter that then would be passed to the method
Sure but then you are just passing the problem up the chain. Now that method that passes in the DateTime is not testable.
@@maxbradley9534 I am passing the responsibility to provide the date to the end user. That doesnt make the method non testable, on the contrary it makes the method that exists testable, because any unit test that uses DateTime.Now or other methods that rely on external resources should be considered failed tests . I can change the machine time and make it output whatever i want, thus the test is not consistent and is a bad test.
@@madsxcva Eh? So when you're unit testing, you prefer to sit there for 24 hours? Because "consistent" time runs at a rate of 1 second per second.
I went even further beyond and created a TimeProvider interface which provides an overridable definition of Delay() (to replace Task.Delay()) so I can do deterministic unit testing of time-dependent code - for example I can make a unit test for "does a token expire from the token cache after 24 hours" just by fast-forwarding simulated time
This is a great application for this
For my curiosity, how would it be any different than providing an instance of your interface where 24 hours would already have passed?
Can you throw a quick example of your test and that TimeProvider? Github gist would be great
Since .NET 8 is far from finalized, the team should be made aware that this design is highly suspect.
Looking forward for the DateTime vs DateTimeOffset video 🎉
Me too
This should totally have been an interface, that mocking setup is complicated.
On the GitHub PR there's a link to a 1.5hr RUclips video that - somewhere in it - contains an argument as to why it's not.
If you can find it, please link it to me :p.. I saw the PR yesterday during break and I forgot about it
Agree 100%, this is ugly.
Absolutely! I dont think the setup would be that much different tough…
It's not that bad imo, pretty much anything you'd mock ends up being messy. Unless it's super simple unit tests.
They will very likely provide a fake class so you won't need to mock it anyway and just use their implementation.
I've implemented this before as ambient context with a good default, such as the one you're using there, given it's a cross cutting, basic concern. Still solves it but no need to inject it everywhere.
Re: DateTimeOffset vs DateTime I would appreciate to hear your perspective on the reason for which is better
Its better to have an excuse why i cant do a unit test
That's funny because in the field it's so true. :)
I would have preferred a minimalistic interface, but I followed the discussion as it was streamed on youtube, and I get why it is the way it is
Do expand a bit please
Do you have a link to this discussion please?
@@ProfessorCodemunkie ruclips.net/video/KVDnUSH90qI/видео.html
@@ProfessorCodemunkie ruclips.net/video/KVDnUSH90qI/видео.htmlh34m27s
I believe AftercastGames is referring to this link? ruclips.net/video/WW65sGkDINQ/видео.html
Edit: Seems this is a link to when the discussion was a bit older, but still relevant imo.
There's so much they can do with the built in DateTime object too with respect to its Kind, they could genuinely make it intuitive, but I don't expect them to because of legacy concerns.
DateTime uses its Kind wrong in almost every single context; it cares about it when you don't, it disregards it when you care about it, and it makes ridiculous assumptions when you don't have one.
Love the vid. I'm really bad with dates, timestamps, etc. Glad to have content on this and hoping for more!
It's like you're reading my mind. I'm currently working with datetime logic and had to write a time wrapper so I can unit test it. Mind is also an abstract class..
They have also added a class called FakeTimeProvider to Microsoft.Extensions.Time.Testing which makes mocking a lot easier.
This is pretty similar to what I do already. Although I take a much simpler approach and have one source class for all of my time related events, and I have multiple classes that listen to those events and then notify other classes that they need to perform specific functions. No interfaces necessary.
What we need now is a abstraction layer for file system, it would make possible some very interesting things like some tests for file system operations
There already is System.IO.Abstractions
@@bomret isnt this 3rd party lib?
@@adrian_franczak yes. But it’s been around for more than a decade and is very widely used.
The best channel for .NET enthusiasts, keep on going mate 🦾
Much ado about about the obvious. Over 30 years ago I was writing business programs in Fortran. It was clear then that the date and time printed on business reports sometimes need be independent of the current computer clock. Viola write a layer to provide times. I'm sure there is some "gang of four" jargon for this approach but it is something any decent programmer should know intuitively.
Please make a video about datetimeoffset!
Please make a video on why to use DateTimeOffset ❤
The main bug with time - it's how the time was implemented in real world. I mean timezones and local times. All of us have common time and we need to use one time for all areas of the world, then million of time issues will be solved. Morning, Day, Evening, Night will have own time range for each area, but time should be equal in any point of the Earth.
using an abstract class allows them to add more and more methods to the TimeProvider without breaking all existing software unlinke an interface.
its the same with DbConnection vs IDbConnection.
But that's why they added default implementations in interfaces in C# 8
@@nickchapsas default interface implementations allow for "multiple inheritance" and are limited to only function if the caller explicitly invokes the methods on the interface, you can't use them on the concrete types that implement the interface
@@nickchapsas I think those don't work because they are planning to ship it down level.
I was using an interface with basically the same name of .NET 8, it was ITimeProvider, in general I think interfaces can be better but an abstract class is still valid
It also took them 20 years to create a file-scoped namespaces. This tiny little code formatting feature should have been done like 10 years ago
I generally prefer using minus operator for getting elapsed time so I’d like to see that with the timers but since c# requires operators be defined statically you wouldn’t be able to mock it ☹️
I had rather that they created their own nodatime variation. Even with a type to store time zone and version and hook it up with EF core to make some geolocation based time calculations. It’s quite a lot of work to maintain and a consistent code base with different time zones and versions.
Yeah. And most probably that's exactly why they did not.
I agree that it should be an Interface!
Please, make a video about why we should use DateTimeOffset
They probably used an abstract rather than an interface with default implementations for backwards compatibility with netstandard2.0, which doesn't support default implementations for interfaces.
Why should we use date time offset? Can you please make a video?
its important if your app is dealing with different timezones and storing everything as UTC will be confusing for user (summer/winter time)
Why DateTimeOffset? Love the videos, thanks for the great content!
Please consider your (maybe our) wish for an ITimeProvider interface.
If they do it, this will obsolete all our nice homebrew stuff.
The timeprovider is nice, but I'll stay with my custom interface for now.
At least we can note that they addressed the issue.
This has never been a problem in any big consulting firm:
Just test it 3 times a day! 🤣
jokes aside: thanks for the update, great video as usual 🤗
When it comes to DateTime, every language/Framework out there has it's own ups & downs. I usually depend on My won Custom Class/Interfaces/Services but it a bit confusing/Tidy/messy sometimes and When I opened this video I was honestly expecting an Interface(ITimeProvider) instead of an abstract class but hey it's a good progress still I guess and the team should be made aware of this.
That’s cool. But passing the frequency in, doesn’t that make it system dependent as well? Or did I did not understand that right? Awesome content. As always.
It feels that this provider lacks the interface segregation principle. It contains several different features that may be split into multiple interfaces. From the usage perspective it will be much more obvious, as now it looks similar to a service locator (anti-?)pattern.
Please make a video explaining why you think they made an abstract class, and why they should be using interfaces for that!
Did you ask this question to chatgpt!! As far I remember you did!! And your reaction was out of the world!
Yeap, that was part of the test that ChatGPT solved!
I agree that it should be an interface. If the system doesn't provide it, for my own newly development projects, I would use a custom time provider interface.
ITimeProvider interface. Cool. Finally a standard one for basic uses. But I'm absolutely shocked that they introduced TimeProvider class (ok, let's have a handy default impl) with STATIC getters wired to system time AGAIN. Holy cow, what for? Those who currently use hard-wired system time, once they hear "the new TimeProvider is better, please do use it instead", they're going to use the static getters as they are accustomed to, gaining literally nothing. It's a goddamn FifthElement's BigRedDontPressMeButton. You just don't add old broken features under bunch of new names if you want to fix your library and want your users to learn to do better. D'oh!
Why is generate greeting not taking the date time as a parameter?
I don't use DateTimeOffset because I convert all dates to UTC in my systems before storage and all processing and computation is done in UTC. Conversion to local time is only done during presentation in the UI. DateTimeOffset is only needed when you want to store time with an offset that is not zero. UTC's offset is zero.
So you don’t care about the user’s offset from utc? For example when you wanna email all users during their morning hours to improve email opening rates, how do you know what is "morning" for them when there is no UI or client? Storing everything is UTC out of context is naive
@@nickchapsas I store the user's actual desired timezone in a database field that they can always change later. That's what I use to accept datetime from them and convert to UTC using TimeZoneInfo.ConvertTimeToUtc()
before saving. Also when displaying, or doing something like the email you talked about, I use their stored timezone to convert from UTC to their desired timezone.
One major advantage of converting to UTC before saving in database is that you are never affected by daylight savings changes. Also computation or filtering data based on time is easier because they are all stored in UTC.
TBH this should be a standard thing to provide interface for a class. The hell, make it part of the language, like if I have class Foo, then I have e.g. Foo.interface. I can't even tell how much time I *wasted* (yes, it is a waste) to write those wrapper classes just to be able to abstract from framework or some referenced library logic.
let them fix/simplify that working with client(saved peer user/taken from request) timezone, instead relying on assumption that client cares if it's afternoon on server or not..
???
So, it looks like this would not stop someone on your project calling DateTime.Now. Are you aware of any analyzer, or similar, which could make sure everyone uses the new abstraction? I was thinking the other day about making an analyzer which can do that. Though its only the DateTime.Now and things like the methods on File which seem like clear targets for something like that.
I've been coding dotnet professionally since 1.1. In every one of my projects I've added an ITime with a default implementation returning utcnow. I've never understood why Microsoft refuse to provide this common mockable interface. It's simple...
They should make *ITimeProvider* a d have *TimeProvider* implement it. That way it would be easy to make a mocked implementation of the interface. This will be moot when roles and extensions/shapes get added though, since then you can just define the shape/interface you need after the fact.
I *really* hope it's coming un 8.0, but I'm not holding my breath..
Can we use TimeProvider as scoped service instead of singleton?
I've seen some ways to solve it by using MS test shims. Which is of course are working in enterprise environment. I usually use my own interface for DateTime... But the need to test such scenario with DateTime is happening not very often
I'm a total und utter noob in C# (and programming) and just starting to learn, but wouldn't the "dateTimeNow" object be 'tightly coupled' with GenerateGreetText, something one should avoid, and I should inject a DateTime object with the time of the greeting I want? So I can mock it in the test? Like I said, I just learn C# via RUclips and I have no idea what I'm doing.
Your instinct is correct. Logic that works on time should be separated from code that gets the time.
In a more complex scenario, however, that does multiple steps with delays and timeouts, having a mockable time interface that speeds up time is helpful.
But yeah I’ve convinced every company I’ve worked in the past 10 years to used an IDateTimeProvider instead of DateTime static directly. Easy sell, there’s no other way to reliably unit test time dependent logic
I’d love to see the stopwatch type take one of these in as a constructor so you could test your code with a stopwatch
This is the perfect example of something to never unit test at all. Very simple code that doesn't need testing. If you even did, you could have just passed in date times with specific times to test and never used a time provider.
Hello TimeProvider is not available in visual studio 17.6 preview 2, What can I do to bring in my project?
Download preview 4
@@nickchapsasI found Preview 1 and Preview 2 for Visual Studio 17.6, but I'm looking for a download link for Preview 4. Could you please provide a link or direct me to a trusted source where I can download it? Thank you.
@@nickchapsas I was able to find Preview 1,2 and Preview 3 for Visual Studio 17.6, but I'm looking for a download link for Preview 4. Could you please provide a link or direct me to a trusted source where I can download it? Thank you
Would it be better to inject a delegate to this method which could provide a datetime?
Can I have written version of this video? I have a hard time with DateTime handling.
Not gonna lie. I've never seen a need to unit test time of day.
Very interesting solution to a problem I never really worried about. :D
Pretty shocked they went an abstract class route. Hopefully they do go w/ an interface approach
Why is the stopwatch functionality put into the timeprovider?
When would you mock the stopwatch?
If you’re using it to measure something and that measurement is part of something like a log parameter and you need to verify it
I kind of hate the clock abstraction they made. So bad I'm tempted to keep using my own or NodaTime.
Yes it should be an interface with default implementations on the interface.
Ugh. TBH this doesn't really change much for me, since I have a design rule to only ever mock interfaces and never concrete or abstract types. I know that sounds a bit dogmatic, but I'd rather have a slight bit of mess in a trivial wrapper than risk having weird test code.
make a video on datetime and datetimeoffset pls
For e.g a REST API... can time provider be the client time (zone)?
Depends on how you use it but yeah you can set a LocalTimeZone as long as you have the user’s offset from UTC
@Nick, do you have plans just in case the AI takeover happens within the next couple of years? Like do you have an alternative career path or a lucrative non-tech side project in case this happens in the short term?
I’m finally gonna start my dream beekeeping business
@@nickchapsasStart now to corner the AI bee market!
You could use the swarm intelligence of the bees as your AI 😄
@@nickchapsas Cool! Maybe you have another RUclips channel about it?
In complex scenarios the reason why Dapper is faster is because you are using SQL, a native language for your database engine - the example in video is where compiling a query takes more time than fetching data, in contrary, for complex queries the opposite happens: compilation of the query is fast, but the query itself is complex, so database engine takes time to process it, then other factors comes to place, mostly that you are using LINQ, so some things might be "lost in translation" when EF is compiling to SQL.
I made this error only once, I spend enormous time to optimise LINQ for complicated query with some minor success and then I just downloaded Dapper, wrote it in SQL and it just worked few times faster (BTW, we were still using EF everywhere else, it's too convenient, Dapper was only for report-like complicated queries). My mistake was that I was using wrong tool to solve the problem - SQL is a language that was specifically designed to deal with querying data, there is no reason to make your life difficult for purity sake.
Finally, hopefully over time this will improve now its finally here.
Good grief I'll stick with my own IDateTimeProvider that takes 1 line to mock for the default common utcnow use case
Sorry, someone is going to have to explain to me the difference between this video and just, in the tests, putting DateTime(2023, 01, 01, 8, 0, 0). I can’t see the difference because the video is not explaining in detail where it’s getting it’s time from.
If you decide to do a DateTime video please consider looking at something like NodaTime in that same video. Would be interesting to see if nodatime is really required.
Definitely should be an interface. Who knows, maybe they change it in the future
Seems like interfaces are default and the most "expected" way to abstract things, espesially for external consumers.
So I really dont uderstand why they "expose" abstract class, with this silly ticks parameter)
Finally I can remove all my IDateTimeProvider interface usage and substitute it with .NET native interf... oh, wait... an abstract class?
I think I'll still use Nodatime
It looks to me like test induced design that offers no benefit for production code. Maybe someone can reply with an example of how this helps a real world scenario to change my mind.
It's little confusing that they added the stopwatch features to it. Why not using them directly over the Stopwatch class?
That was my thought too, seems like unnecessary duplication of the framework surface area.
I think I'll stick with Noda and IClock.
I don't understand why one couldn't just create a DateTime object instead of using system time and pass it to the test cases.
Lol you just answered your own question for why it’s an abstract class and not an interface, the high frequency stuff
And solution looks like addon of stopwarch...still raw solution, so we have to expect different implementaion after sometime ...looks like
I always dislike the fact there are no interfaces. I mean its 2022 decoupling is mandatory i never inject an intstance always an interface and the exception to the rule is third party instances only when i can mock them easily in unit test. If not they will get abstracted away behind a concrete implementation of own with an exclude from codecoverage attribute. Very bad but at least i control my own interaction with the 3rd party code.
sometime interfaces are useless - "abstraction hell" and errors in runtime, in most cases you have only one implementation and interface is only used for testing but it can be solved differently
@@adrian_franczak i get your point but it doesnt mean interfaces are a way to abstraction hell and not are useless when you only have one concrete class implementing the interface. If you want to swap out the old implementation for the new one you get rekt with your hard dependencies and your "ugly" way of testing your own implementation interacting with the 3rd party library
I was so hoping you would say Dotnet was removing null. :)
I wish!
so why utcnow instead of now?
hmm probably you mean why DTOffset?
Dude, there's never been anything stopping you from using dependency injection.
Why could this all of not been done in an interface?
Please tell me about DateTimeOffset
Trivial problem, and trivial unit test....!!!
Comment to remind you DateTimeOffSet Video. Cheers.
they shouldve named it timeservice
Yayy new nick upload!
My IClock implementation is much better. Based on an interface, default service calls DateTime.* and if I want, I can TimeTravel in my unit tests in the TestableClock instance. Microsoft did it again, wrong.
Well done, Microsoft.
Oh, inject this, inject that... In a blink of an your constructor becomes total mess
You can always just resolve it using the IServiceProvider when you need it.
Lmao
Use a source generator if this is a great problem for you, or better, split your code better and not create so powerful classes
If your constructor is taking a lot of dependencies, your class is probably doing too much. If your constructor is a mess, that also suggests that the constructor itself is doing too much. Ideally, a constructor should just get the object in a valid state so it can start taking method calls; often that just means assigning the dependencies to fields.
What's wrong with having DateTime as parameter and using DateTime new() or .Parse in test to run it? There you get consistent results. Omg what is this video even about...
ahh I don't like it, IDateTime interface would be much nicer
The more everything become more abstract/interfaces and dependency-injected, the more over-complicated and over-engineered the code seem to me.
Bullshit twice. TimeProvider is just mix everything in single interface, but them should not. Places where you need QPC is strictly not places where you need wall clock and measure units is different.
Im just wondering why u use nsubstitute instead of moq. Thanks for this great video :)