Architecting shared code
orta opened this issue · 6 comments
At my day job, I have architected a bunch of shared objective-c code into modules. This makes it easier for me to spin up prototype apps to test new ideas that only need some of our code, as well as share code with our other shipping applications (modules are: Foundation, Networking, Authentication, etc). When I develop one of our main applications I often find myself modifying those underlying modules of shared code.
So I have these modules as CocoaPods, but then I refer to them as development pods loaded from git submodules. While that sounds totally insane, it does allow me to have cocoapods easily setup my workspace & manage dependencies, but also as a development pod, I can modify the source since it is in a git submodule. However, I am completely not using the versioning of cocoapods, and relying totally on the SHA of the submodule. Not to mention managing those SHA's becomes a nightmare. So its the best (and worst) of both systems.
How does Artsy do this? What am I missing? I see from the open source that Artsy has an 'Artsy-Authentication' library, that probably is similar to mine (contains all the shared authentication code? durr) And it is used as a private Pod. What happens when you are developing an application and you need to modify that code? Do you just exit the application, go into the Pod project, make the modification then reload everything? Seems....inefficient?
Or maybe the answer is: 'Just don't do that'? Could be the need to modify that underlying shared code is showing a flaw in my architecture? Perhaps I should be getting those modules working via example code, then (and only then) doing the implementation in the main application?
We edit the libraries in their own environment, that way they will get proper PRs / unit tests / CI etc.
Then when happy bring it back in to the apps. We don’t do the full SemVer setup for them, we’re not big enough to warrant it. This approach isn’t the fastest - but it’s the best contained, each lib have their own constraints and their tests should help it be the best it can for it's abstraction. Skipping that process in order to speed up dev on the app would end up meaning shortcuts would be taken from the libraries perspective. They’re also really important as atomic projects. Especially if multiple apps rely on it.
So far we've avoided a meta “ArtsyKit” style project, I think it’s easier to work from smaller components then to try and wrap everything into a single shared project. Especially given how hard 3rd party tooling can be due to Apple in the Cocoa world. It also means we don’t have to keep updating one library, none of our libraries are actively built, they get a day or two of effort occasionally. Then sit untouched for months, meaning that the app gets the work done.
Right....that makes sense. I suppose it falls a bit into the 'Just dont do that' bit mostly... (meaning work on the underlying dependencies from the main application). Combined with the POSSIBILITY that I may have over-engineered the architecture a tad. 🤓 But it is nice to have such small projects with shared code, even if I rarely (if ever) use my 'Networking' code without my 'Authentication' code.
I could alter my setup by using the existing cocoa pods from a private Specs repo, and stop using the git submodule part of it. That would simplify the SHA updating nightmare, and if it works out, great, if not I can always go back to using development pods.
The other wrinkle is that this shared code was written a while ago, and is inside static libraries (which prevents me from adding Swift). I really need to redo the architecture such that I can write shared Swift code, so if I was going to make larger changes to how the code is organized, it would be good to align it with that change.
Thanks for the feedback, and anyone else reading this, I'd appreciate any other comments!
Yeah, switching to support frameworks took us a bit of time due to needing to make sure all our deps ( Eigen has ~50 CocoaPods ) support frameworks. In the end though it was just a part of building our apps, and we could do it once and get it working in 4 apps.
I don't think there's a perfect answer for any of this, I know tumblr are pretty happy with their TumblrKit, style approach similar to what you're talking about, as are Yahoo finance. However they are big enough to have a team devoted to those kind of core projects as opposed to our 1 app 1 developer.
Remembered that I wrote a bit about this too: http://artsy.github.io/blog/2015/09/18/Cocoa-Architecture-Dependencies/
Right, I suppose its a balance between the logistical work of managing those dependencies, the scalability of the architecture if the team grows, and the speed of prototyping new projects with shared code. As you say, no perfect answer. I may have optimized a bit too far towards scalability & prototyping at the cost of a submodule SHA nightmare!
Anyway, thanks for the thoughts!
Jeff Verkoeyen ( three20 / nimbuskit / google material for iOS ) wrote about this topic too, http://design.featherless.software/on-retiring-shared-code/