Front End Architecture - JSJ 522

JavaScript Jabber

A weekly discussion by top-end JavaScript developers on the technology and skills needed to level up on your JavaScript journey.

Front End Architecture - JSJ 522

Guests :
Published : Feb 22, 2022
Duration : 1 Hours, 13 Minutes

Show Notes

In this episode, the Jabberers sit down with Gil Fink, a Microsoft vet and Google developer who’s gonna convince why having front architecture is a no-brainer. They discuss what differentiates it from components, how “memory floods” are washing away developers (and why they’re causing them!), and the BEST way to move between architectures without losing your mind.
“You need to understand all the moving parts in your architecture.”
- Gil Fink
In This Episode
1) What makes front end architecture VERY different from components
 2) The BIGGEST problems around “prop drilling” between your components (and how libraries really help)
 3) How “memory floods” overwhelm developers…and why they don’t even realize they’re causing them!
 4) The CORRECT way to move between architectures without screwing yourself
On YouTube
Front End Architecture - JSJ 522
Sponsors
Picks
Special Guest: Gil Fink.
Sponsored By:

Transcript



CHARLES MAX_WOOD: Hey everybody and welcome back to another episode of JavaScript Jabber. This week on our panel, we have Steve Edwards. 

STEVE_EDWARDS: Hello from a sunny and cold Portland. 

CHARLES MAX_WOOD: AJ O'Neill. 

AJ_ONEAL: Yo, yo, yo. Coming at, oh gosh, it's kind of freaky outside. It must be the inversion. Come and let your life from the inversion. 

CHARLES MAX_WOOD: The inversion. Now we'll have to explain what the inversion is.Dan Shapir. 

DAN_SHAPPIR: Hey from Tel Aviv, where it's 50 degrees Fahrenheit or 10 degrees Celsius. You tell me whether that's hot or cold. 

CHARLES MAX_WOOD: I'm Charles Max Wood from Top End Devs. And before we introduce our guest, I think I will explain the inversion really quickly. So in Utah, a lot of folks live in valleys. AJ and I live in the same valley. And what happens is you have warm air in the valley and the cold air comes over the top of the valley. And so the cold air wants to go down, the warm air wants to go up. And so what?What winds up happening is it traps all of the pollution under the layer of cold air. And so then we all get to breathe our own fumes. We have a special guest this week and that is Gil Fink. Gil, do you wanna introduce yourself real quick? 

GIL_FINK: So hello everybody, I'm Gil Fink. I'm currently a owner of a company, a big consulting company called Sparksys. I'm a Microsoft MVP and Google GBE for web technologies. Coming from Israel like then. 

CHARLES MAX_WOOD: Nice.

 

Tired of explaining your absurdly high big tech cloud bills to your boss? Let me tell you about this cloud infrastructure company that's the talk of the tech world. The name is Volter, that's VULTR. They pack high performance cloud compute at a price that AWS and the other big clouds can't compete with. So reap the benefits of advanced networking features, managed Kubernetes, developer friendly API, and 20 global locations offering elastically scalable computing power. Over a million users have deployed on Volter in 60 seconds or less across 12 pre-selected operating systems with their own ISO. With pricing starting as low as $2.50 per month for Volter Cloud Compute, they offer plans for developers and businesses of all sizes. You can try Volter for free today by visiting Volter.com slash Jabber, and you'll receive a $100 credit. That's vultr.com slash jab. 

 

DAN_SHAPPIR: Yeah. I invited you over because we happened to meet in the context of a web conference. That's called the technology conference that took place in Israel a while back, right at the end of 2021 called the reversing. And we were both scheduled to speak there, but then Gail had an incident. 

GIL_FINK: unfortunately COVID-19 caught me and then the whole family and currently we're well and we're not sick anymore but I have coughing from time to time so if I'm coughing during this show I'm sorry it's not me it's COVID so unfortunately I had to cancel my session but I recorded it and people can see it in the YouTube channel of Reverse Sim Conference. Unfortunately, not live in person, but things happened. And I have to say something very, very interesting about the session and the topic, because the topic was fighting, sorry, using data visualization to fight COVID-19 and the speaker didn't arrive to give the talk because he had COVID-19. Okay. So this is a irony in its big irony.

DAN_SHAPPIR: Well, the other irony is that the Omicron arrived and basically threw all these strategies out the window. 

CHARLES MAX_WOOD: So, yeah, but that's the way we fight this stuff, right? Is we gather information and then try and revise where we're at and what we think will work. 

DAN_SHAPPIR: Yeah. In this case, we gather all the information, looked at it, and then basically gave up. 

CHARLES MAX_WOOD: Yeah. Well, the human race, if you hear me coughing, I had COVID last year. 

AJ_ONEAL: Well, we survived worse than that. 

DAN_SHAPPIR: We survived the black death, didn't we? I mean.

GIL_FINK: We didn't survive it. No, we personally people did 

AJ_ONEAL: So being being the nitpicky one that cares about the way words are used I don't think anyone here ever had kovat They had SARS-CoV-2 This kovat is a disease that needs to be diagnosed by a doctor Which generally is a complication the results from SARS-CoV-2 which means for example You contracted pneumonia and probably had to be hospitalized

DAN_SHAPPIR: Lucky lucky me has not contracted it in any way shape or form so far at least as far as I know 

GIL_FINK: And we hope you won't get it That's not fun at all 

CHARLES MAX_WOOD: I Wasn't that sick this time around? 

DAN_SHAPPIR: Oh, yeah, you've got it again. 

CHARLES MAX_WOOD: Yeah. Well, so in Utah there was a testing shortage They asked us not to test unless we needed to know what it was So we didn't die and since I wasn't sick, but everybody in my neighborhood had it all the people that I go to church with had it. So I'm assuming that's what it was. It could have been something else, the cold or the flu, but it really wasn't that serious. We just stayed home, except for the funeral we went to yesterday. 

DAN_SHAPPIR: You remind me of a friend of mine who got like, was really feeling under the weather, had the shivers, had the fever, had coughing and so forth, and kept on testing himself and always coming up negative and said that he basically couldn't understand how that could be. And I said, well, you know, there still is the common cold. It's still exists. 

AJ_ONEAL: There is flu out there. Yeah. Like in every winter season. 

CHARLES MAX_WOOD: Yep. I fully acknowledge it could have been something else. Yeah. It seems like everybody else was testing positive that had it. 

AJ_ONEAL: So I'm not saying that you didn't have SARS-CoV-2. 

CHARLES MAX_WOOD: And have my symptoms. Yeah. No, I agree. Anyway. We are way off on a tangent. Let's talk about running architecture. 

STEVE_EDWARDS: Way off. Yeah. 

DAN_SHAPPIR: Yeah. So that's our topic for today. Right? That's what we decided in the end. 

CHARLES MAX_WOOD: Yeah, absolutely. And I think Gil said that he loves iFrames when we were prepping for this episode. So, I mean, I'm going to bring it back on my website. 

GIL_FINK: Gives me a very big shiver like having a currently a warm blanket. 

CHARLES MAX_WOOD: There you go. Put a neck warmer on it'll make you feel better. 

DAN_SHAPPIR: I was wearing one just before the show for those of you don't get the joke 

AJ_ONEAL: Yeah, so I by the way, are we live this time or not? I don't see us live on the YouTube channel 

STEVE_EDWARDS: Yeah, I was just looking there too. I didn't see it. 

CHARLES MAX_WOOD: It says I will play with Riverside 

DAN_SHAPPIR: Yeah, let's just keep on going. 

CHARLES MAX_WOOD: Yeah, let's just keep going and we'll see what we're seeing. 

DAN_SHAPPIR: So Gil you Given the kind of jobs that you do, that you do consulting gigs for various companies, you get to mess around with the architectures of a lot of companies or different architectures that you encounter in different places. 

GIL_FINK: Not only encountering, but also imposing architecture because currently, for example, I'm doing something like in the last one and a half year, I'm working with the company and we are building a user interface for a huge machine, huge press machine for press offices and things like that. Then most of the architecture of the front end there is my own. Either I'm coming and I'm seeing different architecture and I evaluate them and try to help the companies to find the solutions for things that they didn't do well, or doing new projects or helping as the front-end architecture for new projects to build something new or something interesting. 

DAN_SHAPPIR: So given that, can you maybe start by maybe even defining for us what architecture for the front-end actually means? And how is it different from just saying MVC? 

GIL_FINK: Okay. So saying MVC is, is it's kind of an architecture. Okay. But, uh, when I'm evaluating or when I'm coming to a company and I'm, and they are most of the people that I talk with says something like, we chose react. This is our architecture. We chose react. We chose redux and boom, this is the, my, our front end architecture, but that's not that's not architecture. That's just technologies. So when you are picking technologies, you are doing something. This is the first thing, pick technologies. But when a project is getting bigger and bigger over time, then only picking some Redux or React and saying, this is our architecture, it's not going to stand the... and it's not going to scale. So when I'm saying...architecture, I'm saying how the data flow goes, how communication between the different models happen in our application, how modules are built, do we divide the vertical slice, the entire front end to different logical parts, do you give those parts to different teams, and etc. etc. So this is the kind of things that you need to ask yourself when you're starting to building a project if you need those things or how do you are going to build those things and then you can come up with some sort of ideas of how to build your architecture and MvC is one solution, but it's not only the only one out there. 

DAN_SHAPPIR: Well, from what I've seen in many cases, a lot of organizations, certainly not all, but a lot, not quite a number that I've encountered kind of punt on the front end architecture. Basically, their architecture is, you know, they can talk about the backend architecture because they've got all sorts of microservices talking to one another. They got this database and that database and whatnot, but the front end, well, that just makes some restful API calls, get some information, and more or less just renders it out. So what does it actually mean to have an architecture in the context of the front end?

GIL_FINK: Okay, so what does it mean? First of all, you need to understand all the moving parts in your frontend. It's like you're looking at a webpage. A webpage is built upon different logical parts. You can divide those parts into different models. For example, I can create a search model in the application or some customer's model in the application and then create different visualizations to those parts and you can divert some team, frontend team, to work with those parts. And so once you divide the application into parts, it resembles microservices in the back end. You have different parts that communicate with one another, and those parts, when you're composing them, you are creating your application. You can do that in different kind of ways. You know, Charles said iframes. Yes, iframe is one of...the solutions that you can create. You can divide all the parts into different iframes, and then you can create those parts with different frameworks. You know, the idea of microfontans, for example, is something that we're hearing a lot of, during the last three or four years. So there are different ways to create microfontans. And once you're...really dividing or thinking about your application in boxes of logical parts, then you will need some communication option. In some companies, the communication between the different parts is, you know, created using Redux. I see it a lot and it's not a good idea in my opinion. In other applications, like in the application that they're currently involved, we created You said MVC as something like a curse, but we created the containers, and each container, which is the smart components, for example, includes a logical part of the code inside some controller that talks with services, and those services are gateways to the backend. The same controller also talks with...Mobics, we use their Mobics as technologies to talk with or to get the information or the data that the smart component needs. And the smart component is just spreading data to the dumb components underneath. So this can be looked at upon some how you can create some closed system to handle some different logical parts in your application. Okay, so why? Would you bother do such a thing? You know, you can just create your webpage with the from bottom up or down to top with the react, redux, whatever, why to divide it? So, or why to use such an architecture, for example, like the dot project. 

CHARLES MAX_WOOD: Can I stop you for a minute? Cause you're kind of talking your way around a question that I have and I, I'm hoping that you can clarify it here. So a lot of people, they treat react like they're. architecture, right? It's like, well, I'm just going to architect all this stuff into components. Right. You were Angular kind of have the same ideas around organizing code. So why is that? Or isn't that enough? 

GIL_FINK: Because you need to understand that the components need to talk with the one each other. And that the idea is how to decouple the components in the components tree. I, when you are creating your entire webpage, you can create the created top to bottom with one component that hold the entire page and then a lot of different components there. And you can spread all the props in React, for example, all the props down the props drilling until the leaves. Or you can use some Redux or some Mobics or things like that. But this is not architecture. This is just component composition. 

CHARLES MAX_WOOD: Okay. Right.

GIL_FINK: So when you have component composition, it's a good idea. Okay, I'm not saying that it's not a good idea to compose components, but where do you put the communication with the server? Where do you do things like we used web sockets and we wrapped them with the RXJS and we need to get notification from the machine. I said we're building a press machine, a big machine. We have a lot of notification that comes from the server. Where do you put that part? How do you inject those notification or say to the whatever you put your data for the current component or things like that? So you need to think about those things. And if you're not doing separation between those concepts, data, services, components, then how do you test this thing? I know that a lot of people say, we can use unit tests on services or things like that. And it's fine. Or we are not going to do any unit testing. But in some projects, like in the project that I'm involved in, we're testing components. How do you test a component in isolation when you have relations or coupling with the data your data source or Redux or Mobix or things like that. So this is why we broke things a little farther. And we put most of the logic in the React hooks or in services. And we're testing the hooks and the services. And all the things that React is doing for us is just rendering, which is what React was created to do. library for rendering. 

DAN_SHAPPIR: I wanted to add to that something that you also kind of mentioned in passing which you know initially seems like something really really bad, but it's just the reality of things and it's the way it is that very often architecture of complex systems is dictated by how your organization is structured basically you say, you know, show me the components or the large scale components that comprise some software system and I can usually fairly straightforward way map it to your org chart. And now it seems silly, like why is HR effectively dictating the architecture of our software, but at the end of the day, very often that's just the way that it is. And given that that is the way that it is, that's another motivation to minimize the coupling between different systems within your software system, between the various subsystems. Because every time you have coupling, you're creating a dependency between one group within your organization and another group within your organization. And since they are working with different plans, they have different sprints you're creating a situation where one group can get stuck because another group, they are dependent on stuff that the other group needs to do for them because otherwise they just, for example, can't get at the data that they actually need. And for example, in React, you can see these sort of things where you need to kind of propagate props through parent components to the child components if you're not careful. And...That means that the parent kind of needs to know what all the descendants need to know in order to perform their operation. And that creates potentially a very tight coupling. And again, if that parent component is owned by one team and one of the descendant children child components is owned by another team, that other team that is responsible for the child component, if they need some additional piece of information, they can't actually even get it until that parent component provides it to them. And they're kind of stuck. And that's where you need to think, for example, about how data can flow through your system in ways that reduce such couplings. Would you agree with that Gil? 

GIL_FINK: I agree. And prop drilling is, it's something that is, is known not only in react, but also in the other frameworks like Vue and the Angular. And that's a that's a problem. And once the parent needs to know, because the parent is the component that gives all the props to its children, it needs to know what each and every children needs, then you have a problem. You don't have isolation. You have coupling between the parent and the child component. And in big hierarchies, for example, you can have a parent ancestor that is...like 13, 15, 20 depth 

DAN_SHAPPIR: levels. 

CHARLES MAX_WOOD: Right. 

DAN_SHAPPIR: Sorry. So, and in React, there is a solution that is called context. So there are those things, but context also is something that gives you some coupling on some inner internal React mechanism in order to deliver the data to the child components. So it's from one side helps you to avoid prop drilling, but in the other side, it gives you much more complexity to organize your code. And this is why libraries like Recoil and Mobix are very successful because they are trying to move you away from those ideas, the idea of drill all the props down to the bottom of the tree or to use some tools like, I'm going to say it, but I don't use React in the last one and 1.5 years because Redux, I have very different opinions about it. I won't get into it because it's a good, it's a good library, but it's, it's solving only one thing and from companies that I was consulting in, it became a big, big problem. Okay. 

DAN_SHAPPIR: So, yeah, what I've seen with, with Redux is that it if it, especially when it's taken to the extreme, it creates a situation where you put, you're effectively putting all of your state inside this, a single huge store, which is effectively a global object. 

GIL_FINK: Or you can say it, in memory database. It's like the entire database from your server will, in one point of the application lifetime, will sit inside your memory in your front end. This is one thing that I see a lot, that developers forget to clean the Redux store from time to time, and then you get memory flood. It's not memory leak because it's like, you're just using tons of memory to hold your entire database or some slice of the database in your front end. So this is one.

DAN_SHAPPIR: Yeah, and I see two additional problems with that. So obviously the one that you mentioned. Another one is that you no longer have a single source of truth because it's not an obvious guarantee that your local copy of the data that is stored within your Redux database will be identical to the one that's stored in the central server, as it were. So you can get consistency issues. And the other problem is that that database is globally available and accessible by every part of the system. And if we go back to the issue that I mentioned before, where you create situations where one group is dependent on another, and let's say group one is dependent on group two to provide the information, but group two is busy and group one is under pressure to deliver, well guess what they'll do? They'll bypass group number, they'll bypass that other group. They'll, they can access and access that global data store. And now you've created an, a non obvious coupling between that component and the structure of the data and the data store. 

GIL_FINK: Another option is they will use different, different way to, to hold their state. For example, I, I saw in the same project using different tools, like combining context because they had someone had to hack something because the other team was busy, as you said, in an application that is Redux-based. So yes, these are major problems that you can see. And this is why solutions like microfrontends that gives you vertical slices in your application and dividing your frontend into different vertical slices is more, it becomes, it's become more shiny to companies because you have only one ownership for each logical part. The team that is building that and the team is very specific working on the, you know, you said the in HR or, or things related to HR for the application that is built. But in the situation that I have in where we don't have a different different teams. We have only one frontend team. We had problems with things like the backend wasn't created faster, like we created the frontend and we had a lot of issues to build the frontend without the backend. So we created a simulator layer to simulate the entire backend to solve that problem, for example.

DAN_SHAPPIR: So let's say I decide to buy into that micro front end type approach of creating strong separation of concerns between the different components and avoiding some sort of a centralized data store that everybody can access to directly. And that kind of means that I need to create some sort of a data bus if I want to share the information between the various components. So what is your general approach there? Do you...Do you implement some sort of client side data bus or do you just have every component talk directly back to the back end? 

GIL_FINK: OK, so what you're referring to as data bus is some sort of event aggregator. So we created the, you can call it an event aggregator. In our application, it's just one place each and every model can sign to listen to different events that other models are sending. And if nobody is listening to some event that the model is publishing, then nothing will happen. If somebody is meaning another model is listening to the published event, it will do something. And yes, most of the time it...you will have to have some sort of some mediator that will be able to mediate between different parts, different models. This is one way to look at it. Another way is to say, okay, I want to divide my entire application to not logical parts, but web pages. And each web page is like my entire model. This is not you creating vertical slicing but rather horizontal slicing of the application. And this can create some difficulties between teams if some team needs to use some component from other team that is building another web page. So whenever those problems comes, then you will use another way of implementing micro-frontends, which is a shared component layer.

DAN_SHAPPIR: But basically again, going back to that event bus or pub sub mechanism or whatever you decide to call it. So I'm kind of amused that you're sort of, at least on a small scale, implementing kind of a front end or client side Kafka system or something like that. For those of you who don't know, by the way, Kafka is an event system that is very popular on the backend. 

CHARLES MAX_WOOD: Yep.

GIL_FINK: And I need to understand whether you think it's a bad idea or whether you think it's a good idea. 

DAN_SHAPPIR: Well, as in all things, the devil's in the details, you know? 

GIL_FINK: Yeah, you need some sort of way to communicate between your components. And either you do that with prop drilling or you do that with the data flows, unidirectional data flow for example, using Redux or Mobix or other libraries out there that support this unidirectional data flow. Or you use data flow with no coupling, which is event aggregator. You pick the things that you want to use as some sort of way to communicate between your components. Okay, this is something that you will have to pick. In the project that I'm currently involved in, we're using MobX as the way to do unidirectional data flow. In a different project that I'm doing for another company currently, we are creating an entire shared component layer with web components on one hand, and we have event aggregator to aggregate events between those components. As I said, there is no one solution to the problem of the communication between components, but each and every company will probably choose what fits to their needs. I can assure you that the company that has the shared component layer with the event aggregator, the idea is that each and every module in their application needs to be decoupled from everything. Everything there is very modular and every model can be replaced by different models. And this is why they went that way. In most of the applications, you're not creating some generic screen that can be manipulated by the user. You have what you're going to create. So there is no need for some massive decoupling. And this is why companies that don't need event aggregators goes to unidirectional dataflow, which is a good idea to make a consistency of the data inside your front end. 

DAN_SHAPPIR: Can you briefly explain what unidirectional dataflow actually means? 

GIL_FINK: Okay. So unidirectional dataflow, the idea is that data flows only on one way. Most of the, in most of the applications from bottom, sorry, from top to bottom this is like you don't have two-way binding, meaning that the screen isn't updating the data or vice versa. The data is updating the screen. The data is only flowing on one direction, and that direction is from the data to the screen. If the screen needs to notify or change the data it shows, it sends some action or some sort of notification to some store or whatever how do you implement that and that stores up do some manipulation and notify the screen that the data change and Send that data back to the screen. So the data is always having only one cycle and then you don't have two-way binding meaning that the data can be updated from different parts or the parts can update the data, vice versa. 

DAN_SHAPPIR: I'll add to that, that if we go back a couple of years, the concept of data binding was really popular. It was popularized even before the web and a lot of early web frameworks kind of adopted that because that seemed to be the way that most people wanted to work. It kind of seems to make a lot of sense because for example, you display a particular screen of data which matches a particular record in a database. So you've got the different screen elements being mapped to different fields within that record. And usually you could also go back or forward the record so you could edit the table in that way. And basically the data from that database record was read and displayed directly on the screen. So that's the flow, one direction of flow of data. But then also if you updated any of those fields on the screen within that form, that would immediately automatically update the data back in the record. So effectively you had a one-to-one binding and matching between the particular screen field and the field within the database. So that's what is meant by data binding. And very often you might actually even bind the same database field to multiple screen elements. So for example, like a situation where you're showing notifications for unread content, they might appear in different places on the screen. So you actually bound all of those items to that same field and clicking on any one of those items that field which would then automatically impact all the rest of the visual items that were linked to it. And that would create situations in which data flow became really complicated and it could and you created all sorts of race conditions between, you know, when certain items were this updating on the screen and in the database. And that's where that single direct unidirectional flow of information tries to address those issues but adds complexities of its own. 

CHARLES MAX_WOOD: Right. 

GIL_FINK: Of course. 

 

So, hey folks, this is Charles Max Wood from Top End Devs. And lately I've been working on actually building out Top End Devs. If you're interested, you can go to topendevs.com slash podcast and you can actually hear a little bit more about my story about why I'm doing what I'm doing with Top End Devs, why I changed it from devchat.tv to Top End Devs. But what I really want to get into is that. I have decided that I'm going to build the platform that I always wished I had with devchat.tv and I renamed it to Top End Devs because I want to give you the resources that are gonna help you to build the career that you want. So whether you wanna be an influencer in tech, whether you want to go and just max out your salary and then go live a lifestyle with your family, your friends, or just traveling the world or whatever, I wanna give you the resources that are gonna help you do that. We're gonna have career and leadership resources in there and we're gonna be giving you content on a regular basis to help you level up and max out your career. So go check it out at topendevs.com. If you sign up before my birthday, that's December 14th, if you sign up before my birthday, you can get 50% off the lifetime of your subscription. Once again, that's topendevs.com. 

 

CHARLES MAX_WOOD: So my question is, is let's say that I decide, you know what, I don't need this mediator in the middle. I've got a relatively simple, simpler app.Right. And my problem set lends itself much more to this other architecture. And then as all things do, my app gets more complicated. Right. It has more things that need to keep track of more things and other things that need to keep track of things that come off of those things. And I start thinking, you know what? That mediator is really sounding good right now. It, it seems to really kind of fix some of these issues that I'm running into with my app. At what point do you start playing with either going hybrid or making a migration from one architecture to another? Because at this point, the one architecture is now making more sense than the architecture that I started with. And I made the right call at the beginning, right? Because I didn't over engineer it to begin with, right? 

GIL_FINK: Yeah, but this is a good question because moving from one architecture or non architecture to an architecture, it can be very cumbersome. It's not like I'm taking a magic wand and waving it and everything works. A lot of things in the application will break or will not function when you're starting to try to decouple things. My suggestion is going from bottom to top, meaning that you start with the bottom components in your application, meaning all the dumb components which are easy to create or to move back to the architecture. But it's like taking some part of the webpage and starting there. As I said, vertical slicing, start with just one main component which is some part of the webpage and try to tackle it and impose the architecture there. And then from there, go on and migrate another part, another vertical slice. In most of the application that I'm currently building, we're starting with building some shared component layer, either in React, Web Components, Angular, whatever. That shared component layer helps to remove some difficulties when you're doing those migrations. So it's a good idea to start with dividing your application when you're starting building it into the UI layer, into the shared component layer, into a package for gateways. And whenever you have those three moving parts, then when you build your application, it will be, I won't say simpler to migrate to a new architecture, but it will help you to do the migration. And I can, I can say something about it's not only migration to architecture. It's a, sometimes it's migration to technologies. I had the pleasure. I'm doing the thing with my hands. The pleasure of helping some big, big enterprise to combined two different applications into one. One of them was created with AngularJS with like five million lines of code. And it had to hold a new application that was created with Angular. Back then it was Angular 5. And we had to migrate the entire AngularJS code. And the manager said, yes, do it in one month. Go. So, uh, this is where the iFrame thing came and we created the iFrame around the, the, the application that we wanted to migrate around. And then the, the set to the manager's yes, we did the migration. Okay. It's working inside the other application. Everything is fine. And then we took like seven months later to migrate the entire thing. Okay. So it's not only Architecture migration it's it's a problem to do migration in the whole It's like moving from one technology to another and so as I said you you start with small parts and then you Start to or you move to the higher or bigger parts of your application later on 

DAN_SHAPPIR: I totally agree and I would even take it a step further and say that from my experience if you're going to re-architect a system, and it doesn't matter if it's from one architecture to another or from no architecture to an architecture, then at the end of the day, the best bet is basically to buy the bullet and rewrite the system. The case of situations in which I've seen in which an attempt was done to impose a different architecture on an existing system usually ended in tears. Now, if you're lucky, like Gil said, maybe you can kind of slice up this operation into steps. So for example, you might convert it one screen at a time. So let's, and in that regard, it is very much like going from one architecture to another. Let's say you have some sort of application that was written in Amber and you say, hey, I don't want to use this technology anymore because it's really difficult to you know, recruit the developers, they don't want to use this framework, they want to go react, then one possibility is just to switch, you know, one page at a time, just change it so that when you switch from this page to that page, you kind of switch to the other system. And then you slowly grow that other system to take, to eat more and more pages, to take away more and more pages from the existing system. Or like Gil said, maybe you can kind of embed an iframe and kind of stick one system inside of the other and then grow that iframe up until you effectively, everything in the page is within that iframe and then it's no longer an iframe, it just becomes the page. So the app, exactly. So maybe you can do these things, but at the end of the day, it's a rewrite. That's kind of the reason why picking an architecture is important. But like you said, Charles, it could be that you pick one architecture at a certain point in time because it made that perfect sense at that time. And then it doesn't make sense anymore. I can tell you that at Wix, for example, the what is called the Wix viewer, which is that part of the product, which actually displays the websites built by Wix's customers. And obviously it's a large and sophisticated system. During my time at Wix, you know, I was there for seven and a half years. It was rewritten from scratch twice. 

GIL_FINK: Oh my God. 

CHARLES MAX_WOOD: Rewrites are painful too though. And that's, that's quite kind of cringing over here. Cause I'm going. 

DAN_SHAPPIR: Yeah. But when we had an attempt to take in, so after the first rewrite, we needed to really change the data flow within, within the system for a good reason, because we changed the requirements for the product it became more interactive and initially an attempt was made to kind of re-architect the existing solution. It barely held water and we needed to rebuild it in order to get the performance and functionality and the flexibility that we wanted in the system. 

CHARLES MAX_WOOD: Yeah, it seems like there's... Because I've seen people do kind of like what Gill outlined in that, hey, we had Angular 5 and we moved it. I've seen that work, right? And sometimes your system is kind of set up that way, right? So if it's loading, yeah, a page at a time, or you can move stuff into an iframe and expand the scope of the iframe. But sometimes it's at a fundamental level, and that's what Dan's talking about, where it's, we need this to actually work differently than it does now, right? It's not just these neat slices that we can pull off or something like that, right? Where you can kind of get away with that. And a lot of cases, if you're replacing one framework with another, in this case, it's no, we at its core, it has to do different work in order to get the job done. Yeah. You're probably going to have to rewrite it. 

GIL_FINK: But, and what I can say is don't be afraid of free rights, but your managers are going to be afraid. 

CHARLES MAX_WOOD: Yeah. Well, I think there are trade-offs. 

AJ_ONEAL: The problem with rewrites, and I think you've, you've already addressed this, is that most rewrites are never completed. Most rewrites result in two code bases that don't get the attention that they need, and both are buggy and not getting the products to where it needs to be for the customers. 

DAN_SHAPPIR: So what happened at Wix in that regard is that we were really strict about it. Basically a timeframe was set, acceptance criteria were made, lots of tests were written, and there was a deadline specified to when the old code base needs to die because the organization can't handle supporting both. But it was a very significant effort, undoubtedly. 

AJ_ONEAL: So I wanted to bring up two questions. One is, when do you make the decisions for what the architecture should be? We've talked a lot about changing midstream, but somebody made a decision in the first place that you had to go back and undecide and redesign, right? So yeah, let's go with that first. 

GIL_FINK: First of all, I think the whenever you start a project, you need to realize that you will have some sort of architecture. You need to do it as part of the starting point of the application. It's not enough to pick a framework. It's a good idea to pick a framework, a React, Angular, whatever, but it's not architecture. We said that at the beginning so what I suggest is do it whenever you you creating your high-level design of the application. You need to start at the beginning. If you're not going to do that, you can say to the developers that are currently building and this is what I'm currently doing in a project. I want to see the design details of the feature that you are going to build before you are going to implement it. I don't want you to go like horse with the blinding blinders. And yeah, I don't want you to do that. I don't want you to rush to development. I want you to tell me how you're going to implement it in terms of communications between the component. Who, which, and which component are you going to use or implement, how you are going to do that. And once you are doing that, then I'm validating the the design that the developer is doing and giving my input. And only then I'm telling them you can proceed, you can go and you can implement the feature. So you can think about designing features as some sort of an architecture or architecting step inside your development cycles. Okay, so if you don't have a high level architecture, like I said, in the beginning of the project, you can do some sort of small designs or small architectures, parts, meetings in in your group when you are creating the application while you're doing or you're creating some feature in the application. 

DAN_SHAPPIR: I would add to that. If it makes sense. Yeah, it makes a lot of sense. And I would add to that, that not making decisions about architecture is an architectural decision. Your system is going to have some sort of architecture, whether you design it or not. The only question is how cohesive it is or how messed up it is. And if you don't, because data will need to flow through your system, there are going to be application states. So if you're not going to be designing it from the top down, it will kind of evolve from the bottom up. And like Gil said, if making a cohesive long-term architectural decision is problematic for you, then one thing you can indeed try to do is try to split up the things into self-contained components that could later line up better with whatever top-down architecture you decide to impose, or at the very least, when you're forced to rewrite your system, at least you can take those components and copy them from the previous code base to the next code base. 

AJ_ONEAL: So one of the things that I think, I think it's Rob Pike that's said it this way, is much of the time, the constraints of the language require that we make too many decisions for which we know the least information at the very time that they're going to cause us the most trouble. And I I hope, did that come across clearly? 

CHARLES MAX_WOOD: Kind of. 

AJ_ONEAL: I'm gonna take that as a no. So we front load decisions that are difficult to change and that we're unlikely to make correctly because we don't have enough information yet because you learn as you build. That's emergent design. As you build. 

STEVE_EDWARDS: So where do you draw the line? I mean, to follow that, you could keep going, going, oh, I still don't have enough information. I still don't have enough information. So I guess you'd have to figure where to draw that line.

GIL_FINK: I can say something about that because in most applications you have requirements. And companies come to me and say, they are giving me the requirements and they are saying, can you help us to evaluate the architecture that we are doing? And from my experience, because I saw not the one or two or three projects, but more than 100 different projects, I can I can help them to understand or to give them from my experience and evaluate what they're trying to do. This is some consulting that I'm doing regularly to companies, even not to tomorrow, but on Sunday I have a new company that came to me with the same request. We're trying to evaluate micro-frontends, we need some help. Can you help us? So One thing is you can consult with a consultant. Another way to do those things is just to relay on the experience of the developers or the architect in your company or CTO, whatever, whoever is in charge of designing the system. And you have to make those decisions, even though they might be wrong. But if you don't do that there won't be any application in the end. So we will have to live with the decision. It's like what I'm saying about whenever we are picking a framework, whenever you are picking a framework like Angular, React, Vue, or whatever, you're getting married with that framework. After you got married, you want, the diverse will be ugly if you want to move from one framework to another. But we are still doing that. You need to pick the technologies, you need to evaluate some architecture, create some architecture, even as Dan said, not creating an architecture is an architecture by itself. But in the end, somebody needs to draw the line, where do you do the cat? 

DAN_SHAPPIR: I will add to that, that and I think that this is something that where AJ will happily agree with is that you should always prefer small and simple. I've seen way too many situations in which front ends were over-architected. It's much, you know, at the very least, if you choose a simple architecture and it ends up being the wrong one, well, you've spent less resources building it than if you've created a really complicated architecture and then it turns out to be the wrong one. And simpler architectures also are easier to mutate or enhance into various directions. So for example, I, you know, and it's really unfortunate in my mind that a lot of the systems that we are currently using for modern web development actually encourage us to create really sophisticated architectures. So for example, In many cases, using an MPA type approach where each page is delivered separately is a much simpler type of a solution than implementing a single page application. Because you don't need to manage a data store that, you know, persists between pages. You just request additional information from the back end whenever you need more information. And go for it AJ. 

AJ_ONEAL: For people that aren't up on today's latest buzzwords. MPA is the new buzzword that means website like we used to build in the 90s. 

DAN_SHAPPIR: Exactly. 

STEVE_EDWARDS: Just just yeah exactly. 

AJ_ONEAL: The Rails developer in me is gratified there's a term for it now. 

STEVE_EDWARDS: Yeah and and it's I mean there's performance concerns there too if you're always having to go to your back end and I suppose then you could throw in things like Cloudflare or CDNs or 

AJ_ONEAL: If you're bad at building architectures no matter which architecture you pick you can make it under performance.

STEVE_EDWARDS: Yes, that's true. But at the same time, there's ways to make it. Sometimes you have more foot guns, I guess, if you're going to work. 

DAN_SHAPPIR: But the reality, the unfortunate reality though, is that when you look at the modern application frameworks that are out there, the NEXT, the NOX, the Remix, the SvelteKit, all of them, all of them encourage single page applications. Some of them do it better than others, but at the end of the day, they all encourage that and I find that to be a bit unfortunate because I do think that in many cases having a simpler architecture, which is each page is delivered independently is much easier and much simpler and you're kind of being forced to use WordPress for that because there are no alternatives. 

AJ_ONEAL: Well, let's, let's define page real quick because part of the thing is that when you look at today's applications, they are Twitter, right? Twitter has one function. It's not something that's useful. It's not a productivity platform, right? It shows you stupid things that people that you don't care about say to make other people angry. That is what Twitter does, right? And it's not hard to do that. You just need to show a picture of a person so you can get an emotional response of, oh, I'm already going to agree or I'm already going to disagree and then the words so that you can start forming your rational argument to how you reply. That's not a hard thing to build in a single page. 

DAN_SHAPPIR: Yeah, but... 

AJ_ONEAL: So what is a different page? 

DAN_SHAPPIR: Well, let's put it this way. Most websites that are more than just content websites are about building forms, right? And putting in information and also viewing information. Well, whenever you click submit, that could theoretically be a page navigation. And, and, but the reality is that these days it usually isn't. Usually these days is JavaScript intercepting that button and then doing stuff with it and then sending some stuff to the backend and, but keeping some other stuff in the front end and doing a lot of complicated things. And, 

AJ_ONEAL: and it will know nobody wants to wait for the page reload just to see their angry response to somebody else's suite appear below it. We want that instant. 

DAN_SHAPPIR: Well, and that's the thing, because if you think about who, who created react, for example.

AJ_ONEAL: It was Twitter. 

DAN_SHAPPIR: No, it was fake. 

AJ_ONEAL: No, no, it was the one they couldn't acquire. Facebook. 

DAN_SHAPPIR: Yeah. So it was Facebook and, and react is a great tool for when you're building a Facebook, it's not necessarily such a great tool when you're building a blog site and yet the reality is that these days, if you ask people, how are you building, you know, the devs like we devs like to build their own blog sites or our own blogging frameworks and whatnot. You know, what are you using? I'm using, I'm using next JS. What is next JS built on? You know, react and, and it's a single page application. Why is my blog a single page application? Why, when I navigate between blog posts, do I need to do it via an Ajax call to get the data and then render it on the client side, instead of just getting the HTML from the, from the server? 

AJ_ONEAL: Because you don't want your, you don't want to be docs. Do you want your own mistakes to help you? So if nobody can navigate to the page because there's no URL structure. 

DAN_SHAPPIR: Oh no, 

AJ_ONEAL: these days there is a URL structure. 

DAN_SHAPPIR: No, these don't. No, I know. 

AJ_ONEAL: I intercept the URL with your router. Yeah, exactly. 

CHARLES MAX_WOOD: I have a hard stock coming up by the way, so we need to derail back onto the topic and wrap up. 

AJ_ONEAL: Well, so one thing I wanted to say with the whole, what's the different page? So I was hoping to evoke this, but whenever you have an idea in your head, you should just say it. Right.

DAN_SHAPPIR: But yeah, just to say a different page is when you have a different euror. 

AJ_ONEAL: Oh, well, those are fighting words. But, uh, so you've got on Twitter, you've got the feed, you've got the messages, you've got the bookmarks, you've got the account. Basically, I would say anytime you have a user, a profile or user account, that's a separate app. I, whatever it is that your app does, unless your app is a CRM. Managing user profiles is just a separate app. Don't try to put it in the main app. I think that's one of the most perfect examples of what should be a separate page, is the user profile stuff. 

CHARLES MAX_WOOD: All right, folks, with that non sequitur, we're gonna go ahead and do picks. Yeah. Uh. Well, so it is. 

DAN_SHAPPIR: Wait a minute, before we go picks, though, we do need to give Gil, I think, a chance to say some final words. Usually you do give that option. 

STEVE_EDWARDS: Yeah, I agree.

DAN_SHAPPIR: So, Gil, anything we missed, any additional, you know, summary of information or, or, or things you wanted to say and we neglected to say, 

GIL_FINK: I will do it short. No. 

CHARLES MAX_WOOD: All right. Let's do picks then. 

 

Hi, this is Charles Maxwood from Top End Devs. And lately I've been coaching some people on starting some podcasts and in some cases, just taking their career to the next level, you know, whether you're beginner going to intermediate and immediate going to advanced whether you're trying to get noticed in the community or go freelance, I've been helping these folks figure out how to get in front of people, how to build relationships and how to build their careers and max out and just go to the next level. So if you're interested in talking to me and having me help you go to the next level, go to topendevs.com slash coaching. I will give you a one hour free session where we can figure out what you're trying to do, where you're trying to go and figure out what the next steps are. And then from there we can figure out how to get you to the place you want to go. So once again, that's topendevs.com slash coaching. 

 

CHARLES MAX_WOOD: Dan, do you want to start us off with picks? 

DAN_SHAPPIR: Okay, for sure. So I really have a, okay, I have two picks this time. My first pick is this. I don't know if you know this, but approximately, well, almost exactly two months ago, 58 days, a very severe bus having to do with privacy was found in the indexed API in Safari 15. Basically, when a table is created in one frame or window of Safari, all other open windows and frames, et cetera, see the name of that table. So they don't see the content of the table, but they see the name of the table. Now, you might ask, why is it so bad? Well, because the name of the table can tell you which other sites are running in the other tabs. You know, one tab is not supposed to know what you have open in the other tabs. Or even worse, sometimes the tables contain information like the identifier of the, you know, your ID within that other application, probably not your password, but your account name. So you could know that, you know, in a different tab, the user is in, let's say in website X and their account within that website is Y, which is obviously information that you're not supposed to have about some other website. Now on Mac OS X, there's a very easy fix for this bug and that fix is don't use Safari. Use some other...Because you know, it's true because you know, you know, it's, it's taking them over two months to fix it. I gather that they're working on it, you know, eventually a fix will come out. So, so just use Chrome or edge or Firefox or brave or whatever for the time being. And when they come up with a fix, you can always switch back. The problem is that on iOS, you don't have any recourse because on iOS, all browsers on the inside are actually Safari. So on iOS, whether you're using Safari or Chrome or Firefox, it's actually Safari on the inside, and you've got this bug. So we've got a really severe privacy issue affecting all browsers on iOS for the simple reason that on iOS, there is no browser choice. You are locked into Safari on iOS. And You know, one of the reasons that they give for that is has to do with privacy and security. Well, here we see the exact opposite situation because of the lack of browser choice on iOS. So that would be my first pick. I'll give a link to the details of the story if anybody is interested in the technical details of what the actual problem is. My other pick has to do with the fact that Amazon Prime is now finally available in Israel. And it's actually fairly cheap and there were some things that I wanted to see. So I actually subscribed to Amazon Prime. And one of the things that I'm watching now that I would like to call out is Invincible. It's an animated series about superheroes. And it's really out there in terms of the subjects that they cover and how gory it gets. It's definitely not something for the little kids but it's really good and I'm enjoying it a lot. So that would be my second pick. And those are my picks for today. 

STEVE_EDWARDS: And I will vouch for the second pick cause I saw the entire show and it's very 

DAN_SHAPPIR: no spoilers, please. I'm only in the middle. 

STEVE_EDWARDS: Haven't said anything about it. I just said it's very good. 

CHARLES MAX_WOOD: Cool. Good deal. All right, AJ, what are your picks? 

AJ_ONEAL: Well, I've got some good ones for you today. So I, you know, I've talked about how I've upgraded my monitor setup and I love the Dell monitor, which I guess I'll just throw that link in there anyway. But also it's a little bit troublesome to figure out which Thunderbolt hubs and adapters to get because they thought, you know, USB four and Thunderbolt four and all that. It's just, it's just too many things multiplexed on top of each other and finding a hub that actually works and does the right thing is obnoxious. So I, I'm going to give you all a little cheat. If you're looking for a Thunderbolt hub for one of the new M1 computers, there's the Sonnet Echo 5 for just generic Thunderbolt hub that actually supports at least all of the Thunderbolt features that I'm using. Maybe it's missing some that I'm not, but it seems that they must have attention to detail because it has VRR support for DisplayLink. And then the WaveLink Thunderbolt 3 to display port adapter because that also has VRR support for DisplayLink. But I don't know, it's so hard, depending on what feature of Thunderbolt or USB4 you're interested in, the devices that you're connecting to support, maybe these won't work specifically for your device. But I ordered several of both. I basically ordered about $1,000 worth of adapters and sent them all back except for these two because these were the two that seemed to support all of my devices correctly with all of their features. And then on, on the, the topic of office upgrades, there's these little, I've been using the, oh gosh, I forget the name of it now, but that company that sends you those books every month that have all the office supplies in it. Uline, Uline. I've been using the Uline books to raise up my, my desk at the other office. And you know, that works pretty good. I think the Uline catalog is great and I think everybody should have a few Uline catalogs. They, they work great for blocking vents when you know, it's summer and icy air is blowing or when it's winter and burning hot air is blowing. They work great for raising desks. They work great for raising monitors. They're just nice, thick, sturdy catalogs. But, but, and all you need to do to get an unlimited supply of Uline catalogs is just do anything that classifies as registering a business in any way, shape or form on any website or with any government, and you will get an unending supply of them. I love them, they're great. But that's not actually what I was intending to pick. For the desk, and it turns out these would probably work for couches and for other things as well. There's a company, I guess, I don't know what the company's called, Slipstick. Yeah, it's called Slipstick. And they make these little furniture lifts. They work for beds or desks or whatever, but they're great. They're great. They're, they're stackable. You get a pack. It comes with eight of them. So you can choose how to distribute that because the desk at work had five legs instead of four, cause it's one of those weird shaped ones. I had to get two packs to start, but, uh, you know, you can raise your desk to one stack or two stack or three stacks, whatever. And, uh, I just think that they're, they're really awesome. So I'm going to pick the, the lipstick furniture lifts. Other than that, fairly, no, there's one other thing. So I gave my apology in the last episode to VAR for slandering it when it didn't deserve it, VAR does not have any exceptions that is entirely consistent. But I did a, I did a presentation, a visual presentation with code examples on the cold hard truth about Consulate and VAR. So if you want to check that out, I'm linking to that as supplementary material to the, the last podcast where we discussed that, that, that, uh, my presentation fixes a few mistakes that I made. And then, and then other than that, it's just the normal stuff. Webinstall.dev for all your tools, Creeds of Craftsmanship.com for good articles and videos on software engineering. And you can follow my live streams and beyond code on YouTube, Twitch, and Twitter and all the things. 

CHARLES MAX_WOOD: Awesome. Steve, what are your picks? 

STEVE_EDWARDS: All right. The high point of the podcast, as always, the dad jokes. So I've got two, I think pretty decent ones today. 

AJ_ONEAL: Unmuting for maximum laughter. 

DAN_SHAPPIR: Same here. 

STEVE_EDWARDS: Yes. Okay. So. One of the things I know 

AJ_ONEAL: you need to unmute in case you laugh 

STEVE_EDWARDS: when you laugh when you laugh 

AJ_ONEAL: in case you laugh 

STEVE_EDWARDS: Okay, so it goes I love putting on warm underwear fresh out of the dryer I mean feels good right when you put it on plus it's super fun to look around the laundromat and guess who they belong to Okay, no 

CHARLES MAX_WOOD: that one was clever okay, 

STEVE_EDWARDS: and my drum jokes not working again, 

AJ_ONEAL: I didn't see that one coming I didn't see that one coming. 

STEVE_EDWARDS: All right. So you're going to have to imagine the drum joke. I'm not sure why it's not working in Riverside. So I have a 10 year old son and when he was smaller, he asked me where poo comes from. I decided to be honest with him. And after I explained, he asked with a slightly terrified and complex look, what about Eeyore? I did see that one coming. So anyway, those are my jokes for the day. 

CHARLES MAX_WOOD: All right. Nothing else you want to shout out about? 

STEVE_EDWARDS: No, nothing today.

CHARLES MAX_WOOD: All right. Well, you can hear more of Steve's tortured soul on views on view. Then I'm going to throw out a few picks. I'm going to make it fast because I really do have to get over to this other thing at noon. First of all, I usually do a board game pick. And while I was down at this funeral, my daughter brought up Candyland and wanted to play. So we played Candyland, my six year old, my, and yeah, it's fun. Little game play with your, your kiddos 

DAN_SHAPPIR: during the funeral. 

CHARLES MAX_WOOD: So no, well actually Actually, yes, because she was sick, so we stayed at my mother-in-law's while everybody else went to the funeral, because it was my wife's family. Anyway, that's neither here nor there. Yeah, and then other picks. I can't think of anything at the moment that I'm really jazzed about. Oh, I did listen to the Brandon Sanderson Skyward series. They released three novellas and one full-length novel. And the novel was... It was entertaining and it moved along, but it wasn't the best of that series. As far as the rest of it goes, yeah, I really enjoyed the novellas actually. They were pretty darn good. So I'm gonna shout out about those and just remind everybody to go check out Top End Devs. Gil, what are your picks? 

GIL_FINK: Okay, so I'm going to pick something that came along with the Chrome 97, the last version that they released. You have a new Chrome recorder and it's currently experimental but this is a very good idea that they started to implement. 

DAN_SHAPPIR: To clarify, you kind of neglected to say it's in the DevTools in Chrome. It's part of the DevTools. 

GIL_FINK: Yes, sorry. So it's part of the DevTools. It's a new tab. It is called Chrome Recorder. It enables you to record the user flows and then to run those user flows and see performance issues on those user flows. I really think that it's a good idea. It can be very helpful. One of the major topics that I'm always interested in is performance tuning. So this is relates to that. The second peak, it's going to be a series that I started to see with my dear wife on the Netflix. It is called Blacklist with James Spader. I won't say anything about it. It's a very good series. We are currently in season three and I can't say anything because I'm not going to do any spoilers, but if you want to see a very decent series, thriller series, go and thrill and smart series, go and see the blacklist with James. 

DAN_SHAPPIR: I just want to add one more thing about that recorder tab in the DevTools. It has another cool feature in which you can actually export the recordings and then you could play them back in Puppeteer which makes it also a useful tool for building end-to-end scripts for end-to-end tests. 

CHARLES MAX_WOOD: Oh, nice. 

DAN_SHAPPIR: That sounds pretty awesome. 

CHARLES MAX_WOOD: My wife and I have been watching Blacklist, and we've been watching it on Netflix, not as it comes out every week. And so we just wait for the whole season to drop. And yeah, we're in the middle of season eight, I think, which is the latest one they have on Netflix. So whatever the latest one on Netflix is, that's when we're watching. And yeah, it's been a really, really fun series to watch.plus one on that. All right, Gil, if people want to find you online, where do they find you? 

GIL_FINK: At Gil Fink in Twitter. That's the main place. If you want to talk with me, DM me. I will try to answer you if you have anything to ask. And you can also find me in my email, gil at sparksis.com. This is my company email. If you need any services of web consultant either in architecture, performance tuning or anything else, I will be very happy to help. 

CHARLES MAX_WOOD: Awesome. All right, folks, we're going to wrap it up right here and until next time, Max out. 

DAN_SHAPPIR: Bye. 

STEBE: Adios. 

AJ_ONEAL: Adios. 

 

Bandwidth for this segment is provided by Cashfly, the world's fastest CDN. Deliver your content fast with Cashfly. Visit C A C H E F L Y dot com to learn more.