Introducing "Time"

I've frequently used now or today as variable names when getting the current time. So makes sense to me for that to be a method name also.

1 Like

Great work, this looks awesome @davedelong. Just a few comments

  • this hogs the Time module name, ie. it'll clash with anything that has a module called Time, exported, not exported, private, public, .... Similarly, it takes the time URL component and the Time package name, all of those have to be unique in a whole package graph as of today :frowning:. This package will probably be in conflict with many other packages revealed in this github search. For the SSWG we therefore require some uniqueness, see for example here.
  • Time exports public types like Value, I'd probably recommend prefixing at least Value because it's such a generic name
  • For your own benefit, I would recommend not making your Error types public enums. The language dialect that is used in Swift packages means that all enums are exhaustive so won't be able to add an enum case without making a new major SemVer version :frowning:. We messed that up in SwiftNIO and are suffering quite frequently, we intend to fix this for NIO 3 which is a long time out though. I'd recommend using public struct SomethingError like in this example assuming you don't need associated values. If you do need associated values, then your best shot is probably creating public enum TimeErrors {} and nesting all errors as types in there?
  • regarding public API of a package that I'd expect to be widely used, you might want to check the SwiftNIO docs regarding public API, maybe you get some inspiration.
6 Likes

Hi @johannesweiss, thanks for taking the time (haha) to write this up.

I'm not sure what you mean about the time URL component. Would you mind explaining that a bit more? There's nothing about URL components in my package.

At first glance those results look super intimidating. Over 360 distinct matches in Swift files alone!

So, I went through every single one, and found that there are generously 8 other public packages called "Time", not including my own:

All other results were either the occasional reference to one of these repos (usually by the same author), or they were usages of the word "time" inside a file that matched the name "*Package*.swift", such as someone using a TimeInterval in their WorkPackageViewController.swift.

@dreymonde's package is one that I actually listed as helping to inspire my own work. It's also the only other package that (I believe) would stand any sort of chance of causing conflicts with mine. While Github Stars aren't a perfect representation of usage, they are a pretty decent proxy for it.

My takeaway from this is that the search results look intimidating at first, but I don't think my package being named "Time" will end up being much of an issue at all.

If someone has a type named Time that they're using, they'll need to deal with that in the same way that we already have to deal with other naming conflicts, and that's to prefix them with a module name. Again, I don't see this as terribly onerous.

Yeah, definitely. Renaming Value is one of my "must do" tasks before declaring a 1.0 version. I've been thinking about some alternatives.

Excellent point. I've filed an issue to change them to structs. I'm a huge proponent of "Not Using Enums™", and I'm surprised that I missed this one.

Thanks! I'll give it a read and digest it before tagging a 1.0.0 release.

1 Like

Regarding the module name collision, personally I'd prefer them to collide. A project should not be using two separate time modules, and would likely have more problems using both at the same time than not.

3 Likes

In this simple example, maybe. But if a package has two dependencies, and both use (different) time packages for internal calculations, it would be annoying to have to fork and change the name in one of them, just to get it to compile. I've had that happen before (though in my case with a module named HTTP) and it was pretty annoying. Remember you will have to fork both your direct dependency to change the url of the time package it depends on as well as the time package to change whatever names you must.

The whole situation with module and package names needing to be globally unique kind of sucks (not even mentioning having multiple versions of the same package), but for now prefixing things like everyone did in ObjC seems to be the only real way out.

2 Likes

I do understand there needs to be a general solution for that. I'm simply referring to time-related utilities, which you likely don't want to have multiples of in your project.

To suggest a solution to the issue you raised, you can also create an internal module that imports only one of the problem modules. From there you can export the symbols as part of that new Module. Here's an example:

A bit cumbersome, but it lets you avoid having to fork the dependency.

1 Like

The problem is the dependency that you can’t control. Like other people’s project.

Hi @davedelong,

Thanks very much for the in-depth answer!

At this moment (I think there's a fix in the working), a package is uniquely identified by its package name (in Package.swift) as well as by the basename of the URL where SwiftPM clones the package from. Ie. in https://github.com/davedelong/time, time must be unique across the whole package graph (it does strip the .git that's optionally there, so basically https://github.com/davedelong/time == https://github.com/somewhereelse/time.git == git@github.com:davedelong/time.git).

Thanks for actually thoroughly checking this. I agree that all of those seem to have a low number of stars and therefore are unlikely to clash, however it's not unique. It's totally your call to decide if that's fine. The SwiftPM Library does list two times already, @dreymonde and yours. CC @daveverwer on what your intended plan is with conflicting package names, just let them conflict or try to only have one at a time?

Again, probably fine. I guess I've seen to many clashes that were very hard to resolve that my alarm bells go off (maybe a bit too much) if I see a package called time with a module named Time :slight_smile:.

1 Like

No plan for conflicting package names, just let them conflict. The unique identifier for the SwiftPM Library is the repository URL.

1 Like

You can create that intermediate module in your own project.