We have some exciting news to share about the future of Foundation. As announced at ServerSide.swift and on the Swift blog we are embarking on a project to create a unified implementation of Foundation, written in Swift, for all platforms.
An important part of our vision is to provide the option of smaller, more granular modules for server side apps.
I'd like to kick off some discussion about the project by walking through a breakdown of which types should appear in which modules.
Module Breakdown
Below is a preliminary proposal of where we think the best separation lines are. This is not a final list -- we are seeking community input to the process.
FoundationEssentials
These types are useful in most applications and have no additional system dependencies. This package may choose to rely on key Swift packages like Collections or Algorithms, but each new dependency will be added only after careful consideration of the tradeoff to the overall size of Essentials. This module contains types which advance the overall mission of Foundation as a library for providing basic utility classes, setting precedent for design patterns, and providing a level of OS independence to enhance portability.
URL
Data
UUID
-
Date
,DateInterval
-
PropertyListSerialization
,JSONSerialization
-
PropertyListDecoder
,JSONDecoder
and encoders NotificationCenter
AttributedString
SortDescriptor
-
Measurement
,Dimension
,Unit
ProcessInfo
-
UserDefaults
(scope may be limited, e.g. to certain kinds of domains) -
FileManager
,FileHandle
,Process
,Pipe
Bundle
Some of these API deserve a new look due to advances in the language since they were introduced. For example, we think API like Process
should adopt async/await. By including them in the Essentials package, we hope we can work with the community to advance the API together. In the short term, the existing API is still useful for many projects that depend on it.
FoundationInternationalization
These types are useful for working with dates and times or formatting data for user presentation.
-
FormatStyle
protocol and all of concrete format style types -
Locale
,Calendar
,TimeZone
,DateComponents
-
Locale
-specificString
extensions -
CharacterSet
(This API may be redesigned or augmented in the future to better fit with SwiftString
) URLResource
LocalizedError
Morphology
FoundationNetworking
The FoundationNetworking module has already been split off from Foundation. It will continue to provide the same networking API. Unifying this implementation in Swift is a highly desired future direction after we stabilize the essential types, especially URL
.
-
URLSession
,URLRequest
,URLResponse
, other associated types -
HTTPCookie
,HTTPURLResponse
, other associated types
FoundationXML
The FoundationXML module has already been split off from Foundation. It will continue to provide the same XML parsing API. Unifying this implementation in Swift is a future direction after we stabilize the essential types and FoundationNetworking.
XMLDocument
XMLDTD
XMLDTDNode
XMLElement
XMLNode
XMLParser
FoundationObjCCompatibility
These types are useful for cross-compilation with Darwin Foundation or legacy code.
NSObject
-
NSValue
,NSNumber
NSError
NSNull
- Geometry types,
NS/CGRect
,NS/CGPoint
,NSEdgeInsets
, etc.
Micromodules vs Monoliths
A frequently asked question is: why don't we split each type in Foundation into a separate package, so they can be imported independently? We believe the right answer is a balance between individual types in independent modules and one large module with everything.
In a system with each component as a separate module, the number of relationships between the modules can grow rapidly. Each interface between the modules must be stable, and public. This can inadvertently tie our hands for future improvements to the API surface as a whole, when we find that an interface we thought was just for a "friend" module is actually used elsewhere.
Instead, we choose to divide the modules by external dependencies. External dependencies are typically where significant binary size growth comes from, and lack of control over the transitive dependencies can cause conflicts for downstream clients.
Removed types
On Darwin platforms, we are required to maintain compatibility for all existing API surfaces. However, we choose to focus our new unified implementation on the most useful Swift APIs. This is a shift from swift-corelibs-foundation's goal of 100% source compatibility. Many of Foundation's features have been subsumed by direct support in the language. These types are currently not planned to be brought forward into the new package:
-
RunLoop
,Lock
,OperationQueue
,Stream
,Port
,Timer
etc. - replaced by structured concurrency - NS-prefix collection types - originally provided for compatibility, but utility has been very small
-
NSCoding
,NSKeyedArchiver
- replaced byCodable
. -
Progress
- No external dependencies, but intersection with structured concurrency has not yet been fully designed.
On Darwin, the Foundation framework will continue to maintain implementations for these types in a combination of C, Objective-C and Swift.
Future discussions
We hope this is just the start of discussions about this exciting new project. In future posts, we want to discuss plans for the existing swift-corelibs-foundation project and figure out how we transition the ecosystem to the new unified implementation.