 You just get to my presentation. There we are. My name is Arshad, and I work on the project I was doing inside what we call the platform team of our company. And inside the platform team, I am in charge of architecting Gothic and making high-level genius into the structure of O-RAM. So this is a second glimpse of what O-RAM looks like and it is very different from most apps you see on the App Store because like Mansi said, we are not an app. We are an app of apps. Just to recap what we do and what the app looks like, we do right-hitting with multiple types of vehicles. We do food delivery, we do groceries delivery, and we do shopping, anything that you can imagine. And we do digital payments, so every product of ours can work with our own digital payment system, which also does robots. And we are also into booking event tickets, movie tickets, and co-leaders and lots more. So at a glance, in a technical sense, we have 18 products which are all part of O-RAM, and we are adding more of them as we speak. We are currently active in five countries, and we are adding or building in more countries. And this entire app is managed by 25 engineers in our industry, and of course we have one in the world as well. And at the end of the day, we compile about 500,000 likes of your O-RAM code. So every time you send it to the App Store, or every time you want the entire app to run, we have to compile about half a million likes of O-RAM code. And this is where our core problems begin. So we have all of these products, and the thing is they all sort of depend on each other, or they are not dependent on each other, it up to some sense, meaning that Google couldn't work unless Google Right will also build, and Google Right couldn't work unless we had some support from the payable points store. And in order to build everything, it used to take us like about an hour, because it was just one project into which we had about half a million likes of code. And with the team of about 25, we saw a daily merge conflicts, particularly in the ex-codes, in the ex-codes file, and we had anyway inconsistent GUI between our apps. This is because apps just choose to take themselves independently of each other. So a few things we tried. The first one was just log and analyze the overall build times of the app. The first command over here, which you will just enter in the template, should show your earlier build time in the ex-code status bar. And the second one would actually log any result policy of our times in the build log of ex-code. With this we identified a bunch of culprits that we think were contributing to this, to this problem we had. The first one was time difference. Now, as you all know inside Swift, when you declare a bar, and you can even give a value to it, you do not need to specify what that type is. For example, if you say var message equals capital, then you do not need to specify that message is a string. Turns out that really walks down the compiler when it comes to complex expressions of the right-hand side, which is why time difference contributes to overall build time. The second one was having too many files in a large project. This happened because we had about more than 1,000 files into our ex-code project. And once you reach to that level, ex-code just stops caching, which means that incremental builds take almost as much time as it really goes. So that was the second problem. But you have too many variables which are either internal or public in your project. Say one class has a bunch of internal variables and the other class is somehow using them. And if you're just changing one of those classes, ex-code tends to build both of them. So there's something that we observe as well, which also results in slower incremental builds. And the last one was having cycle dependencies, meaning that class A depends on class B, class B of C, and C back on A. And in this case, if you end up compiling any of one of these, or rather, if you end up changing any one of these classes, ex-code will end up building all three of them again. So there are a number of easy fixes that you can do right now. They don't require a lot of great changes into your project. The first one is just specified types in complex expressions. So if you have an expression with, say, nested collection, you can just specify the type of that variable beforehand and ex-code would take much less time to compile it. Reducing the number of exposed words. Exposed here means each other or public functions and properties inside your types. Making classes final. And there are a few other things, mostly things that designate and expose optimizations. And we do this in the debug variant of the app, so that at the release, we want all the optimizations to be there. But when you're in the debug mode, that is where you're building most of your work, we just disabled most of these things. And this helped us and this took us a bit far and it took us more or probably made working with the project a lot easier. But as in when we added more products, we ended up with more wood and whatever little things we got from these were all gone away. So we had to architect a wrap in a entirely new way and for it, we set up a few goals. The first one was selective compilation. This means that if you're working on a particular product, you should only need to compile that product and not the rest of the app. So you somehow have to figure out a way to reduce the number of code that you compile when you're working on a later basis inside the project. The second one was making a plug-in play platform. So you're entering many countries now, including Philippines, Vietnam, and you might not be launched with all products in all of these countries. So what we want to do is we should be able to create a variant of Project with just a bunch of those products that we have and support in those regions. We wanted this acceptable, manageable and declarative, who doesn't? And we wanted to avoid imposing a particular structure of all programming styles on our product teams. This means that we do not want to force our product developers to do the same work in a reactive programming way or in any other manner. The last one allowed us to improve our performance to a great level. So when we are testing or profiling one product, we do not want any code from any other product to be the beginning of the same time. This meant that the product should be completely sandboxed when it comes to testing QA and profiling it. And the first step was splitting project into multiple frameworks. At the platform, we have a new framework which we call Launchpad, which is basically the brains of our app. And we have another helper framework called Asphalt, which does our design and resistance. So Launchpad is more like a foundation. Asphalt is more like you like it for you. And after that, we moved every product into its own framework and every framework in its own repository. The moment we did that, we ended up eliminating all our work conflicts because the number of people committing to a single repository just dropped down significantly. So a bit about Launchpad. So Launchpad is the platform there between project and project products. And it's this code that leads to display and launch products or display the homescreen and take user to the right product. Apart from that, it routes notifications, deep links, analytics and variants that you get if you're standing by on this app. It also takes care of analytics, running Aputas and other web-specific features. And now Aputas provides media-specific configuration, meaning that an app which is launching in Philippines would have a significantly different GUI and a configuration compared to the app launching in Indonesia. So we looked at a lot of places for inspiration on how we could design an app of apps. We looked at whiteboard, we looked at reactive functional programming and a lot of things that are very popular these days. But nothing really answered what we were trying to do at Kosek. So if you look at any iOS app to Kosek, for example, it can be coded in a reactive manner, it can be coded in a functional manner, it can be a very strong overall wipe or light code. But I also know how to communicate with this app regardless of how that app internally is implemented. And it does so via your application delegate. So what you can say is your application delegate is like a normalized interface here we have. That's where you get all your life-side elements, that's where you get all your external elements that are coming into your app, and that's where your code begins to execute from. We use the same thing with launchpad and our projects. So instead of a dependent one-man project or a project into launchpad, we just normalize the interface of every product and then we can communicate with it via a weekly launch way. And that project will be called Launchable. And of every project product is Indian Launchable, meaning it has a common interface to itself, meaning that launchpad doesn't need to specifically import code right to show more right in the home screen on Kosek. So Launchable does these things at the very beginning. It has its own catalog and a card. For example, GoFool has a list of restaurants and a way to place orders from them. Then it knows how to make a booking and take an order. Is it? It shows the complete order, whether you're coming in from a previously completed order from history or where it's an ongoing order. It handles promotions, vouchers, and all of our growth related stuff. It has its own analytics and database interface inside of it. And it also redirects to other products. For example, inside GoFool, if you run on top of GoFool, you can just click on drop-up and you will redirect it to a different product to top of your GoFool demands. This is what the protocol looks like for Launchable. At the very minimum, we have an image, a name and an identifier by which we identified that one to them. And the interface is to present or redirect to a particular screen inside of the app. This is the part of it. This is what I could fit in in my slides, but the real one has not many more things in it. So, with this, what we could do is build like a new platform. So, make the term of your code of project now goes from go write the application target inside Launchable framework, creating that, creating the main primary interface with our tabbars or navigation controllers is all managed by Launchable. And the important framework, go write, just has a product-specific screen inside of it. Now, if you want to create an app, it just has go write unit, and if you are, say, the go write team that does this, then you just need to import go write in Launchable into your target and you want to set it. This also means that you only compile and you don't compile 90% of the code. And you can add as many code frameworks as you want, the more you add them, the more you are going to see get on the home screen. This is the V1 project app which launched in about two years back and we launched with three products at that time and creating it was very simple again by just adding these three frameworks into the app. And when it comes to launching on the app store, we just take all our product frameworks, we take a launchpad, and we create the actual project app and push it out to the app store itself. So, what is these were all achievements? And so, team building a single product took less than a minute and this is after the easy fixes that I've shown you before and just the natural fact that the product has 10 times as less code as the entire project app. So, it just takes almost an instant and team building all products took less than a minute. Now, this is not just because of the new architecture, it's also because in a display manner in which we wrote code meaning that we have very few public or open members inside of these frameworks meaning that changing one framework did not result in changing or rebuilding all of those frameworks. We also reuse the platform code when we wrote launchpad by 80%. That's a lot, that's a huge number for us and we could profile our app in a much more meaningful manner and this always resulted in a much faster at launch time. So, that's pretty much about launchpad, our foundation, and project. Now, I want to talk a bit about how we do UI and project. So, at project, we treat UI as a separate product just like we do go-ride and go-food. This means that our UI framework developers have their own team of engineers and designers and they all work together creating a UI framework especially for project. With this, we have a design language system which is basically a bunch of components that we design throughout the entire app. So, we understand few of them but we have all our buttons, we have our cards and what we do is when it comes to designing screens or when it comes to when it comes to launching bigger features we just combine smaller components like this together into larger screens and our teams are independent or you're writing are only assigned to designing these base world components with each other and we got a dashboard and these are basically the goals of our start. One is to get a consistent look and view across all our products. Second one is to get rapid and easy redesigns and we sort of learned this the hard way when we redesigned Go-Ride a few months back that it was just as difficult to put all of that into other products unless we had a common design language system between all of our products. We have an agreement to UI and UI's engineering. We said that our UI and UI and UX teams do not work on product-specific features. They don't work on import requests. They don't fight database queries. They only work on the UI independently of the rest of the company. And we ensure we have pixel-proofed UI's with every build that we make and our dashboard roughly how we do that. And the last and the most important thing is we want our documentation to be accessible throughout the company. Meaning that if you have the source code you have an entire collection of what our UI looks like along with this documentation. So, I'm just going to make a memory that this is this build. Don't let it back. Do you increase the font? Increase the font? Yeah, sure. How about now? All right, cool. So, UI has a separate app that we, of course, we don't want it on the app store but this is what we use internally. So, every property inside of Quintet goes inside this app. Here's an article card, for example. And these are all interactive. You can play with them. You can see how they scale. And these are the various alert type cards that we have inside our app. We can play this and make this interactive. And when it comes to designing a particular screen, the product developers who want to want to use this confidence can just, you know, try to drop these into their mid-files. All of these are highly desirable as well. And we just try to drop these into our mid-files. And, you know, most of the times your work is done over there. In order to ensure that these components stay healthy or stay pixel-perfect over the course of the time, we run UI tests on them. And these UI tests are done in a snapshot basis, meaning that when you run this project and run the test, it goes inside and it clicks on every component inside this catalog. And it takes every state of that component and then it takes a screenshot of each one of those states. We compare these with a reference image that we have in the project, the development, the developer designs a new component, and we use core image to subtract these two images. And what we do is we ensure that the images are exactly the same with every build. So we run it automatically and we ensure that we don't push anything to the UI repository unless you pass or you just pass. Let me just show you a demo where we just get through to just come and understand the career and try to run the button test. What I've done is I just removed the line that says the title text of the button. So the button is obviously missing a title test. And if something like this happens, the test for the button build there you go. So what's the test build? We just don't want to stop over there. What we want to do is we take exactly the build and what we do is we take a screenshot of the part that was the difference between the reference image and the reference and the image actually from there on the screen. So these are the three tests we're dealing with. So that's about it. Last one is about documentation. We have this monitor and we are waiting for it. And this is what the documentation would like. This has most of our components that we have in Asperger right now. And these images are taken from the reference images created by our UI tests. So every time we have a component this immediately comes up on our design website. And if you go inside the component you can see all of these predefined states or all of the states where this component can be in. For example, this is all embedded parts inside our app. These are all the kinds of errors that you can get in the project. Apart from that, you also have documentation which we generate with Jazzy. Jazzy automatically generates a documentation for you even if you haven't documented anything. It actually springs out the public variables and properties of all your classes. So yeah, that's pretty much how we do this project. And I would like to do this for questions now. Do you have any other questions? Yeah. Between the one hour compile time and the 4 minutes how long did the refactor take? So, that's a good question. So, the refactor took two and a half months to do. And it took one month to do it. It was about three people from the platform team. And yeah, it was a very exciting thing that happened to go check. But the one hour compile time, right? Was it on the latest version of Swift or was it on Swift 1.2 and the version of Swift? Yeah, so the one hour compile time was on Swift v3.2 on Xcode 800. So, that was, that was back in June 2017. And yeah, it has struggled a lot. Are you using ports or contents? So, for some of the ports, in fact, we even had ports for our own internal frameworks before we moved to some other ways so much. So, one of the things that we tried before the re-architecture was to, you know, pre-compile most of the code that doesn't get under it frequently and then distribute it as a part. So, that just ended up compiling lesser code. So, you have this as called framework. All your policies are the same. So, what happens when you want to bump that version, you're all framework to be affected? No. So, like I said, it's not talking to frameworks that get affected. Frameworks can park to a particular version on a spot. So, instead of, like, you would write a version in proper parts, you can just write a github over there. So, this will be the same thing for your questions. Yep. You used 20% but so, you know, more about the region. Sure. So, what used to happen is we had a monolithic app which is, like, the app and all of the products were in that one app. And at one time, what used to happen is there used to be so many unnecessary classes that used to be created because of this. So, to give you an example, they were, like, they would add a code inside the app. So, as soon as the app launches, you run, say, an effort request to fetch something from December and the same thing the code would do and some other teams would do the same thing. What LaunchFact does is it abstracts the app launch process away from the app, away from the products, meaning that the products don't know when the app launched. LaunchFact tells them when they're launched and that's what happens when you click on the app icon. So, it sort of enforces apps from running any code unless the user specifically clicks on the app. Any more? Can you use type in framework or type in framework? So, all of these frameworks are dynamic. So, there's three frameworks. You can't make a static framework with suit. But, in case we had some more difficult code, we would request to do it in a static way. Type in framework was okay? Yeah, that's true. Type in framework was because the DLA one does take a bit of time to link all the frameworks, but it only applies for third-party frameworks or for system frameworks. How do you guys manage the localization? So, Gothic has two rules of localization. One way is using the system defaults to just use localize file and do it. The second one is we have an app menu to change the app language. So, that requires us to have a localization there in between this and our app. What we do with localization is we have a tool which takes in an excel sheet which is what most of our translators give us and it converts it into a switch file with a list of constants and their values in different languages. Then we add this directly to the app inside the string bus. So, we try to automate as much as we can. We saw the documentation without any intervention from the developer. We also have tools to slice assets from Sketch and put them directly into an XC assets file, put it into the app and one of the things we are working on right now is to just compare assets that you add to the app versus assets that you already have in the app and make sure that you don't duplicate assets in the app. So, how your app complication is harder because you give your application as a framework. So, maybe in the app you can complicate. So, your app is an app so that you view your app as a framework, right? So, how do you complicate between two apps? Yeah. So, that's a very interesting question. How do we communicate between two apps? One way to do that was to import one product framework into the other but that would have this content as back to not being able to compile just one framework at a time. So, we use various boards here. One is why we have notifications. So, we have notifications that can be imported anywhere. So, that's one way which we use very sparingly. The second way is using deep links. So, each and every one of our product already knows how to handle the deep link that's coming to it and it can redirect or do anything that it needs to do with the deep link. Use the same thing inside our products as well. So, when it comes to GoFood complicating the gateway it just opens a deep link with the base URL we're wanting to go with and the amount in the query parameters of the URL basically. So, this means that they don't have to depend or import each other but this can communicate with each other. Yeah, that's true. So, you can't just send a chunk of data up with error. So, this is a shared storage inside which Launchpad exports and although it's shared as any sort simultaneously, it's like shared between multiple products. So, this product basically sends an assistive Launchpad saying that this is some data I would like to expose to this particular product and if that product accesses we just check it based on the society and then allocate it with that data. Yeah. How do you decide your deep link? Is that the market in the place and the URL or it's going to be like you pass a URL and then it comes to the first page and then the page will push down the data into the navigation checks. Sure. So, every deep link first comes to Launchpad and every product has a property every Launchpad has a property called a base link which identifies a base part rather which just says two things one deep link belongs to this project and two what are deep links this product handles. So, once it comes to Launchpad Launchpad has an array of all the possible products in the app and it just betrays to them and passes it on to the right product and deep links can have two ways one is fire and forget meaning that if you want to just go to a screen you can just fire deep links saying codebase slash top-up for example it goes directly to the top-up screen the second one would be a way to get that target screen inside the other product so that way would be codebase slash top-up and with the parameters in that get screen or I forget what the exact parameter is but in that case instead of showing that screen the product would instead return a view controller which they call you would then decide how to display. As you mentioned like this one application is 16 app right but I just check like one app so it's IP size is around 100 mp so it means like 100 divided by 16 around 7 mp for that. No it's not even distributed across all apps so some of them are like they are sharing assets and some of them are having terms of assets so my question is like are you going to use the data to download the assets or it's IP? In the IP how come it's 100 mp so here's a fun part most of our size inside the IP is not the assets it's the binary itself. So this is something weird that we found out our binaries when Gojek was a monolithic app they used to go into about 70 to 80 mp the binary of Gojek itself and what we are optimizing one right now is there are a few new settings in Xcode 4 which allow you to choose between a faster app or a smaller app so we explain one with the settings and as well as compressing assets as much as we can but like you said we don't have any assets that are downloaded after use of the app they are all there in the app. I have one more question so one of your program is Cycling Dependencies so how do you solve that? Yes, so Cycling Dependencies that's great to solve is User Protocol if you're not sure that if you have three teams depending on each other instead of them depending on each other keep the protocol in between and separate them out so instead of depending on a concrete class or concrete type it would just depend on a protocol Cycling Dependencies