Update to swift package init templates

Perhaps this is because I'm an existing user but the argument that looking two directories deep is heavy doesn't resonate with me. The user is already invoking swift package init from the command line so they must be at least reasonably comfortable using the command line and navigating file hierarchies; navigating one level deeper to find source files doesn't seem like a big stretch.

As mentioned above (and by others) the issue with the current template for executables and tools make it difficult to add more targets. It biases too heavily towards new users at the expense of additional burden for existing users who are likely to add additional targets (it's common to start with an executable and end up with an executable depending on a library and tests for the library).

I think you're right to explore different layouts, so what if we inverted the target and purpose? For a library this would be:

.
├── Package.swift
└── SomeLibrary
    ├── Sources
    │   └── SomeLibrary.swift
    └── Tests
        └── SomeLibraryTests.swift

For executables and tools the template could elide the 'purpose' (i.e. Sources/Tests) and the entry point would be one-level deep. Adding new targets later would not add burden as they would be at the top-level.

.
├── Package.swift
├── SomeExecutable
│   └── main.swift
└── SomeLibrary
    ├── Sources
    │   └── SomeLibrary.swift
    └── Tests
        └── SomeLibraryTests.swift
1 Like

The Vapor Toolbox provides an interactive experience for creating new projects if you want to take a look at some inspiration!

3 Likes

Apologies for the slower reply - I wanted to step back a bit and do another round of self-evaluation on if I was reacting to "I don't like the suggested change because it's different" vs. "I don't like the suggested change because it's not as good for some reason". Which begs the question of what that reason is, if that's the case.

Partially, I'm right in line with @georgebarnett in my perception that two levels of directories makes for a burdensome concept for new developers, but since I've been programming for quite a few years, I have to acknowledge that I'm not anywhere near that starting point - either with programming in general, or with Swift.

But history is also something I don't think you can ignore - especially when new developers are (hopefully) going to be interacting with developers who've been here and while, and have that inherent expectation of structure. And along those lines, for better or worse, SwiftPM's fundamental structure is aligned quite strictly with targets. Because of that, making a simplified use case that hides that scenario (which your suggested change does, and quite nicely) I think is actually doing a disservice. But that's also partially based on my cost/reward evaluation that two directories isn't that much. What I see as the value is an implicit affordance that there is more complexity there. Because a template sets up the directories, you don't need to immediately engage with it other than to navigate down one more directory if you're clicking through folders, or opening another directory in a UI - although VSCode notably hides even that from you. In return, you're getting a clear hint that there's a bigger structure available here for when you want to expand, and its pattern is likewise clear.

I haven't seen ./Previews at the top level of such a structure myself, but I do have ./Snippets now that the feature is functionally available in 5.8 - so I end up with a directory structure for most of my work that looks like:

Package.swift
README (and other misc files)
Tests/
   ATarget/
Sources/
  ATarget/
Snippets/
  SnippetExample1
  SnippetExample2

It's not a far stretch to imagine this kind of layout once you've seen it for an expanded structure, but if you're only ever seeing the top level without anything else, it's not clear where you should expand. I would think it just as likely to see someone reach for the pattern of:

Package.swift
Sources/
OtherSources/
Tests/
OtherTests/

The structure of the directories ends up providing a sort of guard rails to where you're going to expand - at least in such a way that you don't get the "SwiftPM warnings you're holding it wrong" scenario, which I see as valuable.

Just to add more noise to the signal...

If the aim is to help people new to SPM, how about another, extra option:
swift package init --type tutorial

Which could generate a sample package which was even more heavily annotated with comments which explain exactly what each part does and how they interact. There could also be non-compilable files in the package explaining the folder layout. e.g.

/Sources/AboutTheSourcesFolder.txt 
/Tests/AboutTheTestsFolder.txt 
/Snippets/AboutTheSnippetsFolder.txt 
etc...

This example package would have a main executable target.

The executable would have a dependency from the internet (say the SPM 'Deck of Cards' example package.)

The package would also have a very simple library target (also a dependency of the main executable target) perhaps a library that vends card dealing functions.

Again, all heavily commented explaining that these elements are not compulsory but this is how it's done.

The package should have a good README, rather than a placeholder.

1 Like