SlideShare a Scribd company logo
1 of 42
Download to read offline
Moderne App-Entwicklung am
Beispiel waipu.tv
Andreas Bauer Johannes Schamburger10.11.2016
2
Informationen zur inovex GmbH
- IT-Dienstleister in Pforzheim, Karlsruhe, Köln,
München und Hamburg
- Application Development, Datamanagement &
Analytics, Consulting und IT Engineering & Operations
- ca. 250 Mitarbeiter
3
Informationen zu waipu.tv
- Projekt der Firma EXARING AG
- Freenet ist Investor - Vermarktung u.a.
in Mobilcom Debitel Läden
- Entwicklung gestartet im letzten Herbst
- Android Entwicklung seit Anfang des Jahres mit einer
Teamgröße von 3-5 Entwicklern
- Launch von waipu.tv zum 1.10.2016
4
Was ist waipu.tv?
- TV Live-Streams
- Aufnehmen von TV-Streams
- Zeitversetzte TV-Streams
- Wiedergabe in der App und auf
dem TV (Chromecast, Amazon Fire TV)
- App als (Next Generation) Fernbedienung
5
Streaming
6
Weitere Funktionen
- Gott-Klassen
- Testbarkeit
- Wartbarkeit
- Abhängigkeit vom Framework / Lifecycle
7
Motivation
Typische Probleme in der Android App Architektur
8
Überlegungen
- Welches Architekturmodell?
- Welche Libraries?
- Dependency Injection?
- Reactive Programming?
9
Clean Architecture (Uncle Bob)
http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/
10
Eigenschaften
Die Architektur ist
- unabhängig von der UI
- unabhängig von der Datenbank
- unabhängig von Frameworks
- testbar
11
Architektur Beispiel EPG Daten
12
Architektur Beispiel EPG Daten
13
MVP - Model View Presenter
14
MVP Beispiel Kanalwechsel
15
MVP Beispiel Kanalwechsel
public interface StreamingPresenter<T> extends BasePresenter<T> {
void onStop();
void onDestroy();
void onCastDeviceDisconnected();
void onCastStarted();
void onCastStopped();
void onMuteToggled(boolean muted);
void onJumpToStart();
…
}
16
Presenter Beispiel
17
View Beispiel
public interface StreamingView<T> extends BaseView<T> {
void setPreviewImage(String previewImageHref);
void showErrorMessageForStream();
void hideErrorMessageForStream();
void setChannel(Channel channel);
void updateCastOverlayMessage(String castDeviceName);
void showFullScreenLoadingIndicator();
void hideFullScreenLoadingIndicator();
…
}
18
Pros und Cons von MVP
+ Separation of Concerns
+ Kleinere, übersichtlichere Klassen
+ Testbarkeit
- Klassen Overhead
- Mehraufwand in der Entwicklung
- saubere Umsetzung erzeugt teilweise lange
Callstrecken
19
Beispiel Presenter Unit-Test
@Test
public void select_channel_should_start_stream() throws Exception {
String streamUrl = "streamUrl";
doReturn(Observable.just(streamUrl)).when(streamUseCase)
.getStreamURL(anyString(), anyString(), anyString(), anyString(), anyString(), anyLong());
presenter.onLocalChannelSelected("ARD");
verify(liveTvView).hideErrorMessageForStream();
verify(liveTvView).setupVideoPlayer(any(VideoPlayer.class), any(EventLogger.class));
verify(liveTvView).setStream(streamUrl, VideoPlayerView.StreamType.TYPE_DASH);
verify(liveTvView).startDevicePlayback();
verify(liveTvView).updateCastViewState();
verifyNoMoreInteractions(liveTvView);
}
20
Beispiel lange Callstrecke
Szenario: Sender wird gewechselt, Sendungsdetails
werden aktualisiert.
Container Fragment -> LiveTvFragment -> LiveTvPresenter
-> LiveTvFragment -> TvDetailsView -> TvDetailsPresenter
-> TvDetailsView
21
Reactive Programming
“In reactive programming the consumer reacts to the data
as it comes in. This is the reason why asynchronous
programming is also called reactive programming. Reactive
programming allows to propagates event changes to
registered observers.” - Lars Vogel
22
RxJava
- Java VM Implementierung der ReactiveExtensions
- Portiert von .NET zu JVM von Netflix 2014
- leichtgewichtig
- Open Source
- Seit 2014 im ReactiveX Repository auf GitHub
23
Einfaches Beispiel Observable
Observable<String> simpleObservable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
subscriber.onNext("Simple Value");
subscriber.onCompleted();
}
});
24
Einfaches Beispiel Subscriber
Subscriber<String> simpleSubscriber = new Subscriber<String>() {
@Override
public void onNext(String value) {
println(value);
}
@Override
public void onCompleted() {}
@Override
public void onError(Throwable e) {}
};
simpleObservable.subscribe(simpleSubscriber);
25
Operatoren manipulieren emittierte Items
Observable<String> simpleObservable = Observable.just("Simple Value")
.map(new Func1<String, String>() {
@Override
public String call(String value) {
return value + " now modified";
}
});
simpleObservable.subscribe (new Subscriber<String>() {
@Override
public void onNext(String value) {
println(value); // prints “Simple Value now modified"
}
… }
26
Rx bei waipu.tv
public Observable<List<Channel>> getChannels() {
Observable<List<Channel>> apiCall = authorization.
.getAuthorizationStringAsObservable()
.flatMap(new Func1<String, Observable<? extends List<Channel>>>() {
@Override
public Observable<? extends List<Channel>> call(String auth) {
return businessSystemsApi.getChannelData(auth);
}
});
return authorization.loginWhenRequired(apiCall)
.doOnNext(new Action1<List<Channel>>() {
@Override
public void call(List<Channel> channels) {
dbHelper.insertChannelList(channels);
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); }
- Authentifizierung
- BS - Aufruf
- Zusätzlicher Login
- Retry
- Datenbankoperation
- Thread Handling
27
Rx bei waipu.tv
remoteDataSubject.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<Void, Boolean>() {
@Override
public Boolean call(Void aVoid) {
// get Current Remote Program Information
// if program is still valid return false
// else return true
} })
.distinctUntilChanged()
.observeOn(Schedulers.io())
.flatMap(new Func1<Boolean, Observable<List<EPGData>>>() {
@Override
public Observable<List<EPGData>> call(Boolean value) {
// Return Observable which emits Program Data for a timespan
}
})
28
Rx bei waipu.tv
.flatMap(new Func1<List<EPGData>, Observable<ProgramInformation>>() {
@Override public Observable<ProgramInformation> call(List<EPGData> epg) {
// Get Current Timestamp
// return ProgramOverview for channel
}
})
.retry(new Func2<Integer, Throwable, Boolean>() {
@Override public Boolean call(Integer retryCount, Throwable t) {
return retryCount < 3;
}
})
.subscribe(new DefaultSubscriber<ProgramInformation>("NotificationModelUpdater") {
@Override public void onNext(ProgramInformation programInformation) {
// Update Program Information
}
});
29
Problematiken
private Subscription statusSubscription;
private void listenToStatusChanges() {
statusSubscription = someObject.listenToStatusChanges()
.subscribe(new Subscriber<StatusObject>() {
...
@Override
public void onNext(StatusObject o) {
//do Stuff
} });
}
private void unsubscribeToStatusChanges() {
if(statusSubscription != null && !statusSubscription.isUnsubscribed()) {
statusSubscription.unsubscribe();
}
}
30
Dependency Injection
- Klassen verwalten ihre Abhängigkeiten nicht selbst
- Single Responsibility
- komfortable Möglichkeit, Singletons zu verwenden
- einfaches Austauschen von konkreten
Implementierungen (z.B. für Tests)
31
Dependency Injection - Dagger
Inject
@Inject
StreamUseCase streamUseCase;
32
Dependency Injection - Dagger
Module, Provides, Singleton
@Module
public class UseCaseModule {
@Provides
@Singleton
public StreamUseCase provideStreamUseCase(BusinessSystemsApi
businessSystemsApi, AuthUseCase authUseCase, EPGUseCase epgUseCase) {
return new StreamUseCase(businessSystemsApi, authUseCase, epgUseCase);
}
}
33
Dependency Injection - Dagger
Component
@Component(modules = {AppModule.class, CastModule.class, UseCaseModule.class})
public interface AppComponent {
void inject(WaipuApplication application);
StreamUseCase streamUseCase();
}
34
Dependency Injection - Dagger
Component
@Component(modules = {AppModule.class, CastModule.class, UseCaseModule.class})
public interface AppComponent {
void inject(WaipuApplication application);
StreamUseCase streamUseCase();
}@Component(dependencies = AppComponent.class, modules = {LiveTvModule.class})
public interface LiveTvComponent {
void inject(LiveTvFragment fragment);
void inject(LiveTvPresenterImpl liveTvPresenter);
}
35
Dependency Injection - Dagger
Injection
public class LiveTvFragment implements LiveTvView {
@Override
public void onCreate(Bundle savedInstanceState) {
appComponent = WaipuApplication.get(getActivity()).getAppComponent();
liveTvComponent = DaggerLiveTvComponent.builder()
.appComponent(appComponent)
.liveTvModule(new LiveTvModule(this))
.build();
liveTvComponent.inject(this);
}
}
+ Instanziierung und Konfiguration gut nachvollziehbar
+ Singletons
+ Testing
- Klassen-Overhead
- “Boilerplate” Code
36
Pros and Cons
@Inject
protected AudioStateManager audioStateManager;
37
Singletons
AudioStateManager
StreamingPresenter
VideoPlayer
CastManager
VideoPlayerControl
...
38
Klassen-Overhead & Boilerplate Code
39
LiveTvComponent:
@FragmentScope
@Component(dependencies = AppComponent.class, modules = {LiveTvModule.class})
public interface LiveTvComponent {
void inject(LiveTvFragment fragment);
void inject(LiveTvPresenterImpl liveTvPresenter);
}
Klassen-Overhead & Boilerplate Code
40
LiveTvComponent:
@FragmentScope
@Component(dependencies = AppComponent.class, modules = {LiveTvModule.class})
public interface LiveTvComponent {
void inject(LiveTvFragment fragment);
void inject(LiveTvPresenterImpl liveTvPresenter);
}
Klassen-Overhead & Boilerplate Code
LiveTvFragment:
@Override
public void setupComponent(AppComponent appComponent) {
liveTvComponent = DaggerLiveTvComponent.builder()
.appComponent(appComponent)
.liveTvModule(new LiveTvModule(this))
.build();
liveTvComponent.inject(this);
}
- Mehraufwand zahlt sich langfristig aus
- Herausforderung: konsequente Umsetzung
- automatisiertes Testen bei Android nach wie vor
umständlich
- RxJava - easy to learn, hard to master
- Gefahr von sehr großen Klassen ist nicht gebannt
41
Fazit und Erkenntnisse
Das Bild kann derzeit nicht angezeigt werden.
Vielen Dank
Unser Dank gilt
besonders der EXARING
AG, die uns diesen
Vortrag ermöglicht hat.

More Related Content

What's hot

Lasttest auf Zuruf CloudTest on Demand webinar presentation
Lasttest auf Zuruf CloudTest on Demand webinar presentationLasttest auf Zuruf CloudTest on Demand webinar presentation
Lasttest auf Zuruf CloudTest on Demand webinar presentationSOASTA
 
Reaktive Programmierung in verständlichen Worten
Reaktive Programmierung in verständlichen WortenReaktive Programmierung in verständlichen Worten
Reaktive Programmierung in verständlichen WortenQAware GmbH
 
OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...
OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...
OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...NETWAYS
 
Java in the Cloud - am Beispiel der Google App Engineg
Java in the Cloud - am Beispiel der Google App EnginegJava in the Cloud - am Beispiel der Google App Engineg
Java in the Cloud - am Beispiel der Google App Engineggedoplan
 

What's hot (6)

Lasttest auf Zuruf CloudTest on Demand webinar presentation
Lasttest auf Zuruf CloudTest on Demand webinar presentationLasttest auf Zuruf CloudTest on Demand webinar presentation
Lasttest auf Zuruf CloudTest on Demand webinar presentation
 
Reaktive Programmierung in verständlichen Worten
Reaktive Programmierung in verständlichen WortenReaktive Programmierung in verständlichen Worten
Reaktive Programmierung in verständlichen Worten
 
OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...
OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...
OSMC 2021 | SNMP Monitoring mit Prometheus / OIDs dynamisch auswählen und im ...
 
JavaScript Performance
JavaScript PerformanceJavaScript Performance
JavaScript Performance
 
Einführung in React
Einführung in ReactEinführung in React
Einführung in React
 
Java in the Cloud - am Beispiel der Google App Engineg
Java in the Cloud - am Beispiel der Google App EnginegJava in the Cloud - am Beispiel der Google App Engineg
Java in the Cloud - am Beispiel der Google App Engineg
 

Viewers also liked

Datenprodukte für Deutschlands größten Fahrzeugmarkt
Datenprodukte für Deutschlands größten FahrzeugmarktDatenprodukte für Deutschlands größten Fahrzeugmarkt
Datenprodukte für Deutschlands größten Fahrzeugmarktinovex GmbH
 
Advanced Cojure Microservices
Advanced Cojure MicroservicesAdvanced Cojure Microservices
Advanced Cojure Microservicesinovex GmbH
 
Erfolgsfaktoren von Datenprodukten
Erfolgsfaktoren von DatenproduktenErfolgsfaktoren von Datenprodukten
Erfolgsfaktoren von Datenprodukteninovex GmbH
 
Gitlab meets Kubernetes
Gitlab meets KubernetesGitlab meets Kubernetes
Gitlab meets Kubernetesinovex GmbH
 
Continuous Integration for Fun and Profit
Continuous Integration for Fun and ProfitContinuous Integration for Fun and Profit
Continuous Integration for Fun and Profitinovex GmbH
 
Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...
Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...
Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...inovex GmbH
 
Agile Methoden als Erfolgsfaktor in BI- und Big Data Projekten
Agile Methoden als Erfolgsfaktor in BI- und Big Data ProjektenAgile Methoden als Erfolgsfaktor in BI- und Big Data Projekten
Agile Methoden als Erfolgsfaktor in BI- und Big Data Projekteninovex GmbH
 
Kubernetes Workshop
Kubernetes WorkshopKubernetes Workshop
Kubernetes Workshoploodse
 
Kubernetes Frankfurt
Kubernetes FrankfurtKubernetes Frankfurt
Kubernetes Frankfurtloodse
 
OpenStack und Containers
OpenStack und ContainersOpenStack und Containers
OpenStack und Containersinovex GmbH
 
Web Components mit Polymer und AngularJS 1.x
Web Components mit Polymer und AngularJS 1.xWeb Components mit Polymer und AngularJS 1.x
Web Components mit Polymer und AngularJS 1.xinovex GmbH
 
Agile (Software-) Prozesse - Quo Vadis? [in German]
Agile (Software-) Prozesse - Quo Vadis? [in German]Agile (Software-) Prozesse - Quo Vadis? [in German]
Agile (Software-) Prozesse - Quo Vadis? [in German]Martin Gaedke
 
Die dunkle Seite der Microservices - und wie du sie besiegen kannst
Die dunkle Seite der Microservices - und wie du sie besiegen kannst Die dunkle Seite der Microservices - und wie du sie besiegen kannst
Die dunkle Seite der Microservices - und wie du sie besiegen kannst inovex GmbH
 
Continous Deployment - Schneller entwickeln
Continous Deployment - Schneller entwickelnContinous Deployment - Schneller entwickeln
Continous Deployment - Schneller entwickelnMartin Seibert
 
Docker meets Kubernetes
Docker meets KubernetesDocker meets Kubernetes
Docker meets Kubernetesloodse
 
Dockerized Microservices
Dockerized MicroservicesDockerized Microservices
Dockerized Microservicesinovex GmbH
 
Automated Application Management with SaltStack
Automated Application Management with SaltStackAutomated Application Management with SaltStack
Automated Application Management with SaltStackinovex GmbH
 
Concepts of React
Concepts of ReactConcepts of React
Concepts of Reactinovex GmbH
 
Continous Integration: A Case Study
Continous Integration: A Case StudyContinous Integration: A Case Study
Continous Integration: A Case StudyTalentica Software
 

Viewers also liked (20)

Datenprodukte für Deutschlands größten Fahrzeugmarkt
Datenprodukte für Deutschlands größten FahrzeugmarktDatenprodukte für Deutschlands größten Fahrzeugmarkt
Datenprodukte für Deutschlands größten Fahrzeugmarkt
 
Advanced Cojure Microservices
Advanced Cojure MicroservicesAdvanced Cojure Microservices
Advanced Cojure Microservices
 
Erfolgsfaktoren von Datenprodukten
Erfolgsfaktoren von DatenproduktenErfolgsfaktoren von Datenprodukten
Erfolgsfaktoren von Datenprodukten
 
Gitlab meets Kubernetes
Gitlab meets KubernetesGitlab meets Kubernetes
Gitlab meets Kubernetes
 
Continuous Integration for Fun and Profit
Continuous Integration for Fun and ProfitContinuous Integration for Fun and Profit
Continuous Integration for Fun and Profit
 
Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...
Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...
Haltet den (Daten-) Dieb! Echtzeiterkennung von Anomalien in Computernetzwerk...
 
Agile Methoden als Erfolgsfaktor in BI- und Big Data Projekten
Agile Methoden als Erfolgsfaktor in BI- und Big Data ProjektenAgile Methoden als Erfolgsfaktor in BI- und Big Data Projekten
Agile Methoden als Erfolgsfaktor in BI- und Big Data Projekten
 
Kubernetes Workshop
Kubernetes WorkshopKubernetes Workshop
Kubernetes Workshop
 
Kubernetes Frankfurt
Kubernetes FrankfurtKubernetes Frankfurt
Kubernetes Frankfurt
 
OpenStack und Containers
OpenStack und ContainersOpenStack und Containers
OpenStack und Containers
 
Web Components mit Polymer und AngularJS 1.x
Web Components mit Polymer und AngularJS 1.xWeb Components mit Polymer und AngularJS 1.x
Web Components mit Polymer und AngularJS 1.x
 
Agile (Software-) Prozesse - Quo Vadis? [in German]
Agile (Software-) Prozesse - Quo Vadis? [in German]Agile (Software-) Prozesse - Quo Vadis? [in German]
Agile (Software-) Prozesse - Quo Vadis? [in German]
 
Die dunkle Seite der Microservices - und wie du sie besiegen kannst
Die dunkle Seite der Microservices - und wie du sie besiegen kannst Die dunkle Seite der Microservices - und wie du sie besiegen kannst
Die dunkle Seite der Microservices - und wie du sie besiegen kannst
 
Continous Deployment - Schneller entwickeln
Continous Deployment - Schneller entwickelnContinous Deployment - Schneller entwickeln
Continous Deployment - Schneller entwickeln
 
Docker meets Kubernetes
Docker meets KubernetesDocker meets Kubernetes
Docker meets Kubernetes
 
Dockerized Microservices
Dockerized MicroservicesDockerized Microservices
Dockerized Microservices
 
Automated Application Management with SaltStack
Automated Application Management with SaltStackAutomated Application Management with SaltStack
Automated Application Management with SaltStack
 
Concepts of React
Concepts of ReactConcepts of React
Concepts of React
 
From ci to cd
From ci to cdFrom ci to cd
From ci to cd
 
Continous Integration: A Case Study
Continous Integration: A Case StudyContinous Integration: A Case Study
Continous Integration: A Case Study
 

Similar to Moderne App-Entwicklung am Beispiel waipu.tv

Steinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen EvolutionSteinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen EvolutionQAware GmbH
 
Cloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und GrafanaCloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und GrafanaQAware GmbH
 
Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?Josef Adersberger
 
Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?QAware GmbH
 
DevOps Prinzipien im Zusammenspiel mit Kubernetes
DevOps Prinzipien im Zusammenspiel mit Kubernetes DevOps Prinzipien im Zusammenspiel mit Kubernetes
DevOps Prinzipien im Zusammenspiel mit Kubernetes QAware GmbH
 
Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...
Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...
Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...Bernd Zuther
 
Monitoring Openstack - LinuxTag 2013
Monitoring Openstack - LinuxTag 2013Monitoring Openstack - LinuxTag 2013
Monitoring Openstack - LinuxTag 2013NETWAYS
 
Slides__Splunk_UserGroup_20220407.pdf
Slides__Splunk_UserGroup_20220407.pdfSlides__Splunk_UserGroup_20220407.pdf
Slides__Splunk_UserGroup_20220407.pdfAlexanderStz1
 
Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.QAware GmbH
 
Günzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloud
Günzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloudGünzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloud
Günzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloudAndreas Günzel
 
SplunkLive! Frankfurt 2019: Splunk at Generali Insurance
SplunkLive! Frankfurt 2019: Splunk at Generali Insurance SplunkLive! Frankfurt 2019: Splunk at Generali Insurance
SplunkLive! Frankfurt 2019: Splunk at Generali Insurance Splunk
 
Steinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen EvolutionSteinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen EvolutionQAware GmbH
 
Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.QAware GmbH
 
Bkr Workflow Oeffentlich
Bkr Workflow OeffentlichBkr Workflow Oeffentlich
Bkr Workflow OeffentlichRalf Ruethlein
 
SplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case HelvetiaSplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case HelvetiaSplunk
 
SplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case HelvetiaSplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case HelvetiaGeorg Knon
 
SplunkLive! Frankfurt 2016 - Helvetia Use Case
SplunkLive! Frankfurt 2016 - Helvetia Use CaseSplunkLive! Frankfurt 2016 - Helvetia Use Case
SplunkLive! Frankfurt 2016 - Helvetia Use CaseSplunk
 
Zeitnahe Reaktion auf Verordnungsänderungen mit Feature Toggles
Zeitnahe Reaktion auf Verordnungsänderungen mit Feature TogglesZeitnahe Reaktion auf Verordnungsänderungen mit Feature Toggles
Zeitnahe Reaktion auf Verordnungsänderungen mit Feature TogglesBATbern
 
Einführung Progressive Web App
Einführung Progressive Web AppEinführung Progressive Web App
Einführung Progressive Web AppSebastian Blum
 

Similar to Moderne App-Entwicklung am Beispiel waipu.tv (20)

Steinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen EvolutionSteinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen Evolution
 
Cloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und GrafanaCloud Observability mit Loki, Prometheus, Tempo und Grafana
Cloud Observability mit Loki, Prometheus, Tempo und Grafana
 
Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?Cloud Native und Java EE: Freund oder Feind?
Cloud Native und Java EE: Freund oder Feind?
 
Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?Cloud Native & Java EE: Freund oder Feind?
Cloud Native & Java EE: Freund oder Feind?
 
DevOps Prinzipien im Zusammenspiel mit Kubernetes
DevOps Prinzipien im Zusammenspiel mit Kubernetes DevOps Prinzipien im Zusammenspiel mit Kubernetes
DevOps Prinzipien im Zusammenspiel mit Kubernetes
 
Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...
Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...
Java Aktuell Bernd Zuther Canary Releases mit der Very Awesome Microservices ...
 
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-TestsIks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
Iks Sonderdruck Eclipse Magazin Mai 2010: Automatisierte SWTBot-Tests
 
Monitoring Openstack - LinuxTag 2013
Monitoring Openstack - LinuxTag 2013Monitoring Openstack - LinuxTag 2013
Monitoring Openstack - LinuxTag 2013
 
Slides__Splunk_UserGroup_20220407.pdf
Slides__Splunk_UserGroup_20220407.pdfSlides__Splunk_UserGroup_20220407.pdf
Slides__Splunk_UserGroup_20220407.pdf
 
Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.
 
Günzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloud
Günzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloudGünzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloud
Günzel/Griesbaum -OpenShift und GitLab: Continuous delivery in der cloud
 
SplunkLive! Frankfurt 2019: Splunk at Generali Insurance
SplunkLive! Frankfurt 2019: Splunk at Generali Insurance SplunkLive! Frankfurt 2019: Splunk at Generali Insurance
SplunkLive! Frankfurt 2019: Splunk at Generali Insurance
 
Steinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen EvolutionSteinzeit war gestern! Wege der cloud-nativen Evolution
Steinzeit war gestern! Wege der cloud-nativen Evolution
 
Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.Steinzeit war gestern! Wege der Cloud-nativen Evolution.
Steinzeit war gestern! Wege der Cloud-nativen Evolution.
 
Bkr Workflow Oeffentlich
Bkr Workflow OeffentlichBkr Workflow Oeffentlich
Bkr Workflow Oeffentlich
 
SplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case HelvetiaSplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case Helvetia
 
SplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case HelvetiaSplunkLive! Zürich 2016 - Use Case Helvetia
SplunkLive! Zürich 2016 - Use Case Helvetia
 
SplunkLive! Frankfurt 2016 - Helvetia Use Case
SplunkLive! Frankfurt 2016 - Helvetia Use CaseSplunkLive! Frankfurt 2016 - Helvetia Use Case
SplunkLive! Frankfurt 2016 - Helvetia Use Case
 
Zeitnahe Reaktion auf Verordnungsänderungen mit Feature Toggles
Zeitnahe Reaktion auf Verordnungsänderungen mit Feature TogglesZeitnahe Reaktion auf Verordnungsänderungen mit Feature Toggles
Zeitnahe Reaktion auf Verordnungsänderungen mit Feature Toggles
 
Einführung Progressive Web App
Einführung Progressive Web AppEinführung Progressive Web App
Einführung Progressive Web App
 

More from inovex GmbH

lldb – Debugger auf Abwegen
lldb – Debugger auf Abwegenlldb – Debugger auf Abwegen
lldb – Debugger auf Abwegeninovex GmbH
 
Are you sure about that?! Uncertainty Quantification in AI
Are you sure about that?! Uncertainty Quantification in AIAre you sure about that?! Uncertainty Quantification in AI
Are you sure about that?! Uncertainty Quantification in AIinovex GmbH
 
Why natural language is next step in the AI evolution
Why natural language is next step in the AI evolutionWhy natural language is next step in the AI evolution
Why natural language is next step in the AI evolutioninovex GmbH
 
Network Policies
Network PoliciesNetwork Policies
Network Policiesinovex GmbH
 
Interpretable Machine Learning
Interpretable Machine LearningInterpretable Machine Learning
Interpretable Machine Learninginovex GmbH
 
Jenkins X – CI/CD in wolkigen Umgebungen
Jenkins X – CI/CD in wolkigen UmgebungenJenkins X – CI/CD in wolkigen Umgebungen
Jenkins X – CI/CD in wolkigen Umgebungeninovex GmbH
 
AI auf Edge-Geraeten
AI auf Edge-GeraetenAI auf Edge-Geraeten
AI auf Edge-Geraeteninovex GmbH
 
Prometheus on Kubernetes
Prometheus on KubernetesPrometheus on Kubernetes
Prometheus on Kubernetesinovex GmbH
 
Deep Learning for Recommender Systems
Deep Learning for Recommender SystemsDeep Learning for Recommender Systems
Deep Learning for Recommender Systemsinovex GmbH
 
Representation Learning von Zeitreihen
Representation Learning von ZeitreihenRepresentation Learning von Zeitreihen
Representation Learning von Zeitreiheninovex GmbH
 
Talk to me – Chatbots und digitale Assistenten
Talk to me – Chatbots und digitale AssistentenTalk to me – Chatbots und digitale Assistenten
Talk to me – Chatbots und digitale Assistenteninovex GmbH
 
Künstlich intelligent?
Künstlich intelligent?Künstlich intelligent?
Künstlich intelligent?inovex GmbH
 
Das Android Open Source Project
Das Android Open Source ProjectDas Android Open Source Project
Das Android Open Source Projectinovex GmbH
 
Machine Learning Interpretability
Machine Learning InterpretabilityMachine Learning Interpretability
Machine Learning Interpretabilityinovex GmbH
 
Performance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use casePerformance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use caseinovex GmbH
 
People & Products – Lessons learned from the daily IT madness
People & Products – Lessons learned from the daily IT madnessPeople & Products – Lessons learned from the daily IT madness
People & Products – Lessons learned from the daily IT madnessinovex GmbH
 
Infrastructure as (real) Code – Manage your K8s resources with Pulumi
Infrastructure as (real) Code – Manage your K8s resources with PulumiInfrastructure as (real) Code – Manage your K8s resources with Pulumi
Infrastructure as (real) Code – Manage your K8s resources with Pulumiinovex GmbH
 

More from inovex GmbH (20)

lldb – Debugger auf Abwegen
lldb – Debugger auf Abwegenlldb – Debugger auf Abwegen
lldb – Debugger auf Abwegen
 
Are you sure about that?! Uncertainty Quantification in AI
Are you sure about that?! Uncertainty Quantification in AIAre you sure about that?! Uncertainty Quantification in AI
Are you sure about that?! Uncertainty Quantification in AI
 
Why natural language is next step in the AI evolution
Why natural language is next step in the AI evolutionWhy natural language is next step in the AI evolution
Why natural language is next step in the AI evolution
 
WWDC 2019 Recap
WWDC 2019 RecapWWDC 2019 Recap
WWDC 2019 Recap
 
Network Policies
Network PoliciesNetwork Policies
Network Policies
 
Interpretable Machine Learning
Interpretable Machine LearningInterpretable Machine Learning
Interpretable Machine Learning
 
Jenkins X – CI/CD in wolkigen Umgebungen
Jenkins X – CI/CD in wolkigen UmgebungenJenkins X – CI/CD in wolkigen Umgebungen
Jenkins X – CI/CD in wolkigen Umgebungen
 
AI auf Edge-Geraeten
AI auf Edge-GeraetenAI auf Edge-Geraeten
AI auf Edge-Geraeten
 
Prometheus on Kubernetes
Prometheus on KubernetesPrometheus on Kubernetes
Prometheus on Kubernetes
 
Deep Learning for Recommender Systems
Deep Learning for Recommender SystemsDeep Learning for Recommender Systems
Deep Learning for Recommender Systems
 
Azure IoT Edge
Azure IoT EdgeAzure IoT Edge
Azure IoT Edge
 
Representation Learning von Zeitreihen
Representation Learning von ZeitreihenRepresentation Learning von Zeitreihen
Representation Learning von Zeitreihen
 
Talk to me – Chatbots und digitale Assistenten
Talk to me – Chatbots und digitale AssistentenTalk to me – Chatbots und digitale Assistenten
Talk to me – Chatbots und digitale Assistenten
 
Künstlich intelligent?
Künstlich intelligent?Künstlich intelligent?
Künstlich intelligent?
 
Dev + Ops = Go
Dev + Ops = GoDev + Ops = Go
Dev + Ops = Go
 
Das Android Open Source Project
Das Android Open Source ProjectDas Android Open Source Project
Das Android Open Source Project
 
Machine Learning Interpretability
Machine Learning InterpretabilityMachine Learning Interpretability
Machine Learning Interpretability
 
Performance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use casePerformance evaluation of GANs in a semisupervised OCR use case
Performance evaluation of GANs in a semisupervised OCR use case
 
People & Products – Lessons learned from the daily IT madness
People & Products – Lessons learned from the daily IT madnessPeople & Products – Lessons learned from the daily IT madness
People & Products – Lessons learned from the daily IT madness
 
Infrastructure as (real) Code – Manage your K8s resources with Pulumi
Infrastructure as (real) Code – Manage your K8s resources with PulumiInfrastructure as (real) Code – Manage your K8s resources with Pulumi
Infrastructure as (real) Code – Manage your K8s resources with Pulumi
 

Moderne App-Entwicklung am Beispiel waipu.tv

  • 1. Moderne App-Entwicklung am Beispiel waipu.tv Andreas Bauer Johannes Schamburger10.11.2016
  • 2. 2 Informationen zur inovex GmbH - IT-Dienstleister in Pforzheim, Karlsruhe, Köln, München und Hamburg - Application Development, Datamanagement & Analytics, Consulting und IT Engineering & Operations - ca. 250 Mitarbeiter
  • 3. 3 Informationen zu waipu.tv - Projekt der Firma EXARING AG - Freenet ist Investor - Vermarktung u.a. in Mobilcom Debitel Läden - Entwicklung gestartet im letzten Herbst - Android Entwicklung seit Anfang des Jahres mit einer Teamgröße von 3-5 Entwicklern - Launch von waipu.tv zum 1.10.2016
  • 4. 4 Was ist waipu.tv? - TV Live-Streams - Aufnehmen von TV-Streams - Zeitversetzte TV-Streams - Wiedergabe in der App und auf dem TV (Chromecast, Amazon Fire TV) - App als (Next Generation) Fernbedienung
  • 7. - Gott-Klassen - Testbarkeit - Wartbarkeit - Abhängigkeit vom Framework / Lifecycle 7 Motivation Typische Probleme in der Android App Architektur
  • 8. 8 Überlegungen - Welches Architekturmodell? - Welche Libraries? - Dependency Injection? - Reactive Programming?
  • 9. 9 Clean Architecture (Uncle Bob) http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/
  • 10. 10 Eigenschaften Die Architektur ist - unabhängig von der UI - unabhängig von der Datenbank - unabhängig von Frameworks - testbar
  • 13. 13 MVP - Model View Presenter
  • 16. public interface StreamingPresenter<T> extends BasePresenter<T> { void onStop(); void onDestroy(); void onCastDeviceDisconnected(); void onCastStarted(); void onCastStopped(); void onMuteToggled(boolean muted); void onJumpToStart(); … } 16 Presenter Beispiel
  • 17. 17 View Beispiel public interface StreamingView<T> extends BaseView<T> { void setPreviewImage(String previewImageHref); void showErrorMessageForStream(); void hideErrorMessageForStream(); void setChannel(Channel channel); void updateCastOverlayMessage(String castDeviceName); void showFullScreenLoadingIndicator(); void hideFullScreenLoadingIndicator(); … }
  • 18. 18 Pros und Cons von MVP + Separation of Concerns + Kleinere, übersichtlichere Klassen + Testbarkeit - Klassen Overhead - Mehraufwand in der Entwicklung - saubere Umsetzung erzeugt teilweise lange Callstrecken
  • 19. 19 Beispiel Presenter Unit-Test @Test public void select_channel_should_start_stream() throws Exception { String streamUrl = "streamUrl"; doReturn(Observable.just(streamUrl)).when(streamUseCase) .getStreamURL(anyString(), anyString(), anyString(), anyString(), anyString(), anyLong()); presenter.onLocalChannelSelected("ARD"); verify(liveTvView).hideErrorMessageForStream(); verify(liveTvView).setupVideoPlayer(any(VideoPlayer.class), any(EventLogger.class)); verify(liveTvView).setStream(streamUrl, VideoPlayerView.StreamType.TYPE_DASH); verify(liveTvView).startDevicePlayback(); verify(liveTvView).updateCastViewState(); verifyNoMoreInteractions(liveTvView); }
  • 20. 20 Beispiel lange Callstrecke Szenario: Sender wird gewechselt, Sendungsdetails werden aktualisiert. Container Fragment -> LiveTvFragment -> LiveTvPresenter -> LiveTvFragment -> TvDetailsView -> TvDetailsPresenter -> TvDetailsView
  • 21. 21 Reactive Programming “In reactive programming the consumer reacts to the data as it comes in. This is the reason why asynchronous programming is also called reactive programming. Reactive programming allows to propagates event changes to registered observers.” - Lars Vogel
  • 22. 22 RxJava - Java VM Implementierung der ReactiveExtensions - Portiert von .NET zu JVM von Netflix 2014 - leichtgewichtig - Open Source - Seit 2014 im ReactiveX Repository auf GitHub
  • 23. 23 Einfaches Beispiel Observable Observable<String> simpleObservable = Observable.create( new Observable.OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext("Simple Value"); subscriber.onCompleted(); } });
  • 24. 24 Einfaches Beispiel Subscriber Subscriber<String> simpleSubscriber = new Subscriber<String>() { @Override public void onNext(String value) { println(value); } @Override public void onCompleted() {} @Override public void onError(Throwable e) {} }; simpleObservable.subscribe(simpleSubscriber);
  • 25. 25 Operatoren manipulieren emittierte Items Observable<String> simpleObservable = Observable.just("Simple Value") .map(new Func1<String, String>() { @Override public String call(String value) { return value + " now modified"; } }); simpleObservable.subscribe (new Subscriber<String>() { @Override public void onNext(String value) { println(value); // prints “Simple Value now modified" } … }
  • 26. 26 Rx bei waipu.tv public Observable<List<Channel>> getChannels() { Observable<List<Channel>> apiCall = authorization. .getAuthorizationStringAsObservable() .flatMap(new Func1<String, Observable<? extends List<Channel>>>() { @Override public Observable<? extends List<Channel>> call(String auth) { return businessSystemsApi.getChannelData(auth); } }); return authorization.loginWhenRequired(apiCall) .doOnNext(new Action1<List<Channel>>() { @Override public void call(List<Channel> channels) { dbHelper.insertChannelList(channels); } }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); } - Authentifizierung - BS - Aufruf - Zusätzlicher Login - Retry - Datenbankoperation - Thread Handling
  • 27. 27 Rx bei waipu.tv remoteDataSubject.observeOn(AndroidSchedulers.mainThread()) .map(new Func1<Void, Boolean>() { @Override public Boolean call(Void aVoid) { // get Current Remote Program Information // if program is still valid return false // else return true } }) .distinctUntilChanged() .observeOn(Schedulers.io()) .flatMap(new Func1<Boolean, Observable<List<EPGData>>>() { @Override public Observable<List<EPGData>> call(Boolean value) { // Return Observable which emits Program Data for a timespan } })
  • 28. 28 Rx bei waipu.tv .flatMap(new Func1<List<EPGData>, Observable<ProgramInformation>>() { @Override public Observable<ProgramInformation> call(List<EPGData> epg) { // Get Current Timestamp // return ProgramOverview for channel } }) .retry(new Func2<Integer, Throwable, Boolean>() { @Override public Boolean call(Integer retryCount, Throwable t) { return retryCount < 3; } }) .subscribe(new DefaultSubscriber<ProgramInformation>("NotificationModelUpdater") { @Override public void onNext(ProgramInformation programInformation) { // Update Program Information } });
  • 29. 29 Problematiken private Subscription statusSubscription; private void listenToStatusChanges() { statusSubscription = someObject.listenToStatusChanges() .subscribe(new Subscriber<StatusObject>() { ... @Override public void onNext(StatusObject o) { //do Stuff } }); } private void unsubscribeToStatusChanges() { if(statusSubscription != null && !statusSubscription.isUnsubscribed()) { statusSubscription.unsubscribe(); } }
  • 30. 30 Dependency Injection - Klassen verwalten ihre Abhängigkeiten nicht selbst - Single Responsibility - komfortable Möglichkeit, Singletons zu verwenden - einfaches Austauschen von konkreten Implementierungen (z.B. für Tests)
  • 31. 31 Dependency Injection - Dagger Inject @Inject StreamUseCase streamUseCase;
  • 32. 32 Dependency Injection - Dagger Module, Provides, Singleton @Module public class UseCaseModule { @Provides @Singleton public StreamUseCase provideStreamUseCase(BusinessSystemsApi businessSystemsApi, AuthUseCase authUseCase, EPGUseCase epgUseCase) { return new StreamUseCase(businessSystemsApi, authUseCase, epgUseCase); } }
  • 33. 33 Dependency Injection - Dagger Component @Component(modules = {AppModule.class, CastModule.class, UseCaseModule.class}) public interface AppComponent { void inject(WaipuApplication application); StreamUseCase streamUseCase(); }
  • 34. 34 Dependency Injection - Dagger Component @Component(modules = {AppModule.class, CastModule.class, UseCaseModule.class}) public interface AppComponent { void inject(WaipuApplication application); StreamUseCase streamUseCase(); }@Component(dependencies = AppComponent.class, modules = {LiveTvModule.class}) public interface LiveTvComponent { void inject(LiveTvFragment fragment); void inject(LiveTvPresenterImpl liveTvPresenter); }
  • 35. 35 Dependency Injection - Dagger Injection public class LiveTvFragment implements LiveTvView { @Override public void onCreate(Bundle savedInstanceState) { appComponent = WaipuApplication.get(getActivity()).getAppComponent(); liveTvComponent = DaggerLiveTvComponent.builder() .appComponent(appComponent) .liveTvModule(new LiveTvModule(this)) .build(); liveTvComponent.inject(this); } }
  • 36. + Instanziierung und Konfiguration gut nachvollziehbar + Singletons + Testing - Klassen-Overhead - “Boilerplate” Code 36 Pros and Cons
  • 39. 39 LiveTvComponent: @FragmentScope @Component(dependencies = AppComponent.class, modules = {LiveTvModule.class}) public interface LiveTvComponent { void inject(LiveTvFragment fragment); void inject(LiveTvPresenterImpl liveTvPresenter); } Klassen-Overhead & Boilerplate Code
  • 40. 40 LiveTvComponent: @FragmentScope @Component(dependencies = AppComponent.class, modules = {LiveTvModule.class}) public interface LiveTvComponent { void inject(LiveTvFragment fragment); void inject(LiveTvPresenterImpl liveTvPresenter); } Klassen-Overhead & Boilerplate Code LiveTvFragment: @Override public void setupComponent(AppComponent appComponent) { liveTvComponent = DaggerLiveTvComponent.builder() .appComponent(appComponent) .liveTvModule(new LiveTvModule(this)) .build(); liveTvComponent.inject(this); }
  • 41. - Mehraufwand zahlt sich langfristig aus - Herausforderung: konsequente Umsetzung - automatisiertes Testen bei Android nach wie vor umständlich - RxJava - easy to learn, hard to master - Gefahr von sehr großen Klassen ist nicht gebannt 41 Fazit und Erkenntnisse
  • 42. Das Bild kann derzeit nicht angezeigt werden. Vielen Dank Unser Dank gilt besonders der EXARING AG, die uns diesen Vortrag ermöglicht hat.