# Should I divide my code's components into targets or packages?

**URL:** <https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179>\
**Category:** Using Swift\
**Tags:** packagemanager, module, framework, library\
**Created:** [July 1, 2021, 9:59pm UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179 "2021-07-01T21:59:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [July 1, 2021, 9:59pm UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/1 "2021-07-01T21:59:08Z")

</div>

In this thread, Jeremy David Giesbrecht (@SDGGiesbrecht) did a great breakdown of the difference between SPM's targets and modules:

> [@Module vs Product vs Target](https://forums.swift.org/t/module-vs-product-vs-target/27640/2):
>
> Here is my understanding: module: A group of interrelated sources intended to always be built together. (cf. whole module optimization). This is what is referenced when you import MyModule, and when you use its name for disambiguating a symbol: MyModule.Data vs Foundation.Data. In general English, a module is “one of a set of standardized parts or independent units that can be used to construct a more complex structure” target: A unit of the build result; a particular thing you might aim …

Having understood that, I'm still not sure how to apply those definitions towards structuring my code. My codebase has been growing, and I'm looking to modularize it and get more serious about enforcing architectural boundaries. I have several different components I've identified:

1. UI helpers (UI code that could be reused in other apps)
2. UI (UI code that's fairly specific to my one app, often a concrete use of the helpers in #1)
3. System utilities, extensions/wrappers to platform features, etc.
4. Several networking "gateways" that wrap third party web APIs
5. A datastore service that isolates
6. Generic data structures/algorithms

And so on, you get the point.

Ultimately, these will all be used by my one Mac App, but I would still like to enforce clean interfaces around them, so I can reduce some of the interdependence (a fancy word for spaghetti code 🍝). In a sense, I'm trying to get back some of the access control that Java packages got me used to.

Should "components" like these be targets within one package, or independent packages (each with one target)?

---

<div class="post-metadata">

**Author:** ![SDGGiesbrecht](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sdggiesbrecht/32/4768_2.png) [@SDGGiesbrecht](https://forums.swift.org/u/SDGGiesbrecht)\
**Post date:** [July 1, 2021, 10:35pm UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/2 "2021-07-01T22:35:00Z")

</div>

Here is an attempt to summarize various answers I have given across the forums in the past few months. (Search for any of the terms along with my handle and you will get plenty of hits with more details.)

- What group of functionality do I want versioned together? → That’s a good candidate for a package, which is fundamentally about versioning and API stability.
- What group of functionality do I want to be able to individually resolve and fetch? Do I need a unit I can vend outside SwiftPM (dynamic library, executable)? → That’s a good candidate for a product, which is fundamentally about resolution and skipping dead code.
- What group of functionality do I want to be able to `import` as a single statement? Is backdoor `internal` interaction between its components necessary? → That’s a good candidate for a target, which is fundamentally about importing and access control.

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [July 1, 2021, 11:45pm UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/3 "2021-07-01T23:45:37Z")

</div>

Hi Jeremy, fancy seeing you here! Thanks for taking the time to help me out.

From everything I've read thus far, my overall inclination is towards having one package, with multiple products, each with one main target (and a test target, optionally a UI test target, etc.). I'll describe my rationale below. Could you let me know if it sounds reasonable?

* * *

> [@SDGGiesbrecht](#):
>
> What group of functionality do I want versioned together? → That’s a good candidate for a package, which is fundamentally about versioning and API stability.

I guess in some sense, there's no real versioning beyond the git commit sha. E.g. I don't intended to bump the semantic versioning numbers with every feature or code change I make, since the sole intended consumer of these components is the main app that glues them together (which resides in the same repo). If I'm not mistaken, that points me away from the need to have multiple packages.

> [@SDGGiesbrecht](#):
>
> What group of functionality do I want to be able to individually resolve and fetch? Do I need a unit I can vend outside SwiftPM (dynamic library, executable)? → That’s a good candidate for a product, which is fundamentally about resolution and skipping dead code.

Ah products. I forgot to mention those in my post. From what I gather, dependency resolution and fetching is done on a package as a whole. I.e. you can't cherry pick a single products' source files out of a package. For that, you would promote the product into its own new swift package. Is that correct?

> [@SDGGiesbrecht](#):
>
> What group of functionality do I want to be able to `import` as a single statement?

I'm not sure, that sounds like a style/best-practice thing, and I don't know what the current convention is. Do I want:

```swift
import MyAppAllTheThings

```

or...

```swift
import MyAppNetworking
import MyAppCollections
import MyAppUtils
// and so on...

```

🤔

There's some "components" (my generic term for my yet-undecided unit of modularity) that seem reasonably reusable (utils, collections, algorithms, Swifty wrappers around old APIs, etc.), and some that are intentionally quite specific to the particular app (UIs, data models, etc.)

If I go with "1 package, multiple products" today, and I decide in the future that I want to reuse some library (e.g. `MyAppUtils`) in other projects, I can just promote that product into new a package, and all my existing sources wont' need to be changed, since they already had `import MyAppUtils`.

> [@SDGGiesbrecht](#):
>
> Is backdoor `internal` interaction between its components necessary?

That seems undesirable to me. Using `internal` APIs of another component is basically subverting the explicit dependency boundaries I'm trying to establish. Right?

---

<div class="post-metadata">

**Author:** ![SDGGiesbrecht](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sdggiesbrecht/32/4768_2.png) [@SDGGiesbrecht](https://forums.swift.org/u/SDGGiesbrecht)\
**Post date:** [July 2, 2021, 2:06am UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/4 "2021-07-02T02:06:55Z")

</div>

> [@AlexanderM](#):
>
> If I'm not mistaken, that points me away from the need to have multiple packages.

Yes, in your case, I don’t see any good reason for having multiple packages. (In fact it would likely be a real pain; update something at the bottom, and everything above it needs to separately update the hash it is pointing to.)

> [@AlexanderM](#):
>
> From what I gather, dependency resolution and fetching is done on a package as a whole. I.e. you can't cherry pick a single products' source files out of a package.

SwiftPM checks out the entire repository, but then it tries hard to _skip subdependencies_ the product doesn’t need. (Its actual ability to identify skippables still isn’t perfect, but has been improving over Swift releases.)

> [@AlexanderM](#):
>
> I'm not sure, that sounds like a style/best-practice thing, and I don't know what the current convention is.

In my experience, there is a tug‐of‐war between various clients. Some are more annoyed by building and importing way more than they need, others are more annoyed by having to write many import statements. Finding the right balance requires spending time writing client code to experience the tension for yourself.

> [@AlexanderM](#):
>
> If I go with "1 package, multiple products" today, and I decide in the future that I want to reuse some library (e.g. `MyAppUtils` ) in other projects, I can just promote that product into new a package, and all my existing sources wont' need to be changed, since they already had `import MyAppUtils` .

Correct. And this is my recommendation from what you have said.

> [@AlexanderM](#):
>
> That seems undesirable to me. Using `internal` APIs of another component is basically subverting the explicit dependency boundaries I'm trying to establish. Right?

What I meant by that was simply that where such a boundary would be inappropriate to impose, then don’t impose it, and keep both “sides” in the same target. The presence of `internal` (as opposed to `private` or `public`) is your primary cue that a boundary might be inappropriate. When you upgrade `internal` to `public` just to stretch something across a such boundary, it also grants access to clients, spilling aspects of your implementation into the API. There is no access control level that grants access to other modules in the same package while withholding access from clients of the package.

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [July 2, 2021, 2:23am UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/5 "2021-07-02T02:23:59Z")

</div>

Very clear response. No further questions.

Thanks so much!

---

<div class="post-metadata">

**Author:** ![AlexanderM](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alexanderm/32/9781_2.png) [@AlexanderM](https://forums.swift.org/u/AlexanderM)\
**Post date:** [July 9, 2021, 9:06pm UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/6 "2021-07-09T21:06:19Z")

</div>

Thought it might be useful to future readers to post an update on what I ended up doing

Here's my structure (in terms of packages/products/targets, not the file hierarchy):

```swift
Foo Xcode Workspace
├── 🛠 Foo app Xcode project
├── 📦 FooShell Swift Package
│ └── 🏛 FooShell library product
│ └── 🎯 FooShell target
└── 📦 FooComponents Swift Package
    ├── 🏛 FooCore library product
    │ └── 🎯 FooCore target
    ├── 🏛 FooUtils library product
    │ └── 🎯 FooUtils target
    └── ... and so on

```

I wanted to make `FooShell` (which contains all my storyboards, view controllers, etc.) into just another library product under the FooComponents package. But, it appears that [you can't specify platform requirements on a per-product or per-target basis](https://forums.swift.org/t/platform-per-target/29253), so I ended up needing to split it off into its own Swift package.

In `FooShell`, I imported `FooComponents` as a local dependency:

```swift
//...
dependencies: [
	.package(path: "../GizmoComponents"),
],
targets: [
	 .target(
		name: "GizmoShell",
		dependencies: [
			.product(name: "GizmoCore", package: "GizmoComponents"),
   	 ]
	),
   //...
],
//...

```

---

<div class="post-metadata">

**Author:** ![rayx](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rayx/32/12204_2.png) [@rayx](https://forums.swift.org/u/rayx)\
**Post date:** [July 10, 2021, 6:59am UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/7 "2021-07-10T06:59:46Z")

</div>

> [@SDGGiesbrecht](#):
>
> > [@AlexanderM](#):
> >
> > If I'm not mistaken, that points me away from the need to have multiple packages.
> 
> Yes, in your case, I don’t see any good reason for having multiple packages. (In fact it would likely be a real pain; update something at the bottom, and everything above it needs to separately update the hash it is pointing to.)

I'm also in the progress of modularizing my app's code. I don't have much experience with SwiftPM, but I find this approach works for me: creating a stand-alone swift package for each component outside the app's project folder, then importing those components by using Swift local package support. That avoids the hassle Jeremy mentioned.

---

<div class="post-metadata">

**Author:** ![SDGGiesbrecht](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/sdggiesbrecht/32/4768_2.png) [@SDGGiesbrecht](https://forums.swift.org/u/SDGGiesbrecht)\
**Post date:** [July 10, 2021, 7:22am UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/8 "2021-07-10T07:22:34Z")

</div>

If you do that, nothing is pinned, so it is very easy to get pieces out of sync with one another and end up with stuff broken downstream (unless you make sure a single top‐level package depends on absolutely everything—even tests—and you only ever make changes with that package open).

---

<div class="post-metadata">

**Author:** ![rayx](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/rayx/32/12204_2.png) [@rayx](https://forums.swift.org/u/rayx)\
**Post date:** [July 10, 2021, 7:31am UTC](https://forums.swift.org/t/should-i-divide-my-codes-components-into-targets-or-packages/50179/9 "2021-07-10T07:31:40Z")

</div>

Understood. I agree it doesn't scale. It's not a good approach for team based distributed development. But in my case they are all components of a set of apps (a GUI app and perhaps a command line app in future). So it's relatively easy to do the verification. When the app has multiple different versions, I may need a better way for version control.
