SlideShare a Scribd company logo
Building a LEGO ® app with CocoaPods
Playing with bricks
@artheyn @cocoanantes
Problematic
Build a new application which reuses a lot of core
functionalities of an existing one
2
Solutions
3
• Using git submodules
‣ Hard to maintain with a lot of dependencies
‣ Hard to manage a proper versioning for each module
‣ Easy to link
‣ Versioning management and locking for free
• Using a package manager
Overview
• Slicing the app: iAdvize App case study
4
• In practice: build & use bricks
• Pros & Cons
• The wrong way
• Our modules
• Conclusion
5
1. Identify the main app domains which will form our bricks
2. Separate each brick from the main app
3. Reconstruct the main app by linking the bricks together
Slicing the app
Steps
6
Step 1
In Search of Lost Bricks
User
Account
Login
Logger
…
…
…
…
……
7
CocoaPods
Quick Reminder
PodfileApp
App
Workspace
Pods
Podfile
pod install
8
App Pods
Workspace
Podfile
Step 2
Splitting the app into bricks
App Pods
Podfile
Login
Workspace
Login
9
Step 2
Extracting the bricks
App Pods
Podfile
Login
Workspace
Pods
Workspace
Podfile
Login
10
Step 2
Extracting the bricks
App Pods
Workspace
Podfile
Login Pods
Workspace
Podfile
Auth Pods
Workspace
Podfile
…
11
Step 2
App Structure
App
UI Tests
App
Sources
App
Tests
App
12
Step 2
Module Structure
Login
UI Tests
Login
Sources
Login
Tests
Login

Integration

App
Sources
Login
13
• Using an internal pod repo
‣ Useful for strict versioning
‣ Useless if you want to point a dependency directly to a branch
• Using direct git repository link with a specific branch
pod 'iAdvizeLoggerLibrary', :git => 'ssh://(…)/mobile-ios-logger-library.git', :branch => 'master'
Step 3
Rebuild with CocoaPods
Two different ways to manage dependencies:
14
App Pods
Workspace
Podfile
Login
Podspec
Step 3
Rebuild with Cocoapods
:branch => ‘master’
15
Sample of a Podfile in the main application
def app_pods
# COCOAPODS EXTERNAL DEPENDENCIES
# HTTP requests.
pod 'Alamofire', '~> 4.0'
# (…)
# COCOAPODS INTERNAL DEPENDENCIES
# User service (user-related data storage)
pod 'iAdvizeUserService', :git => 'ssh://git@github.com/iadvize/mobile-ios-user-service.git', :branch => 'master'
# Account service (user profile)
pod 'iAdvizeAccountService', :git => 'ssh://git@github.com/iadvize/mobile-ios-account-service.git', :branch => 'master'
# Components library (reusable UI components)
pod 'iAdvizeComponentsLibrary', :git => 'ssh://git@github.com/iadvize/mobile-ios-components-library.git', :branch => 'master'
end
Step 3
Rebuild with Cocoapods
In practice
16
CocoaPods and the power of the `path`
App
Podfile
Login
Workspace
Pods
Workspace
Podfile
Pods
pod 'iAdvizeLoginService', :path => '../mobile-ios-login-service'
:path => ‘../login’
Login
In practice
17
CocoaPods and the power of the `path`
• Editing directly module files in the main app workspace like
if the module was directly in your app
‣ Impossible with Carthage!
• Test locally the integration of a module in the main app
In practice
18
Module creation
Login
PodspecPodfile
Module
Sources
App
1
2
3
4
Podfile
:path => ‘../module’
:branch => ‘master’
In practice
19
Module usage
pod 'iAdvizeConversationService', :git => ‘ssh://(…)/mobile-ios-conversation-service.git’, :branch => 'master'
1. Add module dependency in the Podfile
2. Import, configure and use your module in your app
import iAdvizeConversationService
ConversationServiceManager.shouldDisplayPrincipalImageInChat = true
let conversationRootViewController = ConversationServiceManager.initialViewController() as! UISplitViewController
addControllerToTabBar(conversationRootViewController, at: 0)
In practice
20
Application: Orchestrator of modules
• Almost empty and deserves as a module orchestrator
• Instantiates, configures and displays each module
• Observes modules events (notifications) and actions
(delegate)
• Can forward events between modules
In practice
21
Module: Reusable brick
• Contains all the sources of a domain (including tests)
• Exposes events that apps or modules can observe
• Provides a way to configure it
• Provides an initial view controller (if it contains some UI)
• In a separate project
Git workflows
22
In our applications
‣ git-flow
In our modules
‣ “github like” workflow working with master, feature branches and tags
for production versions
Pros
23
• Fully separated and reusable modules
‣ Helps to have a proper architecture and avoid duplications
• Each module has its own Xcode project so it can be developed, run
and tested independently (without integrating it in a main application)
‣ Can even be shipped as a single module app for acceptance tests
• Lighter Xcode project which means low build time when you work on
a module
• Easy to integrate with the CocoaPods local link (path)
• Even if we don’t use strict versioning, we get the benefits of module
version locking with the Podfile.lock
• More modules -> more chance you have to work alone at a time ->
less conflicts
Cons
24
• Some configuration files has to be duplicated
‣ Continuous integration, lint, localizables, run scripts…
• Multiple Podspec and Podfile to work with and maintain
• Switching module dependency from remote repository to local
sources and vice versa has to be done manually in the Podfile
pod 'iAdvizeLoggerLibrary', :git => ‘(…)mobile-ios-logger-library.git’, :branch => 'master'
pod 'iAdvizeLoggerLibrary', :path => ‘../mobile-ios-logger-library’
Our modules
25
Spreading ideas
User
Account
Authentication
CommonUI
ComponentsConversation
Livefeed
Logger
Login
Stats
PushNotifs
Tracking
Utils
The Wrong Way
26
(For us)
• Using an Internal Cocoapods specs repository was not relevant
‣ Use the git repository direct link feature of CocoaPods and point to a
specific branch
• Trying to use strict versioning on modules can quickly turn into a
nightmare
‣ No versioning is applied to our modules. The Podfile.lock prevent from
accidental updates and as we own our dependencies we are full aware of
break changes
• Applying a complex git workflow in the modules repositories is time-
consuming
‣ Using a single branch with tags for versions in production seems to be
the best solution
Conclusion
27
Great and straightforward mobile architecture approach even
for small applications which helps you to think your code in
terms of reusable bricks.
Just taste it!
Bibliography
28
http://product.hubspot.com/blog/architecting-a-large-ios-
app-with-cocoapods
Thank you!
29
Questions?
@artheyn @SimonLiotier

More Related Content

Build a lego app with CocoaPods

  • 1. Building a LEGO ® app with CocoaPods Playing with bricks @artheyn @cocoanantes
  • 2. Problematic Build a new application which reuses a lot of core functionalities of an existing one 2
  • 3. Solutions 3 • Using git submodules ‣ Hard to maintain with a lot of dependencies ‣ Hard to manage a proper versioning for each module ‣ Easy to link ‣ Versioning management and locking for free • Using a package manager
  • 4. Overview • Slicing the app: iAdvize App case study 4 • In practice: build & use bricks • Pros & Cons • The wrong way • Our modules • Conclusion
  • 5. 5 1. Identify the main app domains which will form our bricks 2. Separate each brick from the main app 3. Reconstruct the main app by linking the bricks together Slicing the app Steps
  • 6. 6 Step 1 In Search of Lost Bricks User Account Login Logger … … … … ……
  • 8. 8 App Pods Workspace Podfile Step 2 Splitting the app into bricks App Pods Podfile Login Workspace Login
  • 9. 9 Step 2 Extracting the bricks App Pods Podfile Login Workspace Pods Workspace Podfile Login
  • 10. 10 Step 2 Extracting the bricks App Pods Workspace Podfile Login Pods Workspace Podfile Auth Pods Workspace Podfile …
  • 11. 11 Step 2 App Structure App UI Tests App Sources App Tests App
  • 12. 12 Step 2 Module Structure Login UI Tests Login Sources Login Tests Login
 Integration
 App Sources Login
  • 13. 13 • Using an internal pod repo ‣ Useful for strict versioning ‣ Useless if you want to point a dependency directly to a branch • Using direct git repository link with a specific branch pod 'iAdvizeLoggerLibrary', :git => 'ssh://(…)/mobile-ios-logger-library.git', :branch => 'master' Step 3 Rebuild with CocoaPods Two different ways to manage dependencies:
  • 14. 14 App Pods Workspace Podfile Login Podspec Step 3 Rebuild with Cocoapods :branch => ‘master’
  • 15. 15 Sample of a Podfile in the main application def app_pods # COCOAPODS EXTERNAL DEPENDENCIES # HTTP requests. pod 'Alamofire', '~> 4.0' # (…) # COCOAPODS INTERNAL DEPENDENCIES # User service (user-related data storage) pod 'iAdvizeUserService', :git => 'ssh://git@github.com/iadvize/mobile-ios-user-service.git', :branch => 'master' # Account service (user profile) pod 'iAdvizeAccountService', :git => 'ssh://git@github.com/iadvize/mobile-ios-account-service.git', :branch => 'master' # Components library (reusable UI components) pod 'iAdvizeComponentsLibrary', :git => 'ssh://git@github.com/iadvize/mobile-ios-components-library.git', :branch => 'master' end Step 3 Rebuild with Cocoapods
  • 16. In practice 16 CocoaPods and the power of the `path` App Podfile Login Workspace Pods Workspace Podfile Pods pod 'iAdvizeLoginService', :path => '../mobile-ios-login-service' :path => ‘../login’ Login
  • 17. In practice 17 CocoaPods and the power of the `path` • Editing directly module files in the main app workspace like if the module was directly in your app ‣ Impossible with Carthage! • Test locally the integration of a module in the main app
  • 19. In practice 19 Module usage pod 'iAdvizeConversationService', :git => ‘ssh://(…)/mobile-ios-conversation-service.git’, :branch => 'master' 1. Add module dependency in the Podfile 2. Import, configure and use your module in your app import iAdvizeConversationService ConversationServiceManager.shouldDisplayPrincipalImageInChat = true let conversationRootViewController = ConversationServiceManager.initialViewController() as! UISplitViewController addControllerToTabBar(conversationRootViewController, at: 0)
  • 20. In practice 20 Application: Orchestrator of modules • Almost empty and deserves as a module orchestrator • Instantiates, configures and displays each module • Observes modules events (notifications) and actions (delegate) • Can forward events between modules
  • 21. In practice 21 Module: Reusable brick • Contains all the sources of a domain (including tests) • Exposes events that apps or modules can observe • Provides a way to configure it • Provides an initial view controller (if it contains some UI) • In a separate project
  • 22. Git workflows 22 In our applications ‣ git-flow In our modules ‣ “github like” workflow working with master, feature branches and tags for production versions
  • 23. Pros 23 • Fully separated and reusable modules ‣ Helps to have a proper architecture and avoid duplications • Each module has its own Xcode project so it can be developed, run and tested independently (without integrating it in a main application) ‣ Can even be shipped as a single module app for acceptance tests • Lighter Xcode project which means low build time when you work on a module • Easy to integrate with the CocoaPods local link (path) • Even if we don’t use strict versioning, we get the benefits of module version locking with the Podfile.lock • More modules -> more chance you have to work alone at a time -> less conflicts
  • 24. Cons 24 • Some configuration files has to be duplicated ‣ Continuous integration, lint, localizables, run scripts… • Multiple Podspec and Podfile to work with and maintain • Switching module dependency from remote repository to local sources and vice versa has to be done manually in the Podfile pod 'iAdvizeLoggerLibrary', :git => ‘(…)mobile-ios-logger-library.git’, :branch => 'master' pod 'iAdvizeLoggerLibrary', :path => ‘../mobile-ios-logger-library’
  • 26. The Wrong Way 26 (For us) • Using an Internal Cocoapods specs repository was not relevant ‣ Use the git repository direct link feature of CocoaPods and point to a specific branch • Trying to use strict versioning on modules can quickly turn into a nightmare ‣ No versioning is applied to our modules. The Podfile.lock prevent from accidental updates and as we own our dependencies we are full aware of break changes • Applying a complex git workflow in the modules repositories is time- consuming ‣ Using a single branch with tags for versions in production seems to be the best solution
  • 27. Conclusion 27 Great and straightforward mobile architecture approach even for small applications which helps you to think your code in terms of reusable bricks. Just taste it!