Home improvement: Architecture & Kotlin
This is a modal window.
The media could not be loaded, either because the server or network failed or because the format is not supported.
Formal Metadata
Title |
| |
Title of Series | ||
Number of Parts | 52 | |
Author | ||
License | CC Attribution 3.0 Unported: You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor. | |
Identifiers | 10.5446/47734 (DOI) | |
Publisher | ||
Release Date | ||
Language |
Content Metadata
Subject Area | |
Genre |
00:00
BitComputer architectureContext awarenessOnline helpWordGoodness of fit
01:20
Computer architectureOnline helpInformation technology consultingoutputAndroid (robot)Java appletSoftware developerJSONXMLUML
01:58
ArchitectureMaterialization (paranormal)System callComputer architectureMereologyLevel (video gaming)Software testingWage labourIterationObject (grammar)Formal languageMultiplication signJava appletDecision theoryCodeWave packetWordUnit testingElectronic mailing listShared memoryBitOrder (biology)Computer fileComputing platformAndroid (robot)CodeCartesian coordinate systemSoftware developerDifferent (Kate Ryan album)Constructor (object-oriented programming)Revision controlDampingSoftware repositoryGoodness of fitJSONXMLUML
07:16
Level (video gaming)Computer architectureArrow of timeGame controllerCASE <Informatik>Level (video gaming)Web applicationAndroid (robot)Cartesian coordinate systemDatabaseRule of inferenceView (database)Inversion (music)AbstractionInterface (computing)Table (information)Endliche ModelltheorieInterior (topology)ImplementationLogicLibrary (computing)State of matterPresentation of a groupEqualiser (mathematics)MereologyHand fanInternet service providerRepository (publishing)BitPattern languageAreaSocial classCodeData structureComputer architectureoutputSoftwareElectronic visual display
12:19
Endliche ModelltheorieInterior (topology)View (database)Social classExtension (kinesiology)Category of beingCASE <Informatik>OvalSoftware testingCantor setMotion captureFormal verificationLie groupBit2 (number)Formal languageCodeCodeComputer architectureCASE <Informatik>Revision controlMotion captureArray data structureWordSocial classElectronic mailing listImplementationFunctional (mathematics)Library (computing)Endliche ModelltheorieAbstractionExpressionTerm (mathematics)Process (computing)Connectivity (graph theory)Decision theorySoftware developerPresentation of a groupOrder (biology)Category of beingSoftware testingFlow separationJava appletDifferent (Kate Ryan album)Computer fontView (database)Multiplication signUnit testingObject (grammar)Online helpNeuroinformatikModule (mathematics)Line (geometry)Table (information)Message passingPoint (geometry)outputExecution unitWorkstation <Musikinstrument>
18:19
String (computer science)Boolean algebraCategory of beingOrder (biology)Limit (category theory)Object (grammar)Type theoryParameter (computer programming)Term (mathematics)Configuration spaceLogicAttribute grammarConstructor (object-oriented programming)Presentation of a groupConcurrency (computer science)Goodness of fitMobile appCodeSocial classHash functionField (computer science)CodeNeuroinformatikDifferent (Kate Ryan album)Extension (kinesiology)BitComputer architectureJava appletSystem callPerspective (visual)Utility softwareMultiplication signCompilerDefault (computer science)Functional (mathematics)Sound effectDivisorServer (computing)Instance (computer science)MathematicsProjective planeTwitterFactory (trading post)CASE <Informatik>JSON
24:19
String (computer science)Interface (computing)Extension (kinesiology)Execution unitOperator (mathematics)Social classLimit (category theory)Goodness of fitInterface (computing)Parameter (computer programming)Computer architectureWorkstation <Musikinstrument>Extension (kinesiology)Android (robot)Lambda calculusCASE <Informatik>Category of beingIntegrated development environmentSoftware developerObject (grammar)Configuration spaceView (database)Presentation of a groupNumberProduct (business)Execution unitMathematicsUtility softwareState observerComputer fileOrder (biology)Pointer (computer programming)ImplementationUser interfaceContent (media)Enumerated typeInitial value problemLogicString (computer science)Line (geometry)CodeBitCodeComputer animationJSON
29:40
Telephone number mappingSpacetimeComplete metric spaceString (computer science)Product (business)Social classException handlingError messageArchitectureComputer configurationNumberSocial classEnumerated typeBitLevel (video gaming)Multiplication signCodeObject (grammar)Formal languageOrder (biology)Semiconductor memoryCASE <Informatik>Computer architectureComputer configurationMessage passingCartesian coordinate systemJava appletAttribute grammarTerm (mathematics)Natural numberParameter (computer programming)Revision controlImplementationCommon Intermediate LanguageSystem callFunctional (mathematics)Different (Kate Ryan album)SpacetimeOnline helpIterationPresentation of a groupRight angleData storage deviceData typeAlgebraMaizeResultantError messageTelephone number mapping
35:38
JSONXMLUML
Transcript: English(auto-generated)
00:00
Thank you. So, good evening. My name is Jorge, and that is all that I can say in German. Well, that's not actually true. I was living here for six months, but my German is really, really rusty. So, I know how hard it is to be in a conference and how tiring it is.
00:23
So, I really appreciate that you came here for listening to my talk. I hope it's not going to deceive you. I know as an experience that if you do the last talk, particularly the one before the beers, you either have to be really amusing or interesting.
00:41
I'm not amusing, so I will try to be interesting. And I will try to talk about the topic that I told you in the name of the talk, which is mostly about architecture and how to apply some of the features that Kotlin offers to you when implementing an advanced architecture.
01:02
But before I start with that, I think I should give you a little bit of context. Because even though I am flattered because of this attendance, I'm pretty sure that most of you don't know a word about who I am and what I do. And what I do is mostly help companies and individuals to learn about best practices and architecture.
01:29
So, I organize myself as a freelance and I work for third parties, for companies who hire me to improve their architecture consultancy
01:41
or to train their developers to create a better architecture. And I do that for both iOS and Android. Okay? So, I do this for Swift and Objective-C, and I do this also for Java and Kotlin.
02:01
So, what I'm going to share with you is what I have learned when I started creating the materials and the first editions that I did with Kotlin. So, let's start without any further ado and let's talk about what I mean by this home improvement. And as I said, it is a way to go a little bit beyond of what made you successful.
02:26
Usually companies create an architecture, they create something that provides business, fulfills the business purposes as they were initially decided that they were relevant. But usually your company, if it is successful, it grows further.
02:42
And then you have an application that then you try to add an additional feature and you touch here and it breaks there, you touch there and it breaks here, and it's a nightmare to maintain this application to make it grow, to add more features to keep with the business.
03:00
So, as I said, I was creating these materials which I use for training people and I had had the materials in Objective-C, in Swift and in Java. And I remember very clearly that I attended as a speaker the DroidCon in Madrid
03:22
two and a half years ago and I was the speaker for the conference teaching testing, unit testing. But that conference, the hot topic on that conference was what was going to be the language that Google was going to take to overcome the problems with Java.
03:44
I mean, Java was designated, they were only allowing us to use Java 6 and we wanted to take advantage of some of the things that other platforms had and in order to do that, there were different answers on stage. Obviously the decision was not taken based on the talks that were happening there,
04:04
but it provided me with a lot of insights on things that could be interesting to check. At the time I remember I attended some talks about Scala, very nice language, about Go, about Dart, and I remember Antonio's talk,
04:21
Antonio Leyva probably you know his book, about calling. And I thought, oh, this looks like a nice language, I should try to test that one and I should try to apply the techniques that I have known to have a good architecture and use calling for that. So I created the first version of the repo that I give to my customers in calling
04:46
and it was as bad as my German, which means that I was roughly translating word by word from Java to something that I called calling, but to be honest it wasn't.
05:01
I have done a couple of iterations more and every time I have learned a lot by doing that. I create a full application from scratch and I do every kind of scenario in the application. So that means that I write a little bit of code to do that. Still, I must say that all the things that I'm going to tell you now
05:25
are based on my personal experience. And as you know, the calling community is not junk, but the calling community with the approval, with the seal of approval from Google, it's very junk, it's in its early stages.
05:42
And some of the things that I may say here may not be what you think about that. And I will be glad to listen always, okay? But my opinions on these languages, on this language are still in the construction. Some of the idioms are not there for me. Some of the things that I will show you maybe in a year,
06:02
I will decide that there is a better way that I didn't know at the time to do that. Still, I'm brave enough to come in front of all of you that probably know far more than me about Android development and I'm going to share what I have learned. So, I hope you like it.
06:20
Before moving on to that, let me cover the three topics that I'm going to talk about today. The first one is a little bit about architecture. And obviously, this cannot be a very long introduction because this is a 45-minute talk and I also want to cover coding and how it applies to that architecture.
06:40
But I want to give you at least the basic ideas that we can all share so when I'm referring to some part of the architecture, you know what I'm talking about. Then I will talk about some usages of coding for the application of this architecture in Android. And I will give you different examples for that.
07:03
And finally, I will do a brief recap. So, if you want to sleep, you have to sleep from now till the recap, okay? Okay, let's talk about architecture. The architecture that I'm referring to when I talk about advanced architecture
07:20
is roughly based on Uncle Bob's Clean Architecture. But because I want to know the audience and I want to know if I talk to you about a presenter that you know what I'm referring to, let me briefly ask you. Who has implemented or uses every day Model View Presenter?
07:47
Yeah, a lot of hands here. Model View View Model, cool. Clean Architecture, Viparish or something like that. Okay, cool.
08:02
I'm not asking about Model View Controller because this is not an iOS room. In Android, it would be putting everything in the activity but the database. Okay? So, let's forget about that and let's go with the Clean Architecture. For those who haven't learned anything about the Clean Architecture,
08:23
this is going to be a very brief introduction. But I think that it's going to be enough to keep you interested and read a little bit more from Uncle Bob or somebody else that can tell you about that. The Clean Architecture is based, strongly based on two previous architectures. The onion architecture and the ports and adapter.
08:43
The basic idea behind the Clean Architecture is centered around the data and the business logic. So, what is the most important part of your application? The UI, the buttons, the animations? No. That's not what feeds you. That's not what brings money to the table.
09:01
It makes appealing the application to the user but the business logic, the business cases, the use cases that you sell to your customers is what is important about your application. And more importantly is what is most immutable. The thing that you want to keep unchanged even though the new release of Android, Android O is there.
09:22
So, then you have these inner layers. The white one which is the data, the entities. The red one which is the use cases, the interactors. And then, surrounding this, you have another layer, the green one, which has the presenters and the repository patterns that you use to access your data and things like that.
09:46
Abstractions to other stuff. In the outer layer, the blue one, you have everything that is considered an implementation detail. Which is a way, a very polite way to dismiss something.
10:01
This is like uninteresting. This is an implementation detail. And these are implementation details because your application, the business logic of your application should be same independently on whether you are using an Android interface or using a web application.
10:23
Okay? The business logic behind that should be similar or in the best state equal. Okay? And notice that in this picture, there is an arrow, a yellow arrow there. And this yellow arrow is the dependency rule.
10:40
And this is key. It is very important that when you implement an application like this with this architecture, everything that is in an outer layer can depend on something in an inner layer. But anything that is in an inner layer cannot have any dependency whatsoever on an outer layer.
11:05
Well, that seems really, really hard. Because something like you have to talk to the outer layers. You have to bring the data and display it on the views. So, how do you do that? Well, you use the dependency inversion principle. The dependency inversion principle says that if I want to use class and make it independent,
11:28
I have the high level code should not depend on low level code. So, my business logic should not depend on the way that I have decided to implement my persistence.
11:42
If I'm using content providers now or tomorrow I want to change it to a network API, I would like to be able to change that without having to change my business logic. So, I remove this dependency and instead I define an abstraction.
12:01
This abstraction is what I will depend on. It's an interface or abstract class. And depending on that, instead of the detail, the implementation detail, I am totally independent on these actual libraries. Instead, what I do is I create the glue code that will connect the abstraction that I define
12:26
with the library that I'm using, the persistence or the API or anything, any implementation detail that I'm using. Do you like this implementation? Do you think that it provides you with a good architecture? Well, what I'm going to say now is tough.
12:47
But I would like to take advantage of this room and make a very respectful criticism about some opinionated decisions. Probably all of you have heard about the Google IO, the recent Google IO,
13:01
and the architecture components that Google released at that time. And I think that is an awesome job. It's great that we finally have some document that talks about architecture and that spreads the knowledge among all of us, all of us Android developers. However, the way they have implemented this, even though it's a good starting point,
13:26
if you were putting everything inside of the activity, it has a problem. Your view models have a dependency on the SDK, which is in an outer layer.
13:41
So, if you want to go with a clean architecture, architectural components, maybe not there, okay? My opinion on that. But I will be glad to discuss that during beers later. Probably before the beers. Okay? So, if this is what we all agree that could be the basic blueprints for an architecture,
14:07
how does Kotlin help me with that? Well, Kotlin brings a couple of things to the table, several. And I'm not going to be able to cover all of them. But I think I want to cover a few. The first one would be the conciseness, the first language that we got with Kotlin.
14:25
Second one will be about the data classes. Then we will talk a little bit about extensions. A little bit about property delegation. And finally, some hints about seal classes.
14:41
Let's start with conciseness. And, well, conciseness is important because we want to have code that can be easily read. And we know since we were very, very young that the more words it has, the longer it takes to read. And you know that code is not meant for computers to be read,
15:03
but for our colleagues and ourselves in a few hours to be read and understood. Which means that the closer the code is, the better it is for us because we will read it better. The code that you have there is just a very simple example of a module for Dagger 2.
15:23
Okay? This is written in Java. And, yes, yes, I said that I was going to show you Kotlin code. But I want to compare it with something. So, this is the Java code. And this is the Kotlin code. Very similar, but notice the difference in font, in font size.
15:43
And this is because, well, it's terse. I mean, the main difference here is that when you see the Kotlin code, you have this nice applied method that allows me to get rid of the object that is being called every time. And we have these equals that allows me to use an expression instead of the body of scope of a function
16:06
in order to be using that. And probably you're thinking, well, that's not match. I'm like, this doesn't help me match in terms of every day's code. Well, a couple of lines, a few more here, are really relevant in terms of being productive.
16:23
And it is not only important in terms of that. It's important to have code that can be read more easily. And this applies not only to the regular code, but also to the code that you write in order to test. This is a test case that we have for testing a presenter with data, a use case, sorry,
16:48
with the data to see if it goes to the presenter. If there is no data or is the name passed to the presenter. This is a very simple unit test using Mockito and using Java.
17:02
I have to define an array with a fixture data that I'm going to use and to check that the data is passed properly to the presenter. What do we do here? Same thing. Same thing in coding.
17:21
But because the way I apply the capture there is nicer, I need less code. Also, with the arrays. You know that probably all of you answered the questioner from JetBrains asking what was the feature that you wanted the most for the next version.
17:42
Who answered here, I want to have literals for arrays? Nobody? Well, I did. And the list of probably will become something shorter in the future. So, well, that is not bad. Only a few words, more readable, nicer.
18:00
So, what do I have with data classes? Well, I told you that the architecture was meant around the data. Around pojos. In this case, pocos because we're talking about coding. So, how do data classes help me with that? Well, data classes are really helpful because instead of having to define all the properties, the fields, the getters, the setters,
18:24
and also to create, even though it is generated, a hash code function, an equals to function, a to string function, I don't have to do anything of that. I can go with the data class, define the attributes of this data class and they will come here and I have a constructor generated by default
18:46
and all these methods that I mentioned are also generated by default. I can even add some additional functionality like the one that I have here that is a computer property. This computer property will be generated based on the logic that I have added to that entity.
19:01
So, having an entity here is several lines because of the size of the code, but this could be two liners or three liners. So, very nice. But one of the limitations of data classes is that they are not value types.
19:20
You know that. I mean, there's a big difference between having a value type and a reference. And Colleen, so far, we will have to wait till Vahala is ready, but so far, it's only able to have references. So, this is not a value type, which has some limitations
19:44
in terms of concurrency and how we use this data class. Another thing that gets in the way is because of this nice constructor that has been generated to you, you have a limitation in terms of defensive copying.
20:01
Who knows about defensive copying here? Defensive copying? Nobody? Okay, so let me explain what the problem is because, sorry, I said nobody, but I saw your hand. So, there is a book that is called Effective Java by Bloch. Is Joshua Bloch the name of the guy? So, really good book, even though it is 2005-ish.
20:25
I recommend you to read it. This is still valid. Not every item of the book, but like 95% of the book is very interesting. And the book tells you that sometimes, I mean, like, if you want to defend yourself against the use of your class,
20:41
of your POJO, you have to make copies of the objects that are used in your constructor. So, imagine that you have a date as one of the fields of your data, of your POJO. If I get the date as a reference, and that object, the reference that was created outside of my constructor,
21:01
is modified because I'm pointing to the same reference, my actual value of the date will be changed. That's bad. Not only that, if I give you a reference to the date that I have, and you change that because we are changing the same reference, I also have my value changed inside of my class.
21:23
Really bad. So, defensive copying is avoiding that problem. Coping what you get in, copying what you provide out. Okay? And the constructor in coding gets a little bit in the way. I've seen many references. I even asked my friend Paco, Paco works for those who follow his Twitter,
21:45
about a solution, because he has more experience with coding than I do, and he gave me one with an underscore in the field for the constructor and providing another property that was private. I'm sorry. I'm like, I have written Swift 2, and one of the differences between
22:02
coding and Swift is that in Swift you do have to use the parameters' names. In coding they are optional, which is good and bad. It's good because you can ignore them when you don't need them, but it's bad because things like having two constructors with the same types is impossible because the compiler is not able to differentiate the two types.
22:24
So, what I did was this construction, which makes the constructor private, uses another property and creates a companion object that provides you a factoring method to create a new instance. Then I can have a customized getter and server that will give you
22:41
or obtain the copy when it is provided from the outside. The name of the property that is seen from the outside is the date without the underscore. The one that is using the inside is the one with the underscore. So, I'm using a backing property, which is a little bit harder from the perspective of a generated data class.
23:05
Extensions. Extensions is a very nice feature of calling. And probably all of us have had at one time this package, which has util classes that are very useful.
23:25
But we have created these classes because we couldn't put the code in their original class, which is a limitation. That is very useful for things like presentation logic in an advanced architecture. When I'm talking about presentation logic, I'm not talking about business logic,
23:43
but the things that I have to do in order to change the object to show it to the user. For example, I have a temperature. Based on the configuration of the user, I may decide to present it in Celsius or Fahrenheit. I have a to-do app. Do I provide the raw date or is it better for me to provide in two days, tomorrow?
24:07
It's more telling to the user. So, that is presentation logic. The data is the same. What changes is what I do to the data in order to show it to the user. But the data is not changing. So, in this case, I can take advantage of an extension and have this extension
24:25
provide this method that provides a relative string based on the content of the date and another one that is the reference. Very simple, but it helps me to move presentation logic. It is still bounded to the date class.
24:42
And it is in the package for the presenter. Okay? But there are a couple of limitations of extensions in coding. One that is really pissing me off is that you cannot implement an interface
25:04
by implementing the methods in extensions. Which is a pain. I know that this is a limitation of the JVM. But sorry, I won't add. I'm like, if I create an interface that has the method present and the interface is called presentable,
25:21
if I add the extension to an object that adds the method present, I want this object to be presentable because it has the method. But it cannot be done. At least that I know of. If anybody knows, please let me know. That is a limitation. Another thing that is, well, I'm picky. A little bit snobby. But the thing is that I will prefer to have all the extensions in a scope
25:44
instead of all of them separated individually. So, I have to go extension by extension and create like one per method. Ugly. Not only that. It's not only ugly for me. It's ugly for the IDE also. Because if I create a file for those, it says like, oh, this is not a class.
26:02
This is not an interface. This is a file. A file of what? So, the interface, the IDE is not classifying this file properly either. Property delegation. That is a very cool feature of Kotlin.
26:22
Really powerful. Probably you have heard some examples like this one. And here what I'm doing is I have a presenter and I have a request. Something that is going to hold the data while it is being changed in the user interface.
26:40
And then when I have the data ready, I will put it into a use case and run the use case. Okay? This presenter is the data class that I show you up there in the first line. Okay? In this case, it's very simple. It has a name and the number of units for a product. Very simple use case. But please notice that I have there what is the by.
27:07
That is the keyword to imply that this property is delegated to this object. To delegate observable with this initial value.
27:22
What I'm telling is, okay, when you have a change, invoke this method. I can ignore the three parameters that are passed to that lambda. Notice that if you run this, if you change this request per property, the method will not be triggered.
27:45
Why? Because the reference to the object is not changing. What it is changing is one of its properties. So, in order to be able to trigger the delegation, you have to go and change the reference,
28:03
the create a new request with new data. Or monitor individual properties individually. Okay? Still, very, very nice. Really, really powerful. Not only for that. You can have this other implementation, which I haven't seen anywhere,
28:29
that is maybe you want to have a weak reference from the presenter to the view. Let's say that you want to survive the configuration changes.
28:42
And when you have this reference to the view, you want this reference to be weak in case you want to delete it. So, you declare this class here that, as you see, is a generic class. And you say to every reference, to every property that you want to be weak,
29:01
that you use this delegation. That is going to be an optional. And it's going to be using this delegate. And it will take care of this. It will take care of wrapping the reference and providing you with a new value if nothing is there. Really useful in an advanced architecture. Because this is a piece that gets created and reused as much as you need it.
29:26
Code utilization is key in a good architecture. Seal classes. Okay. I see many seasoned Android developers here.
29:40
So, probably you all know that enums are considered harmful. Nobody is complaining. So, I assume that's a yes. And the reason why it is considered harmful is because of that message that appeared and disappeared about don't use enums.
30:01
Okay? But if you go and do a little bit more of research, you will find out that there are a couple of reasons why enums are considered harmful. The first one is space-wise. I mean, like, if you were going to use, for example, an integer, it only takes the number of bytes of an integer.
30:21
While if you are holding a reference to the class that contains the enums value, it takes more space in memory and also in storage. That is one. The second one is that it is also relevant in terms of performance. Because now in order to access one of the values, you have to go through the
30:43
gear of that object in order to get the value that you are using for that case. So, that is why it is not recommended to have a reference. Is that a question? Oh. So, that is a reference to the two reasons why it is not recommended to have enums.
31:07
The same thing applies to CIL classes if you are using them in a when. For those who don't write calling, a switch. Calling. Switch. If you use a when, if you use CIL classes only for the purpose of going
31:23
through different use cases in the switch, in the when, then that is not the best option. Okay? However, don't do this. Notice that I have put an star up there. Meaning not that this is something that should not be done, but the code that I wrote
31:43
there should be avoided if this is the only thing that you are doing with the CIL classes. If you are doing something else, if you are taking advantage of the CIL classes for some other attributes of the CIL class, then go with it. I mean, CIL classes are algebraic data types.
32:01
Which is like saying I have a kind of objects that are somehow different and then they can behave differently and they can take different parameters in their nature and number and you want to use them similarly. And the number of cases that I have are a number. A fixed number of cases.
32:21
So, this is what you use CIL classes for. The typical example is to provide back a result. So, you have two cases there. If everything is successful, I will return the generic value that you asked me for. If everything went wrong, it's completely different, then I will provide you with an error.
32:41
So, by just returning something, I will give you the two possibilities. It's like an optional. I can either have null or have some value. So, this is what CIL classes are for. Okay. So, I hope that you have found anything interesting in the cases that I mentioned about Colleen, about usages for the architecture.
33:06
Because I'm going to recap. And I will take questions and answers after that. So, very briefly, I think that my experience is that writing the same code in Colleen or Java
33:22
it is far easier to do it in Colleen than it is in Java to write exactly the same application. Obviously, far easier means that you already have some experience writing it. The first time I did it, it was painful. Like every time that you wrote code in a new language. But after the first iteration, it is a free language.
33:42
It is very fluid. You can get a lot out of it. You don't need to write a lot of code. Some things are very easy to do. You can have top level functions. Imagine that you write Mockito hunkers matchers. So, if you want to have hunkers matchers, usually you create a class to put the methods there that will be the matchers.
34:04
But that class is totally unneeded. They are starting methods and you don't need anything there. Another thing that you could avoid by using Colleen. You can have top level functions and the matchers can be top level functions. So, it provides you with a lot of help in terms of having that.
34:22
I don't know, to be honest, if the companion objects is the best idea for starting methods. But even though that is the case, I think I really like the language compared to Java. In terms of the things that we have mentioned, I told you when to use something and when not to.
34:45
My advice on that, I can be wrong. But still I gave you my reasoning on why some of the stuff is worth to be used and some of the stuff is not. So, learn your options, do your research, check whether something works or not.
35:01
And choose what is worth for you to have in your implementations. And as I said at the beginning, we're still learning. I mean, Colleen in the Android world is very young. So, there are some things that we are writing now and we are proud of ourselves that will be our shame in the near future.
35:22
At least they will be mine because I put them here and it's going to be recorded and you will be seeing them in a future that is not so distant. So, in any case, this is a moving target. So, please adapt to the newest version of this. So, thank you very much.
35:45
I will take questions now if there is any. If the question is can I go and have beer, don't ask it. Just go. Any questions?