Transcript from the "Complexity Resources and Q&A" Lesson
>> Here are two resources or few resources I really like when it comes to thinking about software engineering as a whole. Clean Code by Robert C Martin, is probably one of my all-time favorite books. Refactoring by Martin Fowler, very, very good. So Kent Beck wrote the foreword, so this is where that make it work.
[00:00:19] Make it fast or make it right, make it fast came from and then is an Angular developer, then using the style guide. So with that said, does anybody have any questions and I sure hope you do about the things that I've just said. So this is going to serve as the foundation for everything that we do today, in code.
[00:00:51] So, if you have a question, in your room hop up, say it don't be shy, or if somebody in the chats have it, Mark, feel free to service that for me, I would love to talk about what I just talked about. So the question is if you have a container and the presentation component the presentation component is the very very thin component and your container component will have logic.
[00:01:20] And, that is a very astute observation. And I would say that presentation components are razor thin and a lot of times they're strictly bindings. And so if I have like a list component where I'm just feeding in a collection of something, and we'll see this is that it's just inputs, outputs.
[00:01:40] How do you break or how do you test something with no logic? Like it's really hard to do. Typically you move on to like end to end testing at that point, because unit testing by definition, you have to have units of logic. Now a container component is responsible for pulling in just enough data to satisfy the presentation components ie the templates, and capturing user events and delegating them upwards.
[00:02:13] And so in the context of a container component, it's still very, very thin but any logic that exists at the container level component is present or I would say, it's presentation state is what I would consider is that, it's very focused on the state of the presentation of that specific component.
[00:02:37] And so, there's a difference between like presentation state of like, do I show this login button or not? Do I disabled the submit button? Verses what is the business rule for submitting this flight. So I had the opportunity to work on a flight scheduling app, and the rules the business logic around that is incredibly complex.
[00:02:56] So, like those kind of rules would definitely not go into component. And so very good question. And the answer is, presentation components are very very thin, container components are just not quite as thin. But it's just enough to consume the data for the templates, then capture events and delegate those back out to a facade, typically.
>> What is a facade?
>> So, a facade is nothing more than a service and this specific facade or the facade pattern, what it does is that it sits in between a consumer and a producer. And it hides all of the implementation details of the producer from the consumer.
[00:03:48] And so a lot of times I use a facade is that when I have a component that's coupled to like a service, that's making http request, which is a very, very common pattern, Intel kinda state management libraries came onto the scene is that from my witches component, I would just inject the widget service and I would pull the widgets in, and that would be that.
[00:04:13] But what I wanna do, is I want the component itself to be oblivious. To application state, and how the data is actually showing up, the component doesn't need to know that. And so what a facade does is it sits in between the component and the rest of the application and essentially puts up a facade around what's actually happening.
[00:04:37] Some individuals, I believe, even doorwall, they recommend keeping all your components in a lib and then consuming them back into your application. And the question was, how do I feel about that? Well, the answer is, it doesn't offend me. But I think in a lot of cases, it leads to kinda premature optimization.
[00:05:04] And so there is an overhead by decoupling everything. And there's just kinda this threshold work. Like it doesn't make sense, or it becomes so burdensome to have everything broken out, into tiny, tiny, tiny, tiny, different components, and then moving them away into standalone libs. I've seen it actually create cognitive overhead, inside the application.
[00:05:30] And so, again, coming back to cohesion is that if you have a component that will only ever exist in a single application, then I believe you should leave it in that application. Now, this is my opinion, and there may be a case for not doing that. But if I have a very specific component in an application, I leave it there because that is kind of functional cohesion in terms of where it operates.
[00:05:58] And so I've seen this pattern, I work with it, but I typically try not to optimize something prematurely until I need it. Now if I ever needed to move a component across two applications, absolutely, put that in a lib. But, there is a little bit of an overhead that, I think, at some point we just have to realize it's not worth paying that tax, if you will.
[00:06:25] So the question is, if you have, and correct me if I'm wrong, but if you have an existing app, how do you actually apply these techniques to reduce complexity? Is that correct? So I believe the best apps in the world are Greenfield. Like if I just had a magic wand and I could just wave it around, I would only ever work on Greenfield applications.
[00:06:51] Unfortunately, that's not how the world works. And it's really easy or it's easier to get your architecture right when you get to define it from the ground up. So in the course of this workshop, we're gonna start from nothing. We're gonna build it up it's awesome but I have inherited some real gems.
[00:07:13] And you're sitting there and you're like, how in the world, am I supposed to deal with this? And I think first and foremost, it's understanding that you can refactor through promotion. And so the answer is, little bit, by little bit, by little bit. Do you reduce that complexity so back to the access of evil.
[00:07:33] So when we talk about complexity, more often than not, that you have hidden state, which makes it a very hard to test a function, and you have nested logical and you're violating the single responsibility principle. Well you can fix those, by first of all extracting large functions into tiny smaller functions with preserving all of the functionality and especially if you're writing tests as you go along to where I've been on projects where it's look, we need to break this up.
[00:08:07] But we're not gonna break anything because we've written some tests and as we start to refactor it, the tests are going to continue to pass. So it's refactor through promotion, extract a method, if you have hidden state, take that out, and instead inject that via a parameter. So this is dependency injection, which is nothing more than parameters like you're satisfying a dependency and essentially decoupling your code it kind of the local level and then moving it out into the proper abstraction level.
[00:08:41] Does that make sense? And, unfortunately for us, it's not really a magic trick, in the sense of like against the axis of evil. Is the simplest thing to fix and I see it all the time, is you just look at code and you're like this code. And for me, really, the litmus test is can I test it?
[00:09:03] And can I move it? And if you can't test it or you can't move it, then you need to refactor. And so you start to break it out into smaller single purpose functions. Peer immutable functions, and then you start to promote it into an abstraction layer that makes sense.
[00:09:20] So the question is and I had made the comment that I do not agree with, like the kind of the style guides 100%. I can't think of anything off the top of my head. But, I think sometimes maybe like some naming conventions or I find it to be overly restrictive.
[00:09:41] I would say that most of the time, that, I do agree with them. But there are things where this is a style guide, by nature, it's stylistic. It's a stylistic preference. And so like one of the things that I do that you'll see is if I have an array of something in the last item, I'll just put a comment at the end of it because it doesn't break the code.
[00:10:08] And when I start a new line, like. You're you can just type it, you don't have to go back and put that comma before you start the next line. So for me, that's a stylistic preference. And so somebody could in their style guide, say don't use a trailing comma.
[00:10:22] And I would say, but I'm from Oxford, and I like the trailing comma, and I'm going to use it. And I think as long as you're going to deviate off of a style guide. Then make sure that it's agreed on by your team. And so I would say your team or like your team style guide trumps your organizational style guide, which then trumps the community style guide.
[00:10:45] Because if you've got together as a team you said, this is how we wanna do this particular code. It just makes sense for us we wanna do it, then that in terms of specificity would take over and override that. So I can't say there's anything egregious there's just something where it's just like, that's too much work or doesn't make sense or I don't see the value in it.
>> As it okay and,
>> But nothing like there's no I think fundamental philosophical difference. A lot of it is, I mean, a style guide by nature is mostly stylistic preferences. But I do find them helpful, because they ensure consistency. I talked about a lot of very high level things, a lot of very general things that you can apply to a lot of other things besides Angular.
[00:11:36] But if this first principles that when you are disciplined and you apply them to your code it just makes everything better. And it create consistency not across a single project but across everything that you do. So for the rest of the workshop I hope you can re-enforce those concepts and we can start to see those in action.