SlideShare a Scribd company logo
1 of 37
Download to read offline
Refactor:
From MVC to Redux
Jeff Lin @oath
Refactor:
From MVC to Redux
之 停看聽
Redux on web,每個single page的store是獨立的,但App則否
可以嘗試應用在有用到singleton的部分,如Authentication manager, location
manager
不要衝動,先聽完這場
先說結論
Agenda
從Model, view, controller談起
什麼是redux?
Concern of redux on App
從一個簡易的weather App開始
讀入json file並列出氣象站
Query API,顯示選定的氣象站目前天氣
顯示目前的雷達回波圖
先談Model, View, Controller
顯示測站列表
viewDidLoad: add views
prepareData: load station data
UITableViewDataSource
StationListViewController
plist loader/data parser
tableView dataSource/provider
DataObject
struct WeatherStation: Codable {
let stationId : String?
let name : String
}
reflectivity
API fetcher
weather
detail API
fetcher
顯示測站資料
viewDidLoad: add views
Fetch weather detail Fetch reflectivity
WeatherDetailViewController
Update detail Update reflectivity image
What's redux?
What's redux?
ReactiveX
What's redux?
單一向資料流
Store:保存目前App的狀態、發動Action、發佈state的改變
Action:提供store相關參數的唯一來源
Reducer:pure function,根據現有的state和傳入action,決定下一個state是什麼
View
StoreReducerAction
UpdateCreate
CurrentS
tate
New
State
Three Principles
Single source of truth
所有的狀態、資料皆來自store
State is read-only
所有的狀態改變都由dispatch action來完成
Changes are made with pure functions
由pure reducer 處理action,決定下一個state
Pure and impure function
不該改變傳入的參數
不該呼叫non-pure function
不該有side effect(call API, change route)
Swift本身的型別限制幫了一些忙
// Pure function
func square(x) {
return x * x
}
func squareAll(items: [Int]) {
return items.map(square)
}
ReSwift
Redux-like implementation of the unidirectional data flow architecture in Swift
ReSwift-Router
處理App中個頁面navigation的state
ReSwift-Recorder
記下Action的時間軸,方便做到time travel
Redux架構,一個新的view controller會有什麼?
設計這個頁面的每個State?
這個頁面需要哪些Action?
Reducer該如何處理這些Action+State
在view controller需要狀態改變的地方dispatch action
view controller subscribe store,並做出對應的update
氣象App:顯示列表
viewDidLoad
載入列表檔案
or from API
UITableView
reload data
UITableView
didSelect:
push detail page
Page update:
UI event:
Action
protocol WeatherListAction : Action {}
struct FetchStationList : WeatherListAction { // 讀入氣象站
}
struct LocationListFetched : WeatherListAction { // 資料載入完成
let locations: [WeatherStation]?
}
struct ShowLocationDetail: WeatherListAction { // 顯示指定站天氣
let location: WeatherStation
}
// struct FetchUserLocation : WeatherListAction {}
State
struct WeatherListState : StateType {
var isFetchTriggered = false
var locationList : [WeatherStation]?
}
Reducer
func weatherListReducer(action: Action, state: WeatherListState?) -> WeatherListState {
var nextState = state ?? WeatherListState()
switch action {
case let action as LocationListFetched:
nextState.locationList = action.locations
nextState.isFetchTriggered = true
case _ as FetchStationList:
nextState.isFetchTriggered = true
nextState.locationList = nil
break
default:
nextState.locationList = nil
}
return nextState
}
Store
// Main Reducer
func appReducer(action: Action, state: AppState?) -> AppState {
return AppState(
weatherListState: weatherListReducer(action: action, state: state?.weatherListState),
weatherDetailState: weatherDetailReducer(action: action, state:
state?.weatherDetailState),
pageRouteState: pageRouteReducer(action: action, state: state?.pageRouteState)
)
}
Store
var store = MainStore(reducer: appReducer, state: nil, middleware: middlewares)
Subscribe and stateChange
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
store.subscribe(self)
let fetchAction = FetchStationList()
store.dispatch(fetchAction)
}
func newState(state: AppState) {
if let locationList =
state.weatherListState.locationList {
locations = locationList
tableView.reloadData()
}
}
顯示測站列表
ViewController
weatherList
Reducer Store
FetchList
Action
Updatedispatch
FetchTriggered
State with
stations
那API request怎麼辦?
reflectivity
API fetcher
weather
detail API
fetcher
顯示測站資料
viewDidLoad: add views
Fetch weather detail Fetch reflectivity
WeatherDetailViewController
Update detail Update reflectivity image
Action creator or middleware
func fetchWeatherDetailFor(state: AppState, store: Store<AppState>) -> Action? {
guard let station = store.state.weatherDetailState.station else { return nil }
cwbCurrentWeather(locationName: station.name, completion: { (weather, err) in
if let weather = weather {
let fetchedAction = WeatherDetailFetched.init(weather: weather)
store.dispatch(fetchedAction)
} else {
let fetchedAction = WeatherDetailFetched.init(weather: nil)
store.dispatch(fetchedAction)
}
})
return FetchWeatherDetail(isFetched: false, location: station)
}
About test
State check
Given state, dispatch an action
Expected action should be trigger/expect state should change
看起來很美好,but...
store唯一 & combine reducer
func appReducer(action: Action, state: AppState?) -> AppState {
return AppState(
weatherListState: weatherListReducer(action: action, state:
state?.weatherListState),
weatherDetailState: weatherDetailReducer(action: action,
state: state?.weatherDetailState),
)
}
如果有兩個tab,
而且都可以顯示weather detail
需另設計state
store唯一 & combine reducer
func appReducer(action: Action, state: AppState?) -> AppState {
return AppState(
weatherListState: weatherListReducer(action: action, state:
state?.weatherListState),
weatherDetailState: weatherDetailReducer(action: action,
state: state?.weatherDetailState),
)
}
Detail page有可能永遠用不到
但state總是存在
data狀態&替換需要小心
non-Redux
navigationController?.
popViewController(ani
mated: true)
deinit/dealloc
invoked
data dealloc
data狀態&替換需要小心
Redux
navigationController?.
popViewController(ani
mated: true)
deinit/dealloc
invoked
Data still in store!
deinit {
let action = WeatherDetailReset()
store.dispatch(action)
} // Maybe...
web每個single page的store是獨立的,但App則否
依照redux架構,store為整個App共用,需要更小心的控制
redux的資料流可供參考,但不見得完全適用App(例如多個tab)
可以嘗試應用在有用到singleton的部分,如Authentication manager, location
manager
Summary
Reference
Redux document
ReduxMovieDB
Real World Flux Architecture on iOS
Thank you!

More Related Content

Similar to From mvc to redux: 停看聽

Damian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with ReduxDamian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with ReduxPROIDEA
 
How to use redux with react hooks in react native application
How to use redux with react hooks in react native applicationHow to use redux with react hooks in react native application
How to use redux with react hooks in react native applicationKaty Slemon
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тягаVitebsk Miniq
 
[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux Architecture[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux ArchitectureNaukri.com
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 DreamLab
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practicesClickky
 
Hello, ReactorKit 
Hello, ReactorKit Hello, ReactorKit 
Hello, ReactorKit Suyeol Jeon
 
Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Nir Kaufman
 
첫 리액트 경험기
첫 리액트 경험기첫 리액트 경험기
첫 리액트 경험기석진 고
 
Unidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in SwiftUnidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in SwiftSeyhun AKYUREK
 
Building Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIBuilding Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIJames Shvarts
 
Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSVisual Engineering
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - ComponentsVisual Engineering
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your projectDenny Biasiolli
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexCommit University
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsEvangelia Mitsopoulou
 
Maintaining sanity in a large redux app
Maintaining sanity in a large redux appMaintaining sanity in a large redux app
Maintaining sanity in a large redux appNitish Kumar
 

Similar to From mvc to redux: 停看聽 (20)

Damian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with ReduxDamian Kmiecik - Road trip with Redux
Damian Kmiecik - Road trip with Redux
 
How to use redux with react hooks in react native application
How to use redux with react hooks in react native applicationHow to use redux with react hooks in react native application
How to use redux with react hooks in react native application
 
React lecture
React lectureReact lecture
React lecture
 
Reactивная тяга
Reactивная тягаReactивная тяга
Reactивная тяга
 
[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux Architecture[@NaukriEngineering] Flux Architecture
[@NaukriEngineering] Flux Architecture
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3
 
React + Redux. Best practices
React + Redux.  Best practicesReact + Redux.  Best practices
React + Redux. Best practices
 
Hello, ReactorKit 
Hello, ReactorKit Hello, ReactorKit 
Hello, ReactorKit 
 
Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016Redux with angular 2 - workshop 2016
Redux with angular 2 - workshop 2016
 
첫 리액트 경험기
첫 리액트 경험기첫 리액트 경험기
첫 리액트 경험기
 
Unidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in SwiftUnidirectional Data Flow Architecture (Redux) in Swift
Unidirectional Data Flow Architecture (Redux) in Swift
 
Building Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVIBuilding Testable Reactive Apps with MVI
Building Testable Reactive Apps with MVI
 
Workshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJSWorkshop 27: Isomorphic web apps with ReactJS
Workshop 27: Isomorphic web apps with ReactJS
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
 
Introducing Vuex in your project
Introducing Vuex in your projectIntroducing Vuex in your project
Introducing Vuex in your project
 
State manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to VuexState manager in Vue.js, from zero to Vuex
State manager in Vue.js, from zero to Vuex
 
Battle of React State Managers in frontend applications
Battle of React State Managers in frontend applicationsBattle of React State Managers in frontend applications
Battle of React State Managers in frontend applications
 
Ngrx slides
Ngrx slidesNgrx slides
Ngrx slides
 
Redux - 4Developers
Redux - 4DevelopersRedux - 4Developers
Redux - 4Developers
 
Maintaining sanity in a large redux app
Maintaining sanity in a large redux appMaintaining sanity in a large redux app
Maintaining sanity in a large redux app
 

Recently uploaded

EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfkalichargn70th171
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝soniya singh
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...soniya singh
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 

Recently uploaded (20)

EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
Call Girls in Naraina Delhi 💯Call Us 🔝8264348440🔝
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
Russian Call Girls in Karol Bagh Aasnvi ➡️ 8264348440 💋📞 Independent Escort S...
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 

From mvc to redux: 停看聽