SlideShare une entreprise Scribd logo
1  sur  48
Télécharger pour lire hors ligne
#Swift3Arch
Architecting Alive
Apps
Jorge D. Ortiz Fuentes
@jdortiz
#Swift3CA
A Canonical
Examples
Production
#Swift3CA
Agenda
★ Advanced Architecture Background
★ Application for Frameworks
★ Real World Example
★ Recommendations
★ Recap
Advanced Architecture
The Classics
#Swift3Arch
Clean Architecture: iOS
App
Delegate
View (VC) Presenter Interactor
Entity
Gateway
Connector
#Swift3Arch
Clean Architecture Layers
UI
DB
Preseters
Gateways
Use
cases
Entities
D
ependencies
#Swift3CA
View
class AddProgrammerViewController: UITableViewController, UITextFieldDelegate {
var presenter: AddProgrammerPresenter!
var connector: AddProgrammerConnector!
@IBOutlet weak var nameTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
presenter.viewReady()
}
@IBAction func cancel(_ sender: Any) { presenter.cancel() }
@IBAction func save(_ sender: Any) { presenter.save() }
}
extension AddProgrammerViewController: AddProgrammerView {
func display(title: String) { self.title = title }
func enableSaveButton(_ enable: Bool) { saveButton.isEnabled = enable }
}
#Swift3CA
Presenter
class AddProgrammerPresenter {
private let useCaseFactory: UseCaseFactory
weak var view: AddProgrammerView!
private var programmer = ProgrammerRequest() {
didSet { updateView() }
}
init(useCaseFactory: UseCaseFactory) { self.useCaseFactory = useCaseFactory }
func viewReady() { configureView() }
private func updateView() {
showTitle()
!// …
configureSaveAbility()
}
private func configureView() {
setUpName()
!// …
updateView()
}
private func showTitle() { view.display(title: programmer.name) }
}
#Swift3CA
Interactor
class AddProgrammerUseCase {
fileprivate let entityGateway: EntityGateway
fileprivate let request: ProgrammerRequest
fileprivate let completion: AddProgrammerCompletion
init(entityGateway: EntityGateway, request: ProgrammerRequest, completion:
@escaping AddProgrammerCompletion) {
self.entityGateway = entityGateway
self.request = request
self.completion = completion
}
}
extension AddProgrammerUseCase: UseCase {
func execute() {
let programmer = Programmer(…)
entityGateway.create(programmer: programmer) {
self.completion()
}
}
}
#Swift3CA
Entity Gateway
class InMemoryRepo {
var fetchNotifier: FetchProgrammersCompletion?
fileprivate var programmers = […]
}
extension InMemoryRepo: EntityGateway {
func create(programmer: Programmer, completion: @escaping
CreateProgrammerCompletion) {
programmers.append(programmer)
completion()
self.fetchNotifier?(programmers)
}
}
#Swift3CA
Connector
class AddProgrammerConnector {
let entityGateway: EntityGateway
init(entityGateway: EntityGateway) {
self.entityGateway = entityGateway
}
func assembleModule(view: AddProgrammerViewController) {
let useCaseFactory = UseCaseFactory(entityGateway: entityGateway)
let presenter = AddProgrammerPresenter(useCaseFactory: useCaseFactory)
view.presenter = presenter
view.connector = self
presenter.view = view
}
}
#Swift3CA
Factory
class UseCaseFactory {
let entityGateway: EntityGateway
init(entityGateway: EntityGateway) {
self.entityGateway = entityGateway
}
func addProgrammerUseCase(request: ProgrammerRequest, completion: @escaping
AddProgrammerCompletion) !-> UseCase {
return AddProgrammerUseCase(entityGateway: entityGateway, request:
request, completion: completion)
}
}
And What If?
#Swift3CA
Interacting with
Frameworks
Accounts
AddressBook
HomeKit
EventKit
HealthKit
Core Audio
Core Location
HomeKit
EventKit
The Secret Sauce
#Swift3CA
Injecting Dependencies
View
Presenter
UseCaseFactory
Entity
Gateway
Connector
Been There, Done
That
Dependency Inversion
Principle
High LowAbstract
Low
#Swift3CA
CloudKit
★ This is data source
using CloudKit
★ CloudKit is an
implementation
detail
★ NO leaky
abstractions
class CloudKitRepo {
let database: CKDatabase
let programmerRecord = "Programmer"
init() {
let container = CKContainer.default()
database = container.database(with: .private)
}
fileprivate func recordFrom(programmer: Programmer) !->
CKRecord {
let programmerID = CKRecordID(recordName:
programmer.id)
let record = CKRecord(recordType: programmerRecord,
recordID: programmerID)
updateRecordProperties(record: record, programmer:
programmer)
return record
}
}
extension CloudKitRepo: EntityGatewayProtocol {
func create(programmer: Programmer, completion:@escaping ()
!-> Void) {
let record = recordFrom(programmer: programmer)
database.save(record) { record, error in
guard error !== nil else {
NSLog("Save error: 
(error!?.localizedDescription)")
return
}
DispatchQueue.main.sync { completion() }
}
}
}
#Swift3CA
Injecting Dependencies 2
View
Presenter
UseCaseFactory
Entity
Gateway
Connector
Framework
Real World Example
A Prototype
#Swift3CA
Meetinator
EventKit
HomeKit
Magic
#Swift3CA
Yes, but…
#Swift3CA
MQTT
Server
Suscribe
“/rooms/meeting1/colorlight”
Device
Raspberry
Pi
Device
Device
#Swift3CA
MQTT
Server
Publish
“/rooms/meeting1/colorlight”
{ “firetime”: …}
Device
Raspberry
Pi
Device
Device
iPhone
#Swift3CA
Another Approach
EventKit
CocoaMQTT MQTT
(JSON)
Mosquitto
Right Abstraction?
#Swift3CA
Any* Abstraction is
Better than No
Abstraction
Hints for Good
Abstractions
#Swift3CA
No References to
Framework
#Swift3CA
Use Your Own Data
Types
#Swift3CA
Events
struct MeetingEvent {
let id: String
var name: String
var startDate: Date
var endDate: Date
var hasLights: Bool
}
#Swift3CA
Use Your Own
Communication
(Delegates/Observer/Rx…)
#Swift3CA
Use Only What You
Need
#Swift3CA
Move Implementation
Details Into
Abstracted Type
Details
#Swift3CA
From Date to JSON
★ MQTT messages
contained JSON
★ firetime is a JSON
format date
let formatter =
ISO8601DateFormatter()
let command: [ String: String ] = [
"firetime":
formatter.string(from: fireDate),
"type": type.mqttActionType(),
]
let jsonData = try!
JSONSerialization.data(withJSONObject
: command, options:
JSONSerialization.WritingOptions())
as Data
#Swift3CA
Picky with Dates
★ HomeKit
HMTimeTrigger only
accepts times with
seconds = 0
private func fixFireDate(_ fireDate:
Date) !-> Date {
let calendar = Calendar.current
let fixedFireDate =
calendar.nextDate(after: fireDate,
matching: DateComponents(second: 0),
matchingPolicy: .nextTime)!
return fixedFireDate
}
#Swift3CA
Browse HomeKit
★ HomeKit offers several
abstractions in a
hierarchy
• Homes
• Rooms
• Accessories
• Services
• Triggers
★ Extract what you need
class HomeKitColorLight: NSObject, LightController
{
var delegate: LightControllerDelegate?
fileprivate let homeManager: HMHomeManager
fileprivate var primaryHome: HMHome?
func homeManagerDidUpdateHomes(_ manager:
HMHomeManager) {
primaryHome = homeManager.primaryHome
delegate!?.lightControllerReady(self)
}
private func searchFirstColorLight() !->
HMService? {
let lightbulbs =
primaryHome!?.servicesWithTypes([HMServiceTypeLightb
ulb])
let colorLightbulb = lightbulbs!?.first
{ (service) in
let characteristics =
service.characteristics.filter { (characteristic)
in
return
characteristic.characteristicType !==
HMCharacteristicTypeHue
}
return characteristics.count > 0
}
return colorLightbulb
}
}
#Swift3CA
Look for Events
★ EventKit allows
multiple calendars
★ Avoid that
complexity
fileprivate func fetchMeetingCalendar() {
guard status !== .ready else { return }
let calendars =
eventStore.calendars(for: .event)
let calendar = calendars.filter { $0.title
!== meetingCalendarTitle } .first
if let calendar = calendar {
meetingCalendar = calendar
} else {
meetingCalendar =
EKCalendar(for: .event, eventStore:
eventStore)
if let meetingCalendar =
meetingCalendar {
meetingCalendar.title =
meetingCalendarTitle
meetingCalendar.source =
eventStore.defaultCalendarForNewEvents.source
do {
try
eventStore.saveCalendar(meetingCalendar,
commit: true)
} catch let error as NSError {
NSLog("Error: (error)")
}
}
}
}
#Swift3CA
Authorization
★ EventKit requires
Authorization to
access the data
class EventKitEventProvider {
enum Status {
case ready, accessDenied, unknown
}
let eventStore: EKEventStore
var status = Status.unknown
init() {
eventStore = EKEventStore()
checkAccessToEvents()
fetchMeetingCalendar()
}
private func checkAccessToEvents() {
switch
EKEventStore.authorizationStatus(for: .event) {
case .authorized:
status = .ready
case .notDetermined: !// First time access
requestAccessToEvents()
case .denied, .restricted:
status = .accessDenied
}
}
private func requestAccessToEvents() {
eventStore.requestAccess(to: .event)
{ (granted: Bool, error: Error?) in
!// …
}
}
}
#Swift3CA
extension LightControllerAction {
func homeKitColor() !-> UIColor {
let color: UIColor
switch(self) {
case .start: color = UIColor.green
case .warn: color =
UIColor.orange
case .end: color = UIColor.red
case .off: color = UIColor.black
}
return color
}
func sceneName() !-> String {
let name: String
switch(self) {
case .start: name = "Go green"
case .warn: name = "Go orange"
case .end: name = "Go red"
case .off: name = "Go off"
}
return name
}
}
Extend like a Boss
extension LightControllerAction {
func mqttActionType() !-> String {
let action: String
switch self {
case .start:
action = "start"
case .warn:
action = "warn"
case .end:
action = "end"
case .off:
action = "off"
}
return action
}
}
Recap
#Swift3CA
Recap
★ IoT is cool!
★ Advanced architectures can also be applied
to apps with frameworks
★ Use abstractions
★ YES, I mean it: Use abstractions
Thank
You!
@jdortiz
#Swift3CA

Contenu connexe

Tendances

OSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at Netflix
OSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at NetflixOSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at Netflix
OSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at Netflix
Manish Pandit
 
Akka persistence webinar
Akka persistence webinarAkka persistence webinar
Akka persistence webinar
patriknw
 

Tendances (19)

Reduxing like a pro
Reduxing like a proReduxing like a pro
Reduxing like a pro
 
Advanced redux
Advanced reduxAdvanced redux
Advanced redux
 
FullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + AngularFullStack Reativo com Spring WebFlux + Angular
FullStack Reativo com Spring WebFlux + Angular
 
Firebase ng2 zurich
Firebase ng2 zurichFirebase ng2 zurich
Firebase ng2 zurich
 
Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30) Azure Durable Functions (2019-03-30)
Azure Durable Functions (2019-03-30)
 
Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)Durable functions 2.0 (2019-10-10)
Durable functions 2.0 (2019-10-10)
 
Inversion Of Control
Inversion Of ControlInversion Of Control
Inversion Of Control
 
The Snake and the Butler
The Snake and the ButlerThe Snake and the Butler
The Snake and the Butler
 
A Crash Course on Serverless Applications in Python
A Crash Course on Serverless Applications in PythonA Crash Course on Serverless Applications in Python
A Crash Course on Serverless Applications in Python
 
Rntb20200805
Rntb20200805Rntb20200805
Rntb20200805
 
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
Building multi lingual and empatic bots - Sander van den Hoven - Codemotion A...
 
Event-sourced architectures with Akka
Event-sourced architectures with AkkaEvent-sourced architectures with Akka
Event-sourced architectures with Akka
 
Sane Sharding with Akka Cluster
Sane Sharding with Akka ClusterSane Sharding with Akka Cluster
Sane Sharding with Akka Cluster
 
GradleFX
GradleFXGradleFX
GradleFX
 
Test Driven Documentation with Spring Rest Docs JEEConf2017
Test Driven Documentation with Spring Rest Docs JEEConf2017Test Driven Documentation with Spring Rest Docs JEEConf2017
Test Driven Documentation with Spring Rest Docs JEEConf2017
 
OSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at Netflix
OSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at NetflixOSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at Netflix
OSCON 2014 - API Ecosystem with Scala, Scalatra, and Swagger at Netflix
 
Akka persistence webinar
Akka persistence webinarAkka persistence webinar
Akka persistence webinar
 
Retrofit
RetrofitRetrofit
Retrofit
 
Going Serverless
Going ServerlessGoing Serverless
Going Serverless
 

Similaire à Architecting Alive Apps

Track 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptx
Track 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptxTrack 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptx
Track 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptx
Amazon Web Services
 
Overview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web Framework
IndicThreads
 
Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
vhazrati
 

Similaire à Architecting Alive Apps (20)

Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)Azure Durable Functions (2019-04-27)
Azure Durable Functions (2019-04-27)
 
Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...Online Meetup: Why should container system / platform builders care about con...
Online Meetup: Why should container system / platform builders care about con...
 
DWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A TutorialDWR, Hibernate and Dojo.E - A Tutorial
DWR, Hibernate and Dojo.E - A Tutorial
 
Track 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptx
Track 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptxTrack 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptx
Track 4 Session 2_MAD03 容器技術和 AWS Lambda 讓您專注「應用優先」.pptx
 
Pharos
PharosPharos
Pharos
 
[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless[NDC 2019] Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless
 
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
 
What's New In Laravel 5
What's New In Laravel 5What's New In Laravel 5
What's New In Laravel 5
 
Tasks: you gotta know how to run them
Tasks: you gotta know how to run themTasks: you gotta know how to run them
Tasks: you gotta know how to run them
 
Taming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, MacoscopeTaming Core Data by Arek Holko, Macoscope
Taming Core Data by Arek Holko, Macoscope
 
The Developer Conference - CloudKit, entendendo a Cloud da Apple
The Developer Conference - CloudKit, entendendo a Cloud da AppleThe Developer Conference - CloudKit, entendendo a Cloud da Apple
The Developer Conference - CloudKit, entendendo a Cloud da Apple
 
Overview Of Lift Framework
Overview Of Lift FrameworkOverview Of Lift Framework
Overview Of Lift Framework
 
Overview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web FrameworkOverview of The Scala Based Lift Web Framework
Overview of The Scala Based Lift Web Framework
 
Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
 
Symfony2 - from the trenches
Symfony2 - from the trenchesSymfony2 - from the trenches
Symfony2 - from the trenches
 
Arquitecturas de microservicios - Medianet Software
Arquitecturas de microservicios   -  Medianet SoftwareArquitecturas de microservicios   -  Medianet Software
Arquitecturas de microservicios - Medianet Software
 
Lightbend Lagom: Microservices Just Right
Lightbend Lagom: Microservices Just RightLightbend Lagom: Microservices Just Right
Lightbend Lagom: Microservices Just Right
 
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition! Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
Battle Of The Microservice Frameworks: Micronaut versus Quarkus edition!
 
Ruby on Rails vs ASP.NET MVC
Ruby on Rails vs ASP.NET MVCRuby on Rails vs ASP.NET MVC
Ruby on Rails vs ASP.NET MVC
 
Hadoop training-in-hyderabad
Hadoop training-in-hyderabadHadoop training-in-hyderabad
Hadoop training-in-hyderabad
 

Plus de Jorge Ortiz

Plus de Jorge Ortiz (20)

Tell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature FlagsTell Me Quando - Implementing Feature Flags
Tell Me Quando - Implementing Feature Flags
 
Unit Test your Views
Unit Test your ViewsUnit Test your Views
Unit Test your Views
 
Control your Voice like a Bene Gesserit
Control your Voice like a Bene GesseritControl your Voice like a Bene Gesserit
Control your Voice like a Bene Gesserit
 
Kata gilded rose en Golang
Kata gilded rose en GolangKata gilded rose en Golang
Kata gilded rose en Golang
 
CYA: Cover Your App
CYA: Cover Your AppCYA: Cover Your App
CYA: Cover Your App
 
Refactor your way forward
Refactor your way forwardRefactor your way forward
Refactor your way forward
 
201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG201710 Fly Me to the View - iOS Conf SG
201710 Fly Me to the View - iOS Conf SG
 
Home Improvement: Architecture & Kotlin
Home Improvement: Architecture & KotlinHome Improvement: Architecture & Kotlin
Home Improvement: Architecture & Kotlin
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
iOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h editioniOS advanced architecture workshop 3h edition
iOS advanced architecture workshop 3h edition
 
Android clean architecture workshop 3h edition
Android clean architecture workshop 3h editionAndroid clean architecture workshop 3h edition
Android clean architecture workshop 3h edition
 
To Protect & To Serve
To Protect & To ServeTo Protect & To Serve
To Protect & To Serve
 
Clean architecture workshop
Clean architecture workshopClean architecture workshop
Clean architecture workshop
 
Escape from Mars
Escape from MarsEscape from Mars
Escape from Mars
 
Why the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID ArchitectureWhy the Dark Side should use Swift and a SOLID Architecture
Why the Dark Side should use Swift and a SOLID Architecture
 
Dependence day insurgence
Dependence day insurgenceDependence day insurgence
Dependence day insurgence
 
Architectural superpowers
Architectural superpowersArchitectural superpowers
Architectural superpowers
 
TDD for the masses
TDD for the massesTDD for the masses
TDD for the masses
 
7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS7 Stages of Unit Testing in iOS
7 Stages of Unit Testing in iOS
 
Building for perfection
Building for perfectionBuilding for perfection
Building for perfection
 

Dernier

Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
VictoriaMetrics
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 

Dernier (20)

%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
Large-scale Logging Made Easy: Meetup at Deutsche Bank 2024
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
WSO2Con2024 - From Code To Cloud: Fast Track Your Cloud Native Journey with C...
 
Architecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the pastArchitecture decision records - How not to get lost in the past
Architecture decision records - How not to get lost in the past
 
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdfPayment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
Payment Gateway Testing Simplified_ A Step-by-Step Guide for Beginners.pdf
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
MarTech Trend 2024 Book : Marketing Technology Trends (2024 Edition) How Data...
 
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With SimplicityWSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
WSO2Con2024 - Enabling Transactional System's Exponential Growth With Simplicity
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
WSO2CON 2024 - Cloud Native Middleware: Domain-Driven Design, Cell-Based Arch...
 
WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?WSO2CON 2024 - Does Open Source Still Matter?
WSO2CON 2024 - Does Open Source Still Matter?
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 

Architecting Alive Apps