artsy / README

:wave: - The documentation for being an Artsy Engineer
Creative Commons Attribution 4.0 International
1.1k stars 120 forks source link

RFC: Adopt Swift for new native feature work over Objective-C #426

Closed brainbicycle closed 2 years ago

brainbicycle commented 2 years ago

Proposal:

Adopt Swift over Objective-C for the fairly narrow but important use case of native features that cannot be written in react native or cannot be written in react-native without compromising user experience.

Major caveat: we should still prefer react-native whenever possible.

Reasoning:

Reasons for preferring swift for native iOS feature development over Objective-C:

Reasons in the past for not adopting Swift over Objective-C:

Additional Context and Considerations:

Retro of Swift at Artsy in 2017:

https://artsy.github.io/blog/2017/02/05/Retrospective-Swift-at-Artsy/

Objective-C isn't dead!:

I am not proposing rewriting existing features now written in Objective-C that work to Swift. Simply that we prefer Swift when possible for new native features. Gradually if we find it beneficial or need to refactor old components we can adopt Swift then.

React native bridging code is recommended by the docs to be in Objective-C, we should stick with what the docs suggest here but this should generally be a fairly thin layer of functions exposed to react-native and any major functionality can be called via these functions in Swift code.

Mobile stack preference in order should this RFC be accepted:

@pvinis put succinctly below

  1. React Native whenever possible, e.g the vast majority of mobile feature work should be react native
  2. Swift when we need to write native features or react-native doesn't support the UX we want
  3. Objective-C for glue code like bridging between react-native and native code

Why not Assess then Adopt?

Swift is already in use by many companies in production, in fact we are already using it in production for Live Auctions, Folio and soon the Artsy Widget, so this is more to get alignment with how we think about preferences than to assess if Swift is production ready.

How this RFC is resolved:

I'll collect feedback on this RFC from the team for a week, interested especially in hearing from anyone who works in Eigen regularly or would like to. We'll consider this RFC approved if 50% of the engineering team actively approves of this change or there are no major objections that require. Add a 👍 or 👎 reaction to this proposal to vote.

brainbicycle commented 2 years ago

Writing up this argument and it feels like an RFC, so I think I should make an RFC instead.

pvinis commented 2 years ago

I'm for it. swift for native. objc for glue code. or fast/small things.

jonallured commented 2 years ago

I mean this could be the RFC, right?

MounirDhahri commented 2 years ago

I'm up for this 👍.

Swift compilation is slow

I also tried building Eigen again by making small changes to the Objective-C code and Swift code and didn't see much difference

https://user-images.githubusercontent.com/11945712/142828593-ef4ae99b-acbc-445a-8423-0db86e30a2ef.mp4


I only have one comment about this:

React native bridging code is recommended by the docs to be in Objective-C, we should stick with what the docs suggest here but this should generally be a fairly thin layer of functions exposed to react-native and any major functionality can be called via these functions in Swift code.

The latest versions of react-native no longer recommend using Objective-C and are also specifying steps to bridge Swift code to React-native

kathytafel commented 2 years ago

My thoughts in no particular order:

jo-rs commented 2 years ago

(I don't know if there's a similar resolution for the Android side of things, but if there isn't: Kotlin over Java? 😬 😇 )

joeyAghion commented 2 years ago

I'll leave a few reactions since this is assigned to me, but then I'd defer to others in the Mobile practice to ultimately yea or nay.

Swift is what Apple's docs, development and guidelines prefer... in general the iOS communities knowledge base has largely moved to Swift.

This ☝️ is very compelling.

React native bridging code is recommended by the docs to be in Objective-C

I don't understand the subtleties between (1) bridging and (2) code that must be native and (3) the rest (which is hopefully React Native). It bothers me that there are 3 choices though! Maybe @MounirDhahri's point indicates there'll be just 2 good choices soon?

I am not proposing rewriting existing features now written in Objective-C that work to Swift. Simply that we prefer Swift when possible for new native features.

This means there'd continue to be Objective-C in the codebase for a long time. This might be fine if they're out of the way, but if they need maintenance and fixes, it might be good to either purposefully migrate them or have a heuristic for when they're worth rewriting.

brainbicycle commented 2 years ago
  • 100% disagree that you need to get into a language holy war over SmallTalk message sending, and type + null safety, but maybe that's because I got a lecture on dynamic runtime binding by the person at NeXT who brokered the deal with Apple and it's still part of the thought process of the operating system. Like is NSObject going away anytime soon? Are the fundamentals of how you do anything in swift really that far off from NSObject. You need to make a hash and isEqual and that comes from the origins. And hey now there's nullability in ObjC. But basically my point is the language features are not what would decide this for me. Because what about Ruby on the backend? Personally I really like duck typing. Having said that, you can turn off all the included pods that do swizzling and I wouldn't cry.
  • The language isn't going to help you reason about concurrency, you still need to know how to use it. If you don't understand threads, you'll probably run into problems.

Definitely not my intention to start a language holy war! I still very much like Objective-C and I agree that language features are less compelling reasons than the others I was only trying to make a few points which are perhaps still opinionated: 1) Swift is more approachable for beginners because it has more familiar syntax to most other modern languages 2) Swifts typing is closer to our philosophy around front-end code and typing then Objective-C, e.g. our reasons for adopting typescript: https://artsy.github.io/blog/2019/04/05/omakase-typescript/

Ruby backend is a good counterpoint but type annotation is now here for Ruby and I wouldn't be surprised if we adopted it as an org one day. https://www.honeybadger.io/blog/ruby-rbs-type-annotation/

When I mentioned null safety I was thinking specifically about if let..etc and the language forcing you to handle null cases, I realize Objective-C has annotations for this but you can leave out by default for code you write as far as I know.

On concurrency I agree language features are not a substitute for understanding but can make code more legible and harder to shoot yourself in the foot.

That said very much agree this is the less compelling point for the argument and perhaps the main point for me is the community now mostly using Swift.

brainbicycle commented 2 years ago

The latest versions of react-native no longer recommend using Objective-C and are also specifying steps to bridge Swift code to React-native

Awesome I was totally unaware of this, it looks like there is some extra boilerplate with Swift export and a bridging file but I wonder if we could use some code-gen tooling to make this easier.

pvinis commented 2 years ago

Awesome I was totally unaware of this, it looks like there is some extra boilerplate with Swift export and a bridging file but I wonder if we could use some code-gen tooling to make this easier.

Definitely something we could mess around with in MP 👍.

brainbicycle commented 2 years ago

React native bridging code is recommended by the docs to be in Objective-C

I don't understand the subtleties between (1) bridging and (2) code that must be native and (3) the rest (which is hopefully React Native). It bothers me that there are 3 choices though! Maybe @MounirDhahri's point indicates there'll be just 2 good choices soon?

The bridging code is essentially a small amount of code we need when we need to talk to native (Objective-C, Java, Swift, Kotlin) code that exposes functions we can call from typescript. It is kind of boilerplate and generally just a few functions that call into some more complex native code. It looks like from @MounirDhahri comment that we can minimize the Objective-C even more which is great and we should do if we can. But I think we still need to have some small amount of Objective-C, I don't know exactly how react-native bridging works but I am guessing this is because react-native leverages some of the dynamic language features of Objective-C to expose the methods to javascript. Short version, yes ideally we would have only 2 choices e.g. use Swift and React-Native, but we are constrained by what react-native supports for this bridging code, but also don't think this is a huge deal because it is pretty well documented how to create this bridge code.

For native code, I am thinking of complex features or features that react-native doesn't support easily. In the past, AR/VR which might remain native code, new iOS capabilities like accessing photos in sandboxed photo picker that wasn't yet supported by react-native libraries.

brainbicycle commented 2 years ago

I am not proposing rewriting existing features now written in Objective-C that work to Swift. Simply that we prefer Swift when possible for new native features.

This means there'd continue to be Objective-C in the codebase for a long time. This might be fine if they're out of the way, but if they need maintenance and fixes, it might be good to either purposefully migrate them or have a heuristic for when they're worth rewriting.

It is a fair point, so far we have not really been bitten by this but I could definitely see it happening in the future, a lot of the Objective-C stuff, (Deep Zoom, View In Room, ~Live Auctions~ edit: Live Auctions is Swift) has kind of worked fairly reliably with some minimal fixes here and there. I think one logical point to reevaluate if it is worth rewriting in Swift, or better porting to RN, is when we want to bring the feature to Android or we want to add some major functionality to the code.

kathytafel commented 2 years ago

a lot of the Objective-C stuff, (Deep Zoom, View In Room, Live Auctions) has kind of worked fairly reliably with some minimal fixes here and there. I think one logical point to reevaluate if it is worth rewriting in Swift, or better porting to RN, is when we want to bring the feature to Android or we want to add some major functionality to the code.

Concur here too. Tested code is our greatest asset.

brainbicycle commented 2 years ago

(I don't know if there's a similar resolution for the Android side of things, but if there isn't: Kotlin over Java? 😬 😇 )

I think there should be! Seems like we would want to align, I have no experience with Kotlin but my impression is it is fairly similar relationship as Swift vs Objective-C and even a fairly similar language to Swift.

brainbicycle commented 2 years ago

Thanks for all your input! Since there is no major opposition going to go ahead and merge this as accepted!