Introducing Swift Service Lifecycle
swift.org
swift.org
I've been reading lots of Swift docs/articles, and made quite a few book purchases from raywenderlich.com and hackingwithswift.com. My "gut feeling" tells me making the investments to become proficient in Swift, and eventually mastering it, will pay off big time.
As a web-focused developer, I must admit I found Objective-C and UIKit intimidating, but with SwiftUI, Apple seems to be lowering barriers to entry; if you know something like Ember, Vue, React, or Angular, you won't struggle too much trying to grok SwiftUI.
With Vapor becoming a mature framework, and Apple giving its official blessing for the development of server-side Swift libraries and tools, it does seem like we may soon reach critical mass on the server, and there is a lot of appeal in being able to consolidate and develop with one language across the stack.
If we can get a Swift-to-Kotlin compiler and a Swift-to-JS compiler (there are already Swift-to-HTML DSLs, and I have been experimenting with a Swift-to-CSS DSL - with my limited proficiency in the language - and it does not seem totally impractical), it's not unreasonable to imagine Swift becoming a "rule them all" language (I remember reading somewhere that Chris Lattner said his goal with Swift was "Total World Domination" and didn't think it was that far off, but can't find the source now).
As for performance, it would be cool if every single thing wasn't behind an atomic reference counter, making it slower than even garbage-collected Go: https://media.ccc.de/v/35c3-9670-safe_and_secure_drivers_in_... (the relevant part starts at 33:06).
Regarding ARC, you don't have to use reference types in Swift, and the community seems to agree that structs are more suitable than classes for most use cases (a SwiftUI app is made of structs that conform to certain protocols, and those structs can be initialized, copied, and "modified" with little overhead).
The cool thing about Swift is that structs can still have methods, computed properties, and custom initializers. So if you're coming from Python or Ruby or Java, or think OOP can help you organize your code, you don't have to throw away everything you've learned in order to be productive and write elegant code (and Swift brings a few new OOP tricks of its own).
They've always provided source compatibility modes in new releases of the compiler so you can delay making syntax changes to an existing codebase if you need to.
You're thinking of ABI stability, which is in place as of Swift 5, and doesn't have anything to do with what parent is talking about.
This hasn't been true for a couple years.
I think it was ATP Podcast
But if you are listening to ATP most of the guest and host aren't really liking swift at all. And prefer to stick to Objective-C for as long as they could.
In someway I could understand that, Swift all of a sudden has 10x increase in complexity compared to Objective-C.
I know these types, and they're extremely frustrating. Swift is superior to Objective-C in just about every way a modern programmer could want.
Reflection and dynamism are fairly big areas where Swift falls short. A couple more: interoperatibility with C++, any form of macro support, ability to shed the runtime where convenient…
The combination of ubiquitous closures and reference counting is dangerous. Avoiding circular references is not nearly as easy as you might think and reference counting is slow (low memory usage is an upside though).
And lately, the language has become rather convoluted. They have added features that make Swift code hard to read. Function builders in particular are a terrible idea. I know many people like internal DSLs. I don't.
I think it's a big mistake to overload the syntax of a language to such a degree that reading a piece of code in isolation tells you very little about what it does, because somewhere far away there may be a mode switch that completely changes the semantics of that piece of code.
Consistency is more important than "looking clean" at all cost.
If I'm promoting a DSL that makes heavy use of something like function builders, I should provide robust documentation so other developers know what to expect. And those developers should, on the other hand, at least skim the docs in order to get a basic understanding of how the DSL works. If someone goes through the trouble of providing docs to accompany a DSL, and a downstream developer doesn't bother to read them, is that really the original developer's fault?
There's clearly a trade-off between expressing a specific task as succinctly as possible and for our knowledge to be transferable between different tasks.
It is the job of a programming language to guarantee a minimum level of transferability while allowing maximum expressivity. To do that, it has to put restrictions on how the semantics of syntax can be redefined.
It's clearly an art to get that balance right. In my view, Swift hasn't got it right and is moving in the wrong direction.
Swift does risk getting carried away and becoming just a safer and faster version of Ruby, but I still think it's too early to write it off just because they introduced some syntactic sugar.
I've said before that writing an import statement never killed anyone. If Swift were to make something like auto-imports mainstream, I would definitely take it as an indication they were going in the wrong direction. But so far that doesn't seem to be the case.
You still need to write the iOS/macOS UI in Swift but you can very easily have your data layer and business logic shared across platforms. I actually like that approach better than other cross-platform solutions since you keep the native platform UI.
Is there a Kotlin-first server-side framework that you can recommend? (I use Java/Spring at work and it's OK, but would prefer to try something else for my side projects)
Edit: if someone doesn't want JVM drama on their servers, how far can they get with Kotlin via LLVM?
As far as I'm aware there's no native server side framework available at the moment, but ktor could potentially support it in the future given the ktor client libraries work on native. You could also use GraalVM native image to build a JVM-free binary of your server, Quarkus has built-in support for it.
FWIW, Kitura is probably dead in the water as IBM has stopped supporting it.
What's the problem with .NET, as it belongs to .NET Foundation now?
The ecosystem looks like a hodgepodge of proprietary, MIT (accompanied by a potentially non-enforceable "patent promise"), and Apache. It's better than what Oracle is doing with Java, but Apple did the right thing and released Swift under Apache.
Yeah, considering that only IBM did an acquisition offer that was quickly withdrawn, Oracle is being really nasty for Java, even Microsoft now contributes to OpenJDK.
Edit: There was no warning that installing the latest "update" to Java would trigger an ultimatum screen, and no way to revert the installation. And as far as I know, there is now no way to download Java from Oracle without accepting the new license terms. It's pretty obvious what Oracle's endgame strategy is.
https://www.oracle.com/technetwork/java/javase/overview/orac...
https://medium.com/@javachampions/java-is-still-free-2-0-0-6...
Finally if you want top of the game JIT, GC, managed runtimes someone has to get the money.
If you are afraid what Oracle might do with Java, better not touch any language handled by Apple, Google, Microsoft, IBM, Intel, SAP, ...
It is not you that they care about, rather their shareholders.
Apple also enjoys making use of their lawyers by the way.
After all, software patents aren't a big deal for most languages. Perhaps excepting Swift, where patents are somewhat of a problem - it's debatable whether a competing implementation would be legal due to Apple's patents:
A lot of people refused to use React because it wasn't clear if Facebook intended to weaponize its patents. After lots of protest, Facebook relented and switched from BSD plus a patent grant to vanilla MIT. It hasn't been established in court if MIT by itself gives you implicit protection against patent litigation, but adding a patent grant that is one-side is, in the opinion of at least a few people on HN, more dangerous than not mentioning patents at all.
The phrasing of the .NET patent promise[0] doesn't seem to have that problem. It might be a bit difficult for people who want to copy and modify the code, since the promise is limited there (only reimplemtations, but I can understand that since they don't want to waive the patents altogether). However, the promise seems fine for users of the framework (IANAL etc. etc.).
[0] https://github.com/dotnet/coreclr/blob/master/PATENTS.TXT
What if MS retracted its promise? Would the retraction be retroactive? A license is usually perpetual and non-revocable, with causes for revocation being written into the license itself (side note: RMS is not infallible, and my zeal for making everything Copyleft has mellowed, but I still find the wording of the GPL to be pure genius).
Has a "patent promise" been tested in court? The GPL has been tested and upheld in some jurisdictions, perhaps most notably in the BusyBox cases: https://en.wikipedia.org/wiki/BusyBox#GPL_lawsuits
Speaking of Apple, given its history it's not impossible to imagine a closed source "Swift 6" with no backward compatibility, leaving only a very tiny ecosystem for the open source Swift.
[0] https://patentlyo.com/patent/2013/01/3rd-circuit-covenant-no...
You still need to read code from somewhere else to know whether it is a variable/field/extension or something. But at least you know it is a 'value', so you can access prop on it or something. You probably don't know the context of a lamba. But you will always at least know it is a lambda, and you can/need return value from it. Important basic information didn't lose under the sugar syntax.
Compares to the groovy. That is literally a nightmare that I never find out what it is doing, am I calling a method or assign something to variable? I really don't know. And I end up gave up and copy build.gradle from someone else.
Swift is not even in the default repositories of most distributions, for instance.
Swift is a very nice language, but one is better served with it if their main market is Apple platforms.
Just like .NET Core, regardless of how much commitment Microsoft is putting into it, remains a subset of the .NET community at large, the so called dark matter developers.
Apple is interested in running Swift on OSX and iOS. Goolge is interested in running Swift on Linux servers to do to Machine Learning.
Windows support has to come from whomever is interested in it. Neither Apple nor Google have a big interest in that.
Same with other stuff. I, for example, am interested in using Swift with GTK+. I don't expect Apple or Google to work on that.
Yet they had enough C++, Android, Python and JavaScript to talk about.
C++, Python, Julia, R own Machine Learning.
I don't miss Swift on Windows, the JVM and .NET stacks offer plenty of choice, including better GPGPU support across multiple OSes.
Yes, but the reality of Open Source is that unless money are paid, it often goes nowhere for big projects (that need lots of work to port/create libs/etc).
The interested party is the one who pays for the development of the feature they want, mostly by paying a developer to do it.
You wrote:
"The nature of Open Source means that any interested party contributes to the project the features it is interested in"
And my comment essentially means:
Yeah, BUT this "nature of Open Source" is just a mere potentiality.
The fact that FOSS allows "any interested party can contribute" means nothing if there's no interested party with deep pockets (or time/skill to contribute).
I was trying to make the point that Swift will be good for the things that the parties who are interested in it need it for. And these interested parties are the deep pockets you are talking about.
We might just be saying the same thing :)
I'm not saying it's the current status quo, but if the server-side Swift community reaches a critical mass where it's easy to get support, and there are plenty of libraries available, it doesn't matter one bit if the iPhone developer community is still 10x larger.
This would be like saying coconut is unsuitable for use in pina colladas because it's much more prevalent as an ingredient in curry.
Anyone betting their money on Server side Swift better have a solid story to sell to upper management, why they did not went with Go, Java, .NET, C++20, Rust, OCaml, .....
Right now the only solid story is for Apple shops to share their client code with the server.
The problem is that if people are only using a language because they have to, then they are not as incentivised to create the open source projects that swift needs. Ruby had a large number of very enthusiastic users, that's what made the difference.
Swift has a very capable standard library, a high-quality, officially supported networking library, and fantastic C and Python interop which can fill a lot of the gaps to the extent they exist.
Even in its current state, I can imagine Swift being productive in something like server-less development, where it would offer a nice strongly typed alternative to scripting languages which currently dominate the space.
Swift has a lot of intrinsic features which would make it nice to use for server-side development, and I'm sure it would find plenty of users if there were a strong success story to point to.
Given the number of users, I'm not convinced the absolute number of Ruby users in 2009 was larger than the number of "swift enthusiasts" today.
I suspect that instead of an enthusiasm gap the greater negative impact on FOSS libraries comes from the Apple-platform dev community being strongly oriented around making consumer-focused programs for money.
Swift has already achieved that, Swift == Apple platforms.
From my perspective Swift is in a trailing group with Go and Rust, chasing C# and Java for new server/service development. Swift is behind, IMO, in supporting server-side development, but ahead in language adoption. That's why the SSWG makes sense.
(Probably C/C++ is used for a lot of new server development too, but I feel that's mostly unassailable, at least directly -- I think that's mostly on-going development in systems with heavy ties to existing C/C++ projects where they've already very seriously considered alternatives and rejected them.)
As someone working on porting “everything” to a decidedly not weird architecture and a very well known operating system, I chuckle a bit because neither language works right now. Not even their dependencies work. It’ll be a while before they will be supported.
(Swift works perfectly, but it would be unfair to compare it because it had a strong investment made in it to work…)
Can you say which ones? It's hard to place your comment without details.
These are the benchmarks for different ARM platforms[2], where I had submitted one for Jetson Nano a year back and now it seems there's one for Apple Silicon.
I'm not telling, no one would ever find cross platform issues with Go; I'm just curious to know what issues you have faced and whether it's because of Apple's extension of ARM instructions.
Apple’s proprietary extensions don’t really affect porting efforts except in one specific case when writing high-performance JITs for language runtimes. (And there is a fairly simple patch to disable this entirely.)
I'm not sure what's preventing you from giving a direct & specific answer. As it would be useful to know where Rust/Go's toolchains fail for using the code for cross - platform applications.
Go team was already working on getting the toolchain to work on darwin/macOS before Apple announcement[1] because GOOS=darwin meant iOS(gomobile) and there are instructions available now[2] to build it successfully before the official patches. Your test results there would be a valuable contribution.
>Some warnings that will probably be problematic at the future related to the ABI defining char to be signed
You mean unsigned char? that's a common hurdle while porting x86 code to ARM.
[1]https://github.com/golang/go/issues/38485
[2]https://gist.github.com/tonistiigi/290d2e7118fe6f581e336bf35...
For instance, GCC is not ready and no one really knows when it will support desktop Darwin on AArch64 (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96168#c6)
Many so-called "cross platform" projects have had big surprises when it actually came time them to be ported to other platforms.
It's extremely rare for a project which has never been compiled and launched on another platform to actually require 0 porting effort for that platform once actually required to run there.
And regarding your porting, Perl, sure, was easy to port. What about CPAN? Want to bet how many Perl libraries will keel over? Same thing for Ruby/gems, Python/pip, etc.
Don't get me wrong, your work is nice, but the people that build on top of your work outnumber you by 2-3-5 orders of magnitude and not all of their porting efforts will be trivial.
Edit: I've checked, none. Most of the Python stuff out there will use at least some.
At least that was how things were around >10 years ago, not sure about the current state of things. Anyone can chime in? Do embedded vendors etc. provide proper forks of newish, modern compilers?
https://www.mikroe.com/compilers
https://www.astrobe.com/default.htm
https://www.ptc.com/en/products/developer-tools/apexada
If you add third-party ports and implementations, the list of platforms supported by Go and Rust increases exponentially; see for instance Tiny Go and the ongoing port of Rust to the Xtensa-based ESP32.
> Anyone can chime in?
I work in embedded and as far as my experience goes nowadays unless you go on extremely limited environments, the embedded chips I mostly see or develop for are either ARM (v7, like stuff from Nordic or the STM), or ESP32 (Xtensa). Every once in a while I have to work on some older projects which were based on Atmel or PIC, or very very very rarely MIPS.
It's certainly not like it was before; nowadays you can buy chips like the ESP32-WROVER which have relatively lots of RAM and storage for an absurdly cheap price. They run pretty well even if you opt for using C++17 and complex libraries.
Startup workflow is important, and it is nice to have an abstraction that makes it easier.
I am less convinced that shutdown workflow is important, and may be more trouble than it is worth. On modern operating systems, the OS will handle process shutdown and clean up system resources such as file descriptors etc. In addition, with things like the OOM killer, etc, the process may not have a chance to actually clean up. Trying to engineer graceful shutdowns is extra code with subtle edge cases (like circular dependencies), and generally, less well tested and exercised. Finally, the operating system needs to be robust against leaking resources due to processes crashing, anyway. So on the balance, I think it is worthwhile to do a startup workflow and engineer your service so that you can always crash safely without messing up your system or leaking resources.
Imagining you have one service instance need to shutdown for either migration or maintaince, it is just a bit nicer to report to your service discovery manager that this instance will go offline.
While service discovery manager will eventually figure it out by its own through heartbeat monitoring, proactively notifying the service discovery manager would reduce a little bit on the failed retries etc.
Thus avoiding shutdown logic is sloppy engineering to say the least. Same for ignoring the need to design the system to avoid crashes to begin with, including OOM ones.
This has nothing to do with ensuring your system is OK on crash, which is another side of robustness.
Now if the error cause has led to an endless crash cycle, then not.
That said, I still see the value of doing graceful shutdowns.
A communication channel which survives a process exit is fine as long as the next process start can pick it up again. You can do that with the SysV things and named pipes.
Of course, you can also not do that - i remember the first program i wrote to play with SysV message queues created a fresh private queue each time, and didn't delete it on exit, so i ended up with piles of anonymous queues i couldn't delete. I had to go and cry to a system administrator who knew how to get rid of them.
Yes, you need to engineer for the crash scenario, but you shouldn't be relying on that in the same way you shouldn't tell users the only way to stop your software is to `kill -9 [PID]`.
In a normal deployment it might be useful to use shutdown parts of code to signal to orchestrators that the operation has been completed successfully so they can take further steps, for example.
Everybody's circumstance is different, but I definitely recommend thinking more about shutdown workflows.
You have this exactly backwards. If your software crashes rarely, you have a problem - when it does crash. Because then it's doing something you aren't routinely and thoroughly testing by doing it all the time.
This is an old, counter-intuitive, but powerful idea - if you're not familiar with it, start with this paper:
But in scenarios where you want/need to avoid service interruptions that's not good. The basic scenario is when you have an instance of your service you want to shut down for whatever reason (maintenance, update): (1) start a new instance of your service; (2) route requests to the new instance; (3) shutdown the old instance.
In (3) you'd prefer not to just kill any requests in-progress. It's also nice to flush write-buffers (can be used for high-write-frequency but not critical data -- perhaps stats collection or other informational data).
I'd definitely keep shutdown simple, but you don't need to go without.
Tom Doron is a member of the Swift Core Team and the Swift Server Work Group. He manages a team working on server-side Swift libraries at Apple.
Server Side Swift ? At Apple?
I thought IBM gave up on working Server Side Swift and that was it.
As an iOS developer I'm really excited to use Swift more and more outside of app development.
edit: to clarify a bit more, I think Apple's vision is a lot more than just being able to build a small web app in Swift. They really want to build _everything_ with it.
Google is pretty much Java and C++ alongside their infrastructure, and OSes.
K8s prototype was started in Java and migrated to Go after some Go aficionados joined the team.
Besides k8s, you have Google download service (because someone from Go team bothered to port the service to Go), gVisor, parts of Android GAPI, the new internal Android build system, gVisor, and Fuchsia TCP/IP stack that apparently should be rewritten in C++/Rust.
And that is about it, as much as it comes outside.
That makes sense to me, though I see the risk. There's a big benefit to the community as a whole if standard concerns are handled in a common: developers will become experienced with them and understand them in deep ways. Tooling can target them. Documentation and other learning materials can become wide and deep.
The risk is that potentially better approaches have a very high hurdle to overcome the "official blessing" to become more than a niche option. That's good and fine for alternatives that are only incrementally better or better in some ways worse in others. But sometimes a significantly lacking "official" approach holds back an overwhelmingly superior non-official approach. Hopefully the Swift Server Work Group will keep that from happening or at least not for too long.