React Native Radio

RNR 186 - Organizing Your Source Files

Episode Summary

In this episode, the hosts discuss files and folders -- deep vs flat, colocated vs split up, screens vs containers, and much more. They also *mostly* successfully avoided the tabs vs spaces debate.

Episode Notes

In this episode, the hosts discuss files and folders -- deep vs flat, colocated vs split up, screens vs containers, and much more. They also *mostly* successfully avoided the tabs vs spaces debate.

 

This episode brought to you by Infinite Red! Infinite Red is a premier React Native design and development agency located in the USA. With five years of React Native experience and deep roots in the React Native community (hosts of Chain React and the React Native Newsletter), Infinite Red is the best choice for your next React Native app.

Helpful Links: 

  1. Ignite: https://github.com/infinitered/ignite
  2. Ignite Andross: https://github.com/infinitered/ignite-andross
  3. Invertase: https://github.com/invertase/react-native-firebase
  4. Ryan Florence quote: https://twitter.com/mjackson/status/776155460172775424

Connect With Us! 

  1. React Native Radio: @ReactNativeRdio
  2. Adhithi - @adhithiravi
  3. Harris - @nomadicspoon
  4. Jamon - @jamonholmgren
  5. Robin - @robin_heinze

Episode Transcription

Todd Werth:

Welcome back to React Native Radio podcast brought to you by semicolons, the walkie-talkie of programming. Over. Episode 186, Organizing Your Source Files. 

Jamon Holmgren:

Hey everyone, welcome to the React Native Radio podcast where we explore React Native together. I'm your host, Jamon Holmgren and with me are my stupendous co-hosts today, all three of you... Harris, Robin, and Adhithi. Adhithi, how are you doing? You're on a new computer today, aren't you?

Adhithi Ravichandran:

I am. I'm on MacBook Pro 2019. Happy New Year to everyone listening.

Jamon Holmgren:

Yes, Happy New Year to you as well. It's nice to be on this side of it. And we have Harris. Harris, where are you today? Now that you've had a little bit of time off I'm sure you've moved all around the world.

Harris Robin Kalash:

I'm still in Montreal actually and looks like the COVID situation is getting worse here so we have curfews now. I have to stay home and we can't leave after 8:00. I think in the US if that happened, that would be the-- there would be riots on the street right now. [Laughs]

Jamon Holmgren:

Yeah, right.[laughter] No comment, unfortunately. Wow. It's getting a little--

Robin Heinze:

It’s been a day.

Jamon Holmgren:

It's been a day I. You know, this will be released in a couple weeks but we're recording this just after the whole weirdness that just happened. Yeah, we won't go into that. Last I think we heard you were in Vancouver. Now you're back in your home province--

Harris Robin Kalash:

Yeah.

Jamon Holmgren:

--and, and locked down. [laughter] And Canadians are like, “Yeah, that's cool. That's all we're supposed to do.” [laughter] Must be nice. And Robin, Robin, how are you doing today?

Robin Heinze:

I am doing well, Jamon. I'm glad to be stupendous today.

Jamon Holmgren:

Stupendous, yeah. I like that word.

Robin Heinze:

I look forward to the next synonym in your list of words that mean awesome.

Jamon Holmgren:

Stupendous always reminds me of Calvin and Hobbes. Because wasn't there a Calvin and Hobbes book that was something about stupendous? I don't know. I'd have to look that up. I should have done that for my show prep. But I did other show prep today, we are going to be launching into that pretty soon. But before we do that, I do want to note that this episode is sponsored by, guess who? Infinite Red. Infinite red is premier React Native Design and Development Agency located fully remote in the USA. We've been fully remote for a long time. We have years of React Native experience ever since it was released. Actually since React Native Android was released because iOS was released earlier that year 2015 and then Android came out later. Then once that happened, we took that on and love it. Deep roots, we have deep roots in the React Native community just like trees, I guess? I don't know. I didn't know where I was going. [laughter] And we also publish the React Native newsletter to over 11,000-- I think it's actually 12,000 subscribers-- I should update my notes. 

Adhithi Ravichandran:

Wow!

Jamon Holmgren:

We are the best choice for your React Native app in my very objective opinion. Hit us up at hello@infinite.red. You can also email me directly jamon@infinite.red. Learn more on our website, infinite.red. So, our main topic today is organizing your source files.

Robin Heinze:

It's one of those things that developers just love to argue about.

Jamon Holmgren: It is. It really is. And I really want to kind of talk-- I want to dive into why that is. I want to dive into the psychology of this. Does anybody have a psychology degree here? I feel like a psychology degree is pretty common because people are like, “Hey, that's the easiest degree.” And so they go get that. 

Robin Heinze:

Ouch.

Jamon Holmgren:

Yeah. [laughter] Did I just tick off a bunch people? [laughter]

Robin Heinze: 

Jamon throwing shade. I know, they're probably not listening to this podcast, though, so you're probably safe.

Jamon Holmgren:

That’s true. You’re a psychology major. I don’t know. Anyway, yes. We need to think about the psychology of this. Why did developers argue about this?

Harris Robin Kalash:

It makes us feel smarter. [laughter]

Robin Heinze: It's very personal. It's like your workspace. 

Jamon Holmgren:

It's like your desk. 

Robin Heinze:

It's like your desk and it also affects how you organize your thoughts and how your mental model of what you're building. So it's very unique to each developer.

Adhithi Ravichandran:

I think the reason we argue about it is if we're working with the team and if the team has different opinions, then we need to figure out how do we put all these tools together in this toolbox? If you're working in silo, nobody cares. 

Robin Heinze:

Exactly. It's like having to organize your desk a certain way but then you have to share it with everyone on your team.

Adhithi Ravichandran:

Exactly.

Harris Robin Kalash:

Yeah.

Jamon Holmgren:

[Laughs] Can you imagine if we all had to use the same desk and we had to organize in a way that everybody was cool with it?

Robin Heinze:

I know several people off top of my head that would not do well having the same desk.

Jamon Holmgren:

[Laughs] Yeah, I suspect I know what you're talking about. This is one of the benefits of being remote. Is you don’t even have to look at each other's desks. It's just out of the frame on zoom.

Robin Heinze:

Although we do have a fun, slack exercise that we do once every 6 months called desk raid. 

Adhithi Ravichandran:

Oh, wow.

Jamon Holmgren:

Yes, desk raid.

Robin Heinze:

Where someone will post in slack and call a desk raid and everyone in the thread posts a picture of their desk unaltered.

Jamon Holmgren:

You can't clean it up.

Robin Heinze:

No cleaning, you can't move anything. Just like as is.

Jamon Holmgren:

I suspect the designers always clean them up because they're always so pristine. Is that really how they work? 

Robin Heinze:

Yes, I believe that.

Jamon Holmgren:

Okay.

Harris Robin Kalash:

I have a confession. I stole desk raids and implemented it [laughter] at different places. It's awesome. I think I saw Git do it. So I have to give credit to Git.

Robin Heinze:

It's fun if you work for remote because that's not an angle that you ever get to see from your coworkers. And it's just like a little window--

Adhithi Ravichandran:

That’s awesome.

Robin Heinze:

--to their world.

Jamon Holmgren:

I've done it on Twitter. That's been fun, too. Just get people from all over the world to post pictures of their desk, it's fun. But we're talking about files and folders. When I started coding, I used QBasic and this was-- I was 12. And in QBasic, you don't really have the concept of folders for the simple reason that your whole program’s in one file. [Laughs] And the sound’s unmanageable, but the way that QBasic gets around this and I actually think it's brilliant and I feel like we missed the ball not doing this, the editor actually handles it for you. So what you can do is, you can hit I think it's F2. When you hit F2, it pops up a screen that shows all of your functions and sub routines which are basically functions that return void. They don't return anything. But, you can see they're all sorted alphabetically right in front of you and you can just go and hit enter on a navigate to a function and hit enter on it. And then it goes to a screen that just shows that function. It doesn't show anything else. Now it's in the same file. If you were to look at it in a different editor, you would see it just among all the other functions at the end of the file.

Robin Heinze:

So wait, what's the editor that you have to use?

Jamon Holmgren:

It's just the QBasic editor. 

Robin Heinze:

Okay.

Jamon Holmgren:

Yes.

Robin Heinze:

VS code wouldn't do the same thing for you? It probably would.  I wonder if there's like an extension. There probably is.

Jamon Holmgren:

Maybe, yeah. But it's something we don't really do. I haven't worked in the Visual Studio world or visual like these other applications, maybe there are IDEs that do this for you. But I do remember QBasic doing this. One thing I do just for nostalgia sake is I have a copy of Gorillas gorilla.bas. And-- I think everybody here is quite a bit younger than me-- But back in the day, Gorilla was like one of the first programs that people would see the source code for because it was-- and I'm actually going to share my screen. Those of you on the podcast will not be able to see this, but I'm going to show it to my co-hosts here-- And you can see that here's all this basic code. And I'm going to scroll all the way to the bottom if I can get VS code to work. We have 1150 lines of code, okay? But, each of these sub routines and functions and there's a function: SCL pass the number in to scale for CGA. That's because there were different monitors and monitor modes and stuff. But all you would see if you went to the SCL function after hitting F2 was just this, that's all you would see. It’s just that function which is, like I don't know, 10 lines of code, okay? You would just see that. And then to go back to the main one, it would actually basically scroll you right back to the top and you can kind of see everything else, right?

Robin Heinze:

Is the reason it has to be like this it's just the language doesn't have any concept of importing or bringing in things in from other files?

Jamon Holmgren:

I don't think it did, yeah. And so that was sort of a limitation that led to this particular innovation. The benefit of course is you can distribute your program as just a single file. It's really simple. You don't have to zip up a folder. It's pretty straightforward. Now if you were doing this today--

Robin Heinze:

But, developer experience, though.

Jamon Holmgren:

Yeah. Well, and especially if you're sharing with someone, so like, if you were doing this today, what would merge conflicts like-- 

Robin Heinze:

Merge conflicts?

Jamon Holmgren:

Yeah.

Robin Heinze:

I don't even want to know.

Jamon Holmgren: 

I'd imagine that Git would handle it differently. There would be some other way. But yeah, it's just kind of an interesting peek into the past of one single file. Now you can go beyond that and be like, “Okay. Well, this function could be in its own file.” We could do a dot bat file that you could then import at the top and then you have access to that function in your main area. Now you have these applications that have a lot of you see this in older C programs a lot where you'll have a bunch of files all at the kind of the root .C files. So that's sort of the next evolution of this.

Adhithi Ravichandran:

So do like in the file you showed us, do they have to be on chronological order, the functions? Can they all be jumbled up and you'll still know it?

Jamon Holmgren:

You know that's a very good question. I believe that they are actually in alphabetical order. And then it would insert based on the name of the function that you create. Cuz you would like to create a new function, you would hit create new from the menu and then name it, and then you would insert it in alphabetical order which would please all the pedants who looked at the file and wanted to save it.

Adhithi Ravichandran:

Wow, you took us to a journey. [laughter] 1990s, I'm guessing.

Jamon Holmgren:

Yes. Back probably before you were born.[Laughs] 

Robin Heinze:

I was born.

Jamon Holmgren:

Okay. So it's definitely a different way. And of course, Basic was intended for beginners to-- it wasn't actually necessarily supposed to be for people making really serious applications. I did see recently a game called Black Annex. It's not actually all that recent [laughs], it was back several years ago. But it was a really cool game. I didn't know it was written in QBasic, but they were actually releasing it on Steam. And it actually has-- it's sort of a pixel art game. And it looks really fun and stuff like that. But they actually wrote it in a somewhat newer version of QBasic called QB64 which you can actually compile to an executive file. Someone is still using it apparently for games and stuff. But yeah, this is a peek into our past. So you have these files. Now, programmers feel the need to start categorizing them. If you have 150 source files in your root folder, that can get a little tough to manage. Although Robin and I worked with a guy who advocated for this. [laughs]

Robin Heinze:

If you're listening, Ryan, you know who you are. [laughter] Was a fan of completely flat project structure, so all of your files just in the root and just use your editor to find what you're what you're looking for. Which I mean, the way editors work now it's not hard to just pull up the file that you want assuming you've named it in a helpful way. This wouldn't-- I don't think this will work if you have--

Jamon Holmgren:

index.js index2.js

Robin Heinze:

--index2.js. [laughter]

Jamon Holmgren:

Imagine, though, let's just follow this a little bit. Let's say that its component-menu.js or something. I guess you could deal with that. It would sort-- all your components would be good together because it's like all at the beginning of the file name. 

 

Robin Heinze:

Yeah.

Jamon Holmgren: 

I'm just trying to kind of follow this thought. 

Robin Heinze:

Oh, yeah.

Jamon Holmgren: There’s something about it that's kind of appealing.

Robin Heinze:

You can do a lot with your naming structure to give your files a little bit of predictable sort order. And you don't-- I mean, if someone opens the project, they don't have to hunt through folders to find what they're looking for. So that's definitely an advantage.

Jamon Holmgren:

Just have to hunt through files.

Robin Heinze:

Just have to hunt through files.

Jamon Holmgren:

One thing that's kind of interesting about is sometimes you'll drill way down into it, and we're gonna get to deep sort of deep folder structures later, but you drill all the way down and you're like, “Oh, there's one file in that folder.” Or you drill all the way down and all of a sudden there's 20 files in that folder. It's not discoverable. But if they're all in the same, you're gonna see them.

Robin Heinze:

In your Android project, you'll drill down and it's just like folder, folder, folder and you have to go through like six layers of folders before you actually get to a file.

Jamon Holmgren:

Let me actually read-- I looked, as part of my show prep, to see how deep this goes. And it's myapp/android/app/source/main/java /com/maya... and then there's a file in there. [Laughs]

Robin Heinze:

Yeah, and the Android folder structure always leaves me scratching my head a bit and I'm like, “Wait, which main am I in? Which app am I in? Which build am I in?”

Jamon Holmgren:

Which Gradle? [laughter] Harris, have you ever thought about just putting all your files into the root folder of your app?

Harris Robin Kalash:

Yeah, I kind of agree with Ryan here. I would just do everything flat. So I think I honestly I don't think too much about-- I'll just typically go with whatever's there. But, there are some advantages I guess to something like DDD. I don't know if we want to dive into that right now. 

Jamon Holmgren:

Yeah, we can certainly dive into that. So, obviously flat structure is not the only thing. But as programmers have sort of gotten more and more sophisticated apps. We've come up with all these different ideas. So, Harris is going to jump right into one of the actually more complex ones that I've found- DDD. Go ahead and explain that.

Harris Robin Kalash:

The main benefit for DDD is really that if you're in a large—At least the way I see it is if you're in a large team, you could really benefit from that design pattern because it reduces the commit surface area of your code base. So, the main idea behind it is that if you're working on a specific domain in your application, you should only be touching these files, right? And what will happen is you're probably going to get less merge conflicts down the road. You're not gonna have to go across different areas of your culture really reducing the commit area of your codebase. So, I can see that being really useful in a large team.

Robin Heinze:

Did we define what DDD is? 

Harris Robin Kalash:

We did not. 

Robin Heinze:

We should probably define what DDD is real quick.

Adhithi Ravichandran:

It stands for Domain-Driven Design file structure.

Jamon Holmgren:

And design, of course, meaning the design of our folder structure and our architecture of the app, not design, not UI design.

Robin Heinze:

I think the basic idea is you organize your project in a way that makes sense for the business logic of what you're building. 

Jamon Holmgren:

What's an example? Let's get some examples out there.

Robin Heinze:

If you have an app that has maybe a concept of users and things that go around users like profile, editing, and maybe managing friends something like that stuff that has to do with users, then those files would all be kind of grouped together. And then if you had another part of your app that was like widgets, they like you're listing a product or something, everything to do with those widgets would go together.

Jamon Holmgren:

Yeah, I remember encountering this first with Ember. Ember started kind of pushing a layout. They called it pods which I actually liked that a little bit. It's like you just have this little container, this pod and it has everything you need in it. So, the way that they explain it is pods based projects organize files by features combining all entity files into a common directory. And so then they show an example. And you would have like your app, and then you'd have post, and then under post you would have controller dot js model dot js route dot js and template dot HBS which is their handlebars template format that they use. So in your app, if you wanted to edit something to do with a post, you would just go into the post folder and then everything you need is there. All of your files that have to do with posts there. And as Harris said, it reduces the surface area if you're in one area. You're not scattered all over the app.

Robin Heinze:

One good way to think about it in terms of mobile apps could be like if you have an app that has a tab bar and you have like three or four tabs that sort of section your app, each one of those is probably a particular domain that you would be dividing your app into.

Harris Robin Kalash:

I'm actually not a huge fan of that architecture. I think I can see the benefits for large teams, but typically I work in very small teams and I don't really feel the benefit of it personally. But, I can definitely see how if you’re Airbnb that would greatly benefit you.

Adhithi Ravichandran:

I used to work for a team which was quite large few years ago. And we had the shared codebase across four or five different UI teams. So the only way for us to not step onto each other's toes was doing the DDD folder structure. So we know for sure, “Okay, this is our team. We won't even touch any of those guys.” Let's say there was a documentation team, we wouldn't touch anything that's under the document folder. There will be a ton of stuff and then I would be in the orders team. So, I'll just focus on the orders. So that helped if you were working with teams that you wouldn't even meet and have any interaction with, but for some reason, architecturally, you're sharing that code base. But, I personally wouldn't use this model for smaller projects. Jamon Holmgren:

A lot of times-- Well, I guess when I started programming more in earnest in 2005, I grouped things... Here's Jamon again going back into the old days. I remember the very first websites I started building, I used the flat folder structure because it was index dot HTML and about dot HTML, this was not rocket science. And then I started using PHP because it's kind of weird, but I wanted to say Copyright 2005 and then have that automatically updated to 2006. [laughs]

Robin Heinze:

That was your only reason for switching to PHP?

Jamon Holmgren:

And this is why I am here today.

Robin Heinze:

That’s hilarious. Wait, it was like jQuery not a thing? Or like--

Jamon Holmgren:

No. Well, jQuery was definitely not a thing. There was JavaScript. I could have done it with JavaScript.

Robin Heinze:

You could have realized that that would have--

Jamon Holmgren:

No jokes. Yeah. And the other thing though, Robin, it wasn't just that. I also had to rewrite the menu in every page because like in HTML file you can't include another one.

Robin Heinze:

Right.

Jamon Holmgren: 

So that was the other thing. So that was actually pretty big. So PHP, I could include files and I could of course do the whole date thing. So I actually created a folder just called library, and I would put common files in that folder. I would have like header.php, footer.php, et cetera, functions.php. I remember writing that like, "Oh, I just need a function that does whatever." That, of course, quickly became not inadequate. And so I had to do something different. I actually eventually wrote my own framework, and it was called PHP Genesis, it was really cool. I still think it was one of the coolest, most productive things I've ever worked in. I had folders in there, I had a pages folder, and I had a models folder. So, this is the other more common way to go about it, is to split things up by what they are. So you have components, you have controllers, you have models, you have routes, maybe if you're in a web context, you might have many other things, i89 may be a thing. So, you're splitting them up by what they are. And I remember, when we started doing Rails in 2010, it was like, "Okay, so they already have a convention here." They have your app folder and inside of your app folder, you have controllers, you have models, you have views. And if you want to create a new route, you would create a file and each of those pretty much. You're going to be touching files in each of those. That was my other experience with this and it worked pretty well but you're definitely touching a lot of different folders when you're creating or editing something. Robin, you worked with Rails, what was your experience with that?

Robin Heinze:

Well, when I was working with Rails, I was still so new to programming cuz that's what I learned on, that's the framework that the boot camp that I went to used. And so, I wasn't really in a position to have any opinion about folder structure because the way I was bringing it in was just like, "This is just how it is." And I didn't really know any different. And now it's been four years since I've done Rails. So, I honestly don't remember how I felt about the folder structure because it was just what you did, that's just the way things were.

Jamon Holmgren:

It's usually not worth it to try to fight convention in a situation like that. 

Robin Heinze:

Well, especially with something like Rails where it's so widely used. 

Jamon Holmgren:

Yeah. 

Robin Heinze:

And with Rails, convention is the point. 

Jamon Holmgren:

Yeah. 

Robin Heinze:

Was it the official model of Rails, convention over configuration?

Jamon Holmgren:

[laughs] Pretty much, yeah, I think it is. 

Robin Heinze:

So, you do it the way that everyone does it because that's just what you do and it makes it easier to have a shared experience with all the other Rails developers in the world.

Jamon Holmgren:

Exactly. I was a tab indentation person when I was using PHP. And when we moved to Rails, I was using tabs in one of my programs. I was like, "Hey, everybody uses space, two spaces in Ruby." I'm like, "Yeah, but tabs are better." [laughter] And he told me something I've never forgotten, I actually really appreciated it. He said, "Sometimes standard is better than better." 

Robin Heinze:

Standard is better than better. Yeah.

Jamon Holmgren:

I was like, "Oh, you're right. It is better than better."

Robin Heinze:

But really, spaces are objectively better. Let's just settle that right now.

Jamon Holmgren:

Really? We're going to have this right now? [laughing]

Adhithi Ravichandran:

I remember being in code reviews where the only comments will be spaces, spaces, at spaces, no tabs. I'm like, "Dude, review my code." 

Robin Heinze:

We should have a whole segment about spaces versus tabs. But, that's can of worms.

Jamon Holmgren:

I'll leave all my snarky comments for that.

Robin Heinze:

But, yes, it's a good point that standard is better than better.

Jamon Holmgren:

I'll tell you what, I have used spaces ever since. If I start a brand new project that nobody will see except for myself, I still use spaces, but I still maintain the tabs are better. Anyway, don't you use prettier? Yes, that's the whole episode.

Robin Heinze:

"Standard is better than better."

Jamon Holmgren:

Standard is better than better, I actually really like that. And there are situations where you should jump out of that and do something different but it should be deliberate. It shouldn't just be, "That's my best preference or whatever."

Robin Heinze:

It's been a long time since I did Rails, but I do remember the feeling of being able to open anybody's Rails project and know where I was. And that is absolutely not true with React Native or probably pretty much any JavaScript framework.

Jamon Holmgren:

I think you hit on something really key there, and that is just being able to jump in and have a common understanding of where things are. So, if we were to bring this back to a construction crew analogy, if you were a person who maybe goes between several crews in a particular month maybe, and one crew has their truck setup one way with all of the hand tools are in the front and all of the power tools are in the back and all the nails are in the middle, then you get used to that. And then if you were to go to another crew and they have their power tools, with the nails that they need, and the hand tools that tend to go with that power tool all in one box in different spots, it would screw you up. And if you're trying to get some work done, you'd be running around the truck trying to find the right tool. And I've actually experienced this. I work construction so I know what that's like. That would get very frustrating. And developers often will jump between projects, especially consultants like we are. So, when you can jump from one project to another and instinctively know exactly where to find things so you don't even have to think about it you just grab it and you go, there's a lot of value there. I think that there are differences between different approaches, and there's different trade offs. And some are objectively better than others in some ways, certainly at least to my mind.

Adhithi Ravichandran:

We need universal folder structure in React Native.

Robin Heinze:

Okay, so let's talk about specifically React Native projects.

Jamon Holmgren:

So, one of the things that jumps out to me, you mentioned this already Robin, is the Android folder structure. It's very deep, it just keeps going and going and going. And to me, there's this tendency programmers have to want to really get it pedantically correct with their folder structure, they really want to do this.

Robin Heinze:

They're trying to convey meaning and categorization by having a folder that has a main and something else.

Jamon Holmgren:

Yes, I think it's test.

Robin Heinze:

You're communicating to the developer that what they're going to find in this folder is specifically related not to testing but for communication.

Adhithi Ravichandran:

The Android folder that we're talking about since it's all in Java, I've noticed that other teams, with Java, that's the convention they use to drill deep into that folder structure.

Robin Heinze:

A Java developer can feel at home inside the Android directory.

Adhithi Ravichandran:

Right. So I think that's what it represents, the Java conventions.

Jamon Holmgren:

Yeah, and it's also where I think, Android Studio would find it. I think if you put it somewhere else than Android Studio, it wouldn't find it. You'd have to do some configuration or it wouldn't even work, I don't know.

Robin Heinze:

Who knows? 

Jamon Holmgren:

And this is a little bit of one of the challenges of React Native, you're working within two other ecosystems not just your own, you have iOS and you have Android. It's interesting though because you're just trying to find your main application file. Of course, Android makes sense, but then you're at appsourcemainjava.com/myapp, and then you finally find the main application. If you're drilling down, you're having to make these decisions every time. So, instead of having a main and a debug folder, you could have that at the end of the tree, at the node. You could have a mainapplication.java and you could have a debugapplication.java or something like that. I'm just spitballing a little bit here.

Harris Robin Kalash: 

I could be wrong but with Android, I don't know if it's just for communication, cuz unlike JavaScript projects you actually do get something by following their structure for free, right? For example, when you run like a release versus debug, you don't have to worry about which activity file to use. Yeah, you do get certain benefits that if you don't follow their structure, you don't. Whereas, JavaScript, you don't get those benefits, anyway.

Jamon Holmgren:

Yeah. Yeah, it makes sense. And we're playing in their playground so we have to be good citizens and use their folder structure, it's fine.

Adhithi Ravichandran:

Think about it, how often do we even drill into those folders? If you're using Expo, you're not even going to look at it. And even if with React Native CLA, I hardly ever go into that folder at all. 

Robin Heinze:

The only reason I ever go in is if I'm doing  a one off release build and I have to go find the build artefact.

Jamon Holmgren:

Yeah. Yeah, that makes sense. 

Robin Heinze:

Right. So, it's not like a daily problem they will face.

Jamon Holmgren:

The last thing I need is some obscure native error that took me the whole day because I needed to put something in the right place. [laughing] Once I put my keystore in the wrong place, I was spending hours trying to figure out why it wouldn't read it. So, I think we're all in agreement there, use whatever the conventions are there. But then once you get to the JavaScript side, what you get with React Native in it is an app.js file. You don't even get any folders. So, I guess what they're telling us is they want all of your code in one file.

Robin Heinze:

That would be the conclusion that you could come to. That's the official React Native stance, is everything in app.js.

Jamon Holmgren:

It is, let me go find my ending comments.

Adhithi Ravichandran:

While we're talking about this, I should give big kudos to Infinite Reds, the Ignite boilerplate. So the very first time I was doing React Native, one of my teammates and I were like, "What folder structure do we use? How do we put these things?" And I'm like, "Hey, there's this cool thing called Ignite." I think it was version one. And we're like, "Let's check this out." And it came out with the boilerplate and nice folder structure and we used that for a couple years. 

Robin Heinze:

That's actually a really good segue into like, where do you go from app.js after you have emitted your React Native project?

Jamon Holmgren:

So, we ran into this early when we started using React Native. We had our native structures that we liked, but we had to come up with something for that. So, we had a lot of discussions, and we came up with what you saw in the original Ignite. And that was like an app folder. it had components, screens, styles I think, we're in their own folder, tests, fixtures, models. Actually, no, we were using Redux so it would have been reducers and things like that. Yeah, sagas. So yeah, those were all what came out in the original Ignite. And that worked really well. We then went to a different architecture, later. One of our engineers really wanted to explore a different direction. And Robin, I don't remember if you worked on the original Bowser, if you did any apps that were in the original browser one.

Robin Heinze:

I don't think I worked on it. I do vaguely remember the original presentation that he made about it, and it was very domain driven. I think there was at least one project that I did that was on that very very first iteration of Bowser that was very domain-driven. 

Jamon Holmgren:

I remember one of the discussions being our screens components. 

Robin Heinze:

Yes. 

Jamon Holmgren:

Yes, 100%. I want to ask you, Harris, our screens components, should they be in the components folder?

Harris Robin Kalash: 

I don't think so.

Jamon Holmgren:

Yeah. Technically, they are components. Everybody agrees they aren't. 

Robin Heinze:

Oh, yes, that's the answer, right? It's technically yes, but they're special.

Jamon Holmgren:

But they're special, exactly. And you see this also with things like layouts or pages on the website things.

Harris Robin Kalash: 

Yeah, and again it comes down to communication, right? If I see screens and components, how do I differentiate? And then, do you want to nest more folders and component? Maybe you can nest screens and components, but then what do you do with actual components?

Robin Heinze:

Yeah, they have different roles. In a lot of cases, your screens are going to be what's hooked up to your state management. There's a lot of differences and I think it's important to communicate that.

Adhithi Ravichandran:

I think this is one of those things where maintaining that standard really helps so we know for sure. Okay, what they mean, we don't want to go into a React Native project, and look at screens inside components, although they are components.

Jamon Holmgren:

Yeah, I think, originally he won on that and he did put screens in the components. In fact, they weren't even in their own folder. It was just mixed in with the other components; login screen was next to button or whatever. 

Robin Heinze:

If that's how he did it, it didn't last very long. I don't remember that being.

Jamon Holmgren:

I think he even hated us.

Adhithi Ravichandran:

I think the Ignite that I checked out so many years ago didn't have that. It had containers and components.

Jamon Holmgren:

Oh, yeah, containers.

Robin Heinze:

Andros does have containers.

Jamon Holmgren:

Containers were basically screens, I guess.

Robin Heinze:

I think we just called them containers. 

Jamon Holmgren:

Which I hated, I did not like that name. 

Robin Heinze:

They were screens. 

Jamon Holmgren:

They were screens. How would you think of it if you looked at it in a design. 

Robin Heinze:

It's a screen. 

Jamon Holmgren:

There's sort of the pedantic thing that, well, sometimes they're not the full screen. Sometimes, it's a partial pop-up or something like that.

Adhithi Ravichandran:

I still go with the containers convention with most of my products

Jamon Holmgren:

Oh, you do? Okay. Well, I hate it.

Adhithi Ravichandran:

I do agree with the note that it could sometimes be half the screen, like the word containers because of that. There could be sliders and stuff that you can have. 

Jamon Holmgren:

You're not wrong. You're not wrong. 

Adhithi Ravichandran:

So, but, yeah. Yeah. Screen container, same thing in my head.

Harris Robin Kalash: 

I think it made a bit more sense when we were using higher order components because then your container could just be an HOC.

Jamon Holmgren:

Yeah, that makes sense. 

Robin Heinze:

Oh, yeah. 

Jamon Holmgren:

And that's what they were, so that totally makes sense to me. But, I've always been pragmatic.Even PHP Genesis, I mentioned this earlier, I created a PHP framework. It was pages, the way that I model it I guess in my mind isn't about how I'm accomplishing it, it's what the thing is. And so, the fact that I'm having to reuse a piece of technology called components to create a screen doesn't matter to me, it's a screen.

Robin Heinze:

Right. We have to separate the concept of a react component, the technology from the concept of a little reusable movable piece of UI, essentially.

Jamon Holmgren:

One thing that we also did was we had a styles folder. And I certainly know for websites, I used to have a styles.css file. Just one, and I would just dump everything in there.

Robin Heinze:

Oh, yeah. It felt like having a separate styles folder, was somewhat of a carryover from web where your styles are always separate from your UI layout.

Jamon Holmgren:

And that had to do with the technology too, cuz you were importing it differently on the front end. So we actually then, with Bowser and this was something that has stuck, included the styles with the component. So it'd be like login.ts, and then we have login styles.ts.

Robin Heinze:

Well, I don't actually know what the current iteration that Bowser has. But in most of my projects that use Bowser stack, styles are not even in a different file.

Jamon Holmgren:

They're in the same file.

Robin Heinze:

They're in the same file.

Jamon Holmgren:

And why do we do that?

Robin Heinze:

Because I got really tired of needing to change a style. Especially if you're debugging, if you trace it to the component and then you need to change the style and you're like, "Now I have to find the style." and open that up, versus scroll a little bit and there it is. 

Jamon Holmgren:

A little bit of friction there.

Adhithi Ravichandran:

Typically, if I have a bunch of components, I would have the styles within the styles folder which is just one step above it. So I would be like okay, header component and then we'll have a header style file for it.

Jamon Holmgren:

Yeah, there are a lot of different ways-- I actually have a lower sort of what we call "gaffo" which is how much I care about it. We've probably explained that in other podcasts. Yeah, it's basically a one to 10. One is I don't care, 10 is I will literally quit if you do this. [laughing] And so, I have a low gaffo on the whole styles discussion, but I do know that a lot of our teams like to put them in the same files, or at least in the same folder.

Robin Heinze:

And it's the same for tests, too. 

Jamon Holmgren:

Yeah. 

Robin Heinze:

Co-locating the test file right with a component.

Jamon Holmgren:

How much do you think the sort of awkwardness around importing where you have ../../../../? It kind of plays into this. If every import started at the root, at the app, and you just immediately had styles/mycomponentname, do you think that that would affect our psychology around it? Cuz then it would start feeling more natural, style slash whatever is and that's where I'm importing my styles from versus ../../../../ styles. [laughing]

Adhithi Ravichandran:

We also have web app and stuff that can help with these folder namings, you don't need that many dot dot slashes. But I agree. I think with styles, as long as we keep it close somewhere either within the same file as Robin mentioned or in name and closeness around the location, I think it should be okay. And sometimes it's just muscle memory, you know this is cuz you've been in that project for so long. 

Harris Robin Kalash: 

The way I see it, it's not just about the path. Let's say you want to delete a component, right? You probably want to delete its test and styles at the same time. So, you just go in that folder and just delete the whole thing.

Robin Heinze:

That is definitely an advantage to the colocation strategy. 

Jamon Holmgren:

Yeah. Ryan Florence once described it this way: How do I know that I can delete this file, basically? If you're colocating everything-- I don't think I actually did justice to how he said it-- But it's basically the idea of how do I know I can delete a style. And if you're in a styles.ts file that's at the root, you're not going to know where is this being used. If you are in a folder or even better, in the same file, you know where it's being used. It's not being imported anywhere else, it's right there. And so, the kind of more generic that you make something, it's more reusable but the more harder it is to determine who's using it. There is a trade off there. But of course, we're not going to necessarily just put our model or store in the same file. If we did that, then we would have hooks. [Jamon and Adhithi laugh] Sorry, I joke. But if you have a centralized store, you probably are going to put it somewhere central. And so, that's a tradeoff. We generally don't need to worry about it as much. It's not like styles where things move around as much when you're modeling your domain, you generally know where things are. So yeah, I think that that's a piece of this as well. Okay, so we've done a lot of and we hinted around our preferences, I think. The audience probably has somewhat [Jamon laughs] of an understanding of where we stand on things. But I'd like to actually ask each of you, what is your favorite? All of us agree if you're jumping into a project that already has a standard, you're going to use the standard. But if you're in charge, if you're the founder of the startup and you're the CTO or whatever, and you're creating the new app, and you're just starting from scratch, what is your favorite folder structure? How do you like to approach this? Adhithi, let's start with you.

Adhithi Ravichandran:

So, the way I usually do it is if the app needs also web version, then I would completely separate them out. I would have app components and web components, that way the components are separated unless we're using something like React Native web. And I would have the typical assets, folder, fixtures, services, and all of that stuff. And I'd like to keep the Redux portion-- if I use Redux-- separated out. So, Redux will be in its own folder. And all of the custom hooks too, I keep them in a separate folder. And then within the app components, I would have the containers or screens, and then I would have components. And with React Native, we would have the entire navigation folder, which has all the navigation items. And specifically the styles, within the components, I would have a styles folder, and I would have a separate styles file for each component unless there’s a lot of sharing that goes on. I would name the component... I don't like to do a lot of generic stuff, so I like to keep it specific. So, I would have a header, or footer, slider, whatever. And then I would have the styles have the same name and then say header component style.js. 

Jamon Holmgren:

Okay. That's what I've been doing. And I do have usually, a library folder that would have utils and things like that. Definitely, like to keep all of the business logic separate and Redux separate and have the UI components just literally do that job.

Jamon Holmgren:

Yeah, that makes sense to me. It's actually very similar to the initial version of Ignite, what we came up with there, and I think it's a very common pattern. 

Adhithi Ravichandran:

Yeah. 

Harris Robin Kalash:

I'm curious, do you guys usually put the hooks in a separate folder outside of components?

Adhithi Ravichandran:

So, within components, I would use the simple hooks like use effect, or use date and all of that stuff, but if I have a custom hook, I would put it separately. Yeah.

Harris Robin Kalash:

I see. Okay. Interesting.

Jamon Holmgren:

We don't use a lot of custom hooks in Infinite Red because we use MobX-State-Tree. But Robin, what do we do if we are creating a custom hook?

Robin Heinze:

It depends on what it's for. We really don't do it very often. But the ones we've done recently, I think have just gone into a utils folder or a helper folder. 

Jamon Holmgren:

Yeah. 

Robin Heinze:

Not co-located with the components.

Jamon Holmgren:

And the fact that it's a hook doesn't necessarily differentiate it from other utilities. It's just--

Robin Heinze:

Exactly.

Harris Robin Kalash:

It may in the future if we start doing it a lot more. It's been such a one-off scenario so far.

Jamon Holmgren:

Yeah, makes sense. I do know that we have one in the model’s folder for use root store and so--

Robin Heinze:

Yeah, or use stores.

Jamon Holmgren:

Use stores, actually. Yeah. So, it pulls it from the model’s folder because that's where you're grabbing the root store.

Robin Heinze:

I consider that part of the definition of the root store or part of the configuration of the root store.

Harris Robin Kalash:

With the exception of root store, when I was working with Yulin, we've actually just put them into components and I find that it's easy to differentiate because it starts with use, right? That's how you differentiate it just from the initial word. And that's-

Jamon Holmgren:

And Yulin, of course, is senior software engineer at Infinite Red that Harris has worked with. [crosstalk] Hey Yulin, I'm sure you're listening to this. [Jamon and Harris laugh] Robin's shaking her head. [Robin laughs] Yulin will not listen to this. [Jamon and Harris laugh] But Harris, what do you mean? You have app/components/use something?

Harris Robin Kalash:

Use interval, use whatever it is, use location, we would just put it in the components folder. And I actually like it because at the end of the day, it is a component you might return. In JSX, you might return an object. The way you differentiate it is just because it starts with use. So, I don't think we have a convention at the end for the tread because of... Yeah.

Jamon Holmgren:

And a lot of times, we do have conventions about some things, obviously, but the primaries have a lot of freedom within that and then even to go beyond it in certain cases if they can make a case for it. But yeah, with custom hooks, it's just not a very big topic. So, Harris, with that said, if you were starting your own project for your own startup or whatever, how would you organize your folders and files?

Harris Robin Kalash:

I really like Ignite, so I would just do that. [Jamon and Harris laugh] Yeah.

Jamon Holmgren:

Yeah, describe that. Describe how that looks.

Harris Robin Kalash:

Typically, you'll have your store or models, which is where all the MobX-State-Tree models live, whether it's a store, or just an individual model, they all live there. We differentiate by naming the stores. The stuff that are the child of the root store, will have usually a dash store at the end. And any specific entity like a user or whatever, will just not have the dash store. [crosstalk] Yeah. And then components and screens and navigation folders. And I think that works really well. And I would put my hooks in components.

Jamon Holmgren:

And you put your co-locate your styles in the files with the components.

Harris Robin Kalash:

Yeah, I would co-locate my styles. If I'm using style components, maybe I would create a new file. But typically, I'll just have the object there and co-locate everything. And one thing I tend to do is I always have three files per component. So usually, it'll be button.props.ts, then it'll be button.presets.ts, and then button.tsx, so yeah.

Jamon Holmgren:

And Robin, if you're starting something, what's your favorite way to approach it?

Robin Heinze:

Well, I think I'm supposed to say Bowser. [Jamon, Adhithi, Robin, and Harris laugh]

Jamon Holmgren:

You are supposed to say, wow. Say whatever you want. It’s just your job on the line. [Jamon and Robin laugh]

Robin Heinze:

I do actually really like the way the default Bowser stack. There's a reason for that. I'm in control of what Bowser looks like, to be honest. I'm part of the team that builds it. And so, at this point, if it wasn't a stack that I enjoyed using and made sense to me, it probably would have changed by now. So, I really like Bowser. I really like that it's a hybrid between true domain-driven design and more of sort-by-tech approach.

Jamon Holmgren:

It is a hybrid, isn't it?

Robin Heinze:

Well, because we do separate the state management files, the [unintelligible 50:18.02] stores are separate. Even if you have a user store and then you have maybe a profile screen, those aren't co-located. You have your stores and you have your components and all that separate. But I do really like that you have little units. So, you'll have a component folder, and within that folder is the component file itself, the storybook file if there is one, any assets that it needs that I really like if that specific component takes us an image rather than having a big old bucket of images at the root of your project. If you have an image that's only used by this one component, it's right there in the folder with it. Same goes with models. If I have the model has a test, it's in the same folder. If the model has a really specific helper that I just want to move into its own file, I'll leave it in the folder with the model. Yeah. And so, it makes it so that if I want to delete something, it's really easy. Just delete the whole folder. I think if I were doing a side project or just playing around with something, I would probably leave it pretty flat. I'm a big fan of not optimizing for a problem that you don't have. So, I'm more inclined to just have my app JS file and maybe a separate component file, but just not bothered adding any folders. But for a legitimate full-fledged app, I usually go with Bowser.

Jamon Holmgren:

Yeah, awesome. And by the way, by the time people listen to this, they'll probably have heard that we also have moved away from Bowser toward a new rewrite Ignite six, which is codenamed Flame. But it's basically the same. There's really not a major difference between Bowser and Flame. The main thing is just an architecture change.

Robin Heinze:

Right. The stack is really similar, but the tooling around it is different.

Jamon Holmgren:

The tooling is different. Sorry.

Robin Heinze: Yeah.

Jamon Holmgren:

Yeah, the tooling is different. So, when we say Bowser, we really mean the latest version of Ignite, which is we've gotten away from having the boilerplate be separate. For myself, I would agree really with what you just said there, Robin, I'm very similar, that Bowser… See, I just said it, Ignite really does mirror my thinking there. I'm very pragmatic when it comes to this stuff. I'm not ideological. I want to see empirical evidence. If people want to try something like we did early on, when that developer wanted to experiment with more of a domain-driven focus, we experimented. And we found out that there were things about it we didn't like and we actually backed off on some of those things. That's actually why we ended up with a hybrid. We went full DDD and then we came back halfway toward the original Android’s structure and kept the parts we liked about both, which was really cool. I like that approach. Be pragmatic about it. I will mention one more thing. We are working with a client who has dictated the structure of their app. Totally happy to do that as a consultancy, we're flexible. And they use learn packages just everywhere, just tons of packages. And so, as an example, screens are not even in their app package at all. Screens are in its own package and you can drill down and see, log in and register. And then underneath that, then there's register, and then you'll see styles and the index.tsx.

Robin Heinze:

So, did they give you an already developed product and asked you to enhance it? Because how did they already have like an app structure?

Jamon Holmgren:

Well, it was basically a CTO. So, this happens regularly, where it's a CTO who came to us and said, I need React Native experts to work with me, [crosstalk] to help me. I don't have enough people on my team to do it. Actually, I think he's the head of mobile development at the company. And so, we provided two, now we're actually up to four developers, and we're going to come back two after a bit here, but they are working with that person. He is the lead and our developers are secondary developers on that. And they're providing their expertise. They've both been working in React Native for five years, so they know a lot. And he's really just been working [crosstalk] for about six months or so. But he's also a very accomplished, very well experienced developer in his own right. And so, he came in with a lot of ideas about how he wanted to structure it and [crosstalk] certainly been just working within the direction he wants to go there. Certainly, there may be decisions he's made that we wouldn't necessarily go that direction, but he's also been open to feedback. He asked me, he was saying something about the whole screens and components thing, that was coming up. And I said, “Technically, you're right. But [Jamon laughs] I have found in practice, that separating screens out into their own thing helps for just discoverability and things like that.”

Robin Heinze:

Yeah, it helps with the mental model of your app because you can think about your app in terms of like, “Okay, this is the screen and this is the screen.”

Jamon Holmgren:

So, I think we've successfully beaten this topic to death. So, let's move into [crosstalk] weird bugs, the part of the program where we talk about weird bugs that we've encountered along the way and maybe how we've solved them, or if we still haven't solved them.

Adhithi Ravichandran:

I have a weird issue I encountered and it's not necessarily a bug, it's more of a compatibility problem. Maybe the listeners can benefit out of that, too. So, I was trying to upgrade this project and I was like, “Why aren't you using Hermes engine?” So, let's go ahead and utilize Hermes and we upgraded to React Native latest version and all of that stuff, but Hermes just wouldn't work. And I ran into a lot of errors. And it took me a couple of days to realize that the project was using React Native Firebase. And apparently, if you have React Native Firebase, then you can't use Hermes. So that was an interesting thing to note which I wasn't aware of.

Jamon Holmgren:

I wonder if it has to do with proxy support or something along those lines because I know that Hermes hasn't had proxy until [crosstalk] more recently.

Adhithi Ravichandran:

It's a deadlock there because they really want to upgrade to Hermes to improve the Android performance, but getting away from React Native Firebase is not an easy task either because that would involve a lot of rewiring and rethinking.

Robin Heinze:

A lot of people use Firebase, too.

Adhithi Ravichandran:

Yeah. So, it's a deadlock situation there, so I hope somebody somewhere fixes this.

Jamon Holmgren:

I'm going to give a free little commercial spot here ad for my friends over at Invertase. I actually don't know how to say the word, Invertase. They are the people behind React Native Firebase and they are consultants, good friends of Infinite Red. And definitely, go talk to them. I'm sure that they can help you out.

Adhithi Ravichandran:

Very cool. Yeah.

Jamon Holmgren:

So, but yeah, that's them. I've always had really good luck talking with those folks when I've had problems with React Native Firebase. They're really good engineers. I think they're based in the UK.

Adhithi Ravichandran:

Okay. I just see a pull request on the Hermes on React Native Firebase a few months ago, and they responded saying that the JavaScript engine from Hermes and React Native Firebase has some compatibility issues. So hopefully, they work on it. It's probably not an easy to ask. 

Jamon Holmgren:

Yeah. [Jamon laughs] Yeah, no kidding, brand new JavaScript engine. Robin, I think you had a weird bug as well. You want to dive into that one?

Robin Heinze:

I did have a weird bug, one of those lovely date-related bugs. So, what happened was, we got back to work in the New Year and all of a sudden, we were getting a test failure [Jamon laughs] that we weren't getting before, which is always you are like, “Something's date related.” [Jamon laughs] The test was testing a function on a person model. So, the model was for a person and we were calculating their age based on their date of birth. And the date of birth, the format that we get from the server is just a day value, a month value, and a year value. So, we would assemble those values into their birthdate and then compare it to the current year to get their age. So, what was happening was the test filler said their age was off by one year. And so, at first, I thought, “Well, okay, so that means we just, it's a brittle test. We didn't account for offsetting it.” The person just turned a year older when the New Year happened and so I just need to make the test less brittle. And I get into the test and we've already accounted for that. We're already adding or subtracting an offset from their age to account for that. And so, I look closer at the test failure, and it's actually in the opposite direction than I would expect. [Jamon laughs] And so, I look closer at the age function, I'm like, “What? What is wrong here?” [Adhithi laughs] We're offsetting correctly, we're doing the subtraction correctly. 

And then I hover over the date initialization, where we're taking the three values and making them into a birthdate. And I look at the tooltip and it says that the month value starts at zero [crosstalk] [Robin laughs] because for whatever crazy reason, JavaScript dates index the month using zero index rather than the more logical month of the year, with January being one. [Jamon laughs] And so, of course, the way you would write a date is one dash whatever. [crosstalk] So that's what we were putting in. So, it was actually thinking that this person's birthday was a month later. So, our test assumed that they had already aged up by a year, but the calculation was thinking they were still a month younger than we were thinking they were. [Jamon laughs] So, don't [Robin laughs] let that bite you. JavaScript dates, the months are zero and less.

Adhithi Ravichandran:

Interesting.

Jamon Holmgren:

Yes. What was the actual feature? Was it actually something to do with their birthday, or it was just a-

Robin Heinze:

So, the feature was just that we needed to check their age for if they're over 65 for some reason. So, we just needed to know how old they were.

Jamon Holmgren:

It was healthcare-related situation. Yeah. And I think this comes from way back in the day, this decision was made for some reason. I think it was a POSIX thing way back in the day or something like that. Basically, yeah, the decision was made a very long time ago and it has never [Jamon laughs] it’s influence things ever since. But I'm sure that it's the source of many bugs having that. Because the assumption, a day luckily, is one bit one index. Can you imagine if the days were not one index if they were like, “Hey, November 29th is 10.28.” 

Robin Heinze:

Yeah, very bizarre.

Jamon Holmgren:

Everything would be so bad. But at least, it would be consistent. Okay. Well, people can find us on Twitter. You can find the official Twitter handle @reactnativerdio, React Native Radio but missing the A there. You can find Harris @nomadicspoon, Adhithi @adhithiravi. You can find Robin @robin_heinze with an E at the end. And you can find me @jamonholmgren all on Twitter. Feel free to hit us up and let us know what you liked about the episode. If you have complaints, you can keep them to yourself. [Harris laughs] I'm joking. It's fine. You can DM me. I have opened DM’s, hit me up. And as always, thank you to our producer and editor Todd Werth. Also, my co-founder of Infinite Red, and our transcript and release coordinator, Jed Bartausky, and our social media coordinator, Missy Warren. Thanks to our sponsor Infinite Red. Check us out at infinitered/reactnative. Special thanks to all of you listening today. Make sure to subscribe. Tell a friend. Of course, we'd love to have more people tune in to React Native Radio. So, if you like this episode, send it to a friend, please. That would be very, very cool of you. And thanks again to all my co-hosts for being here today and we will see you next time. Bye.

Robin Heinze:

Bye.