Software Engineering 101: Learn the Software Development Cycle for Better Programming | Kurt Anderson | Skillshare

Software Engineering 101: Learn the Software Development Cycle for Better Programming

Kurt Anderson, Computer Scientist, Multi-Media Designer

Play Speed
  • 0.5x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 2x
48 Lessons (4h 54m)
    • 1. Introduction Video

    • 2. 1-1 Why Use Models

    • 3. 1-2 Software Development Cycle

    • 4. 1-3 Software Cycle Example

    • 5. 2-1 Requirements Definition

    • 6. 2-2 Requirements vs Specifications

    • 7. 2-3 Functional vs Nonfunctional

    • 8. 2-4 WRSPM Model Introduction

    • 9. 2-5 WRSPM Deep Dive

    • 10. 2-6 Requirements Example

    • 11. 3-1 Architecture Introduction

    • 12. 3-2 Architecture Overview and Example

    • 13. 3-3 Pipe and Filter Pattern

    • 14. 3-4 Client-Server Pattern

    • 15. 3-5 Master-Slave Pattern

    • 16. 3-6 Layered Pattern

    • 17. 3-7 Software Engineering Pattern

    • 18. 4-1 Software Design Process

    • 19. 4-2 Stages of Design

    • 20. 4-3 Modularity

    • 21. 4-4 Information Hiding and Data Encapsulation

    • 22. 4-5 Coupling Introduction

    • 23. 4-6 Tight Coupling

    • 24. 4-7 Medium Coupling

    • 25. 4-8 Loose Coupling

    • 26. 4-9 Coupling Conclusion

    • 27. 4-10 Cohesion Introduction

    • 28. 4-11 Weak Cohesion

    • 29. 4-12 Medium Cohesion

    • 30. 4-13 Strong Cohesion

    • 31. 4-14 Importance of Design

    • 32. 5-1 Implementation Basics

    • 33. 5-2 Buy Vs Build

    • 34. 5-3 Deployment Overview

    • 35. 5-4 Deployment Planning

    • 36. 5-5 Deployment Rollback

    • 37. 6-1 Testing Overview

    • 38. 6-2 Testing Bugs

    • 39. 6-3 Verification and Validation

    • 40. 6-4 Unit Testing

    • 41. 6-5 Integration Testing

    • 42. 6-6 Incremental Testing

    • 43. 6-7 Back to Back Testing

    • 44. 6-8 Who Should Test

    • 45. 6-9 Automatic vs Manual Testing

    • 46. 6-10 Black and White Box Testing

    • 47. 6-11 The problem with testing

    • 48. Project Overview

28 students are watching this class

About This Class

Building good software takes hard work. It takes planning, design, adjustments, and flexibility to be done properly. Poor decisions during the planning phase can cost hundreds or thousands later on in development. 

In this course, we will be going over the software development life-cycle. We will cover the models, techniques, and planning required to create sustainable code. 

In this course we will be covering:

  • Requirements
  • Specifications
  • Modularity
  • Design
  • Coupling
  • Cohesion
  • Lifecycle Models
  • Architecture Patterns
  • World Machine Model
  • Testing
  • Testing Perspectives
  • Black and Whitebox Testing


1. Introduction Video: Hello, everyone, and welcome to skill share and this software course. In this course, we're gonna be mainly discussing the software development cycle. So software development cycle is really just a set of different steps you can take to design better software. If you're designing, for example, a small calculator, you don't need a lot of beforehand practice and figuring out the details. It's a small application. It might be, you know, maybe 100 lines of code. Maybe it's bigger and it's, you know, 1000 lines of code or even 10,000 lines of code. These projects don't require a lot of planning to get right, because once you designed the 10,000 you can kind of have it all in your mind. You can go back and you can rework it, make things better, and it won't be too difficult. What starts to get problematic is when you get into larger than that. If you have 100,000 lines of code, suddenly there are lots of things interacting with each other. Bugs start coming into play that you didn't expect, and these bugs start being really, really complex instead of a bug which just contacts another place. Let's say in a smaller application you have a bug which kind of propagates like this, it's easy to track. You know, You the bug starts here. You look at this piece of code. You look at this piece of code, you fix the bug when you get the larger pieces. Larger programs suddenly have bugs that look like this where everything is talking to one another. And if you have no plan and no diagram, a bug can look like it's appearing in 100 different places, and you need to be able to figure out how to find stuff like that. You also need to figure out how to design it so that you can extend later on. If you want to make your project bigger, you need a bank it so that it's in a state where you can add on to it easily. And that's what all of this is going to detail. So we'll be starting off, which is going over the software development cycle. We're then gonna talk about requirements and specifications. This step is really just figuring out what we're trying to build, and then how we're going to build it. We then go into architecture, which is sort of really, really large view down. What are the patterns were going to use? What are the different ways really connect the different parts? How could we break it up so that a bunch of people can work on it? They were gonna look at the software design. Once we've broken up in a parts, we need to figure out how each one of those parts is gonna be built. That's where you start designing things. You start looking at what loops? What libraries. What different ways of storing data you need for each one of those parts. Then we're gonna go into implementation. That's when you actually handed down toe. Developers and developers begin coding it. So we're looking at something like this where we have a big problem and they were breaking it down into, let's say, a bunch of these sort of boxes. Then we break these boxes down even farther. And then now we start putting developers on each one of these boxes to start building it out. Then we look at deployment. Once we have all of this together, how do we make it one big, cohesive unit And then how do we take that cohesive unit and get it to the real world for building an iPhone app? How do we get it onto the store? If we're building a desktop up, how do we get it so that people can buy it? So deployment is important and then finally, testing and these two kind of go back and forth? Testing is usually done before deployment, but a lot of times we'll deploy in like today's world will deploy a minimum viable product or something that's quick will get feedback, will find up bugs and errors, and then we'll fix them afterwards and keep this sort of loop of testing, deployment, testing or actually be sort of testing and then back to the top all the way down back to the top. And you kind of go in this cycle of actually revamping and continually updating and maintaining your software. So in this course, this is what we're going to learning. We're learning all of these steps on how to build better software, how to organize your software, and overall, just how to make sure that when you build something large, it ends up working. In the end 2. 1-1 Why Use Models: let's go over the importance of really the course in general. Why are we using software models and software engineering? Why don't we just code the thing? Why don't we jump in and just make the project? Well, this becomes more apparent whenever we think about another project, something that's in the physical world. Let's talk about building a bridge. Imagine if you're building a bridge and you start from each side. So you have, like, this river and you start building on the left side and the right side and you join in the middle. A lot of bridges are created like this because you can create it two times faster instead of having to build from the right and go all the way across. You can actually start on both sides with two construction crews and just meet in the middle. In Japan, the bullet trains the big old railways. There actually usually started in like eight or nine different locations, and they all just connecting the end. Imagine, however, if this bridge here, if it connected in the middle and it was like 10 feet off from one another, So instead of this perfect straight bridge, we now have part of the lanes on the right and part of the lanes on the left that actually just go straight into the ocean. That would be a catastrophe. That bridge would be rendered useless. We would not be able to work with it. And software engineering, we might consider those two sides. Ah, Bug. Ah, pretty big bug. But just a bug. And from the left and the right, maybe the top. Maybe like the very, very back, it might look like the bridge is working. However, the structure is unsound. Not on Lee. Could it fall down because of this? But also, there could be this problem where people just drive into the ocean. It's a It's a catastrophe for the construction company, cause now, not only do they have to pay to build the bridge the first time, they also have to pay to deconstruct it and then rebuild the bridge properly. And that cost a whole lot of money. And maybe the construction company goes under. It has to be abandoned. And now we just have this bridge sitting here that'll rot away. And we don't actually have a solution for the problem. We're trying to fix. So this is what sort of is the importance of that whole planning. They missed a single plan. Accepted. It costs millions. A lot of people don't think that this can happen. And software engineering I will just fix it later on. It's all code. Weaken, delete and rewrite. However, whenever you get into millions of lines of code, that becomes an issue. Amazon, for example, I think, has over 10 million lines of code or even more same with Facebook and all these large entities. They have all of this code. Imagine if you somehow created a bug in there that represents itself on, for example, on Facebook on the friends page. But it's actually something to do with the timeline feed. Imagine how hard that would be to debug. This is something called technical debt. It's This is my definition of it. Ah, poor hard to understand hacky implementation, which will have to re repaid with interest later on. So this really just comes down to cutting corners in the beginning, not actually planning something out and just jumping into it. It might look like it works right now that you did do a quick little test. There's no bugs, so, you know, save the hour or two of planning, and now you can move on to the next thing. However, that could cost you 20 plus hours later. Imagine it's just a little line in a file and you put it in there and you don't document and there's no plans of toe. Why you put it in there. Also no comments to explain why you put it in there now, 68 months later. 68 months. Maybe it's three years later this, actually this line you put in there creates a bug. Another programmer comes in to try to fix it. He not only has to find the original line that you put in there, but maybe it doesn't actually put any sort of bug in that file. Maybe it actually creates a bug on a completely different part of the server. So he has to go through the entire tracing process to get back to this line of code. And then once he sees it, yes, to understand what it was supposed to dio look up the proper way of doing it, document the proper way of doing it and then fix the line. That is a whole lot more work than just you doing it at the very beginning, where you already understand how this thing is being built and you just put the proper line of code in there. So with this example, you can quickly see how costs could go and skyrocket the longer and longer they wait, because maybe here there's only 10 files. And four months from now there is potentially maybe up 400 files. And then when we get in the back into development, maybe we got something like 1000 different files to check through. And this little line a coat becomes harder and harder and harder and harder to find, especially if there's poor programming practices elsewhere in the production. And this sort of thing can actually lead to this. This number 80 of the 20% of projects failing. Um, that is an actual statistic. I forget what study was from, but it was semi recent and imagine all of these companies creating software that can cost millions of dollars. That means 20% of those $1,000,000 Softwares are just they fail. The company just wasted their money and has to gets none of it back. There's no r a y, no return on investment at all. That's really, really bad for the company. This cost is actually calculated in a recent study to be $85 billion a year. And that usually comes down to this. Is that a typical developer, Spence. 13.5 hours on this technical debt and then 3.8 hours on fixing or debugging additional bad code or even adding in more bad code. So you know you're sitting here and you're spending all of this time and money on fixing old mistakes, and you might actually be even implementing MAWR mistakes later on. And this is a big cost. This is for a developer that's paid $50 an hour. It could be, You know, this is upwards of about about $700 every single week for every single developer that you're just wasting because people cut corners at the very beginning. So software engineering at the whole allows us to all come together, create a central plan and to sort of prevent a lot of these bugs looking at this code, this is just a really quick example. So you can see Just sort of something physical to look at is imagine. You came across this line of code and you wanted to figure out what it does now. Typically, this isn't You know, this isn't too hard, but this could be really, really, really difficult if someone just went off the deep end in, you know, coating this thing. But right now we have to look at this. We have to understand what this is doing. And so we might even have to, like, you know, grab a quick piece of paper and be like, OK, true. Okay. False data. Oh, okay. This line of code is completely equivalent to this whole block, and this may be throws us off. Maybe it waste 10 minutes of our time to fix, even though it's just 10 minutes. If we're paying being paid $50 an hour, that's a few dollars of company time. And not only that, but let's say that entire file or every time the programmer wanted to do this over here, there's just check of whether a and B are both notes Knoll. At the same time, he added this every single time a programmer encounters is there going to waste that time, and it just increases the technical debt over and over and over. So in the end, what I'm trying to say is that the important part of this course is learning that design is important. If you're gonna be creating something that's, you know, larger than just a tiny little add on or a little tiny game or something like that, then designing it so that it could be expanded, it could be collaborated on, and it doesn't create these really bad situations later on is important. And that's we're gonna be going over in this course is how to do. All of that is how to come up with a plan and how to join a team and understand what they're talking about. 3. 1-2 Software Development Cycle: So let's jump into the software development sort of cycle, the the way that we engineer software with software. There are a bunch of different ways that you can do it and these usually called models, and that's how you actually implement these sort of five steps. However, these five steps are usually crucial to getting a piece of software up to standards that are, you know, very reliable. With this, you'll also notice that these can be applied to really any engineering practices of like in the last lecture. When I talk about building a bridge, this could be sort of used for that as well. We would go over requirements and design and implementation and verification and maintenance all with a bridge. So if we want to think about it like that as we go through this, it might make it stick a little bit better. The first thing we want to talk about is we want to talk about something called requirements, so the requirements it are pretty simple. The requirements are what are we building? So the requirements are the what? What are we going to build? We want to be able to get that to a point where no one will be able to contend what we're building. What I mean by that is we don't want a group of eight people building this all with a different idea of what the end product is going to be. We don't want them thinking that, you know, maybe one person thinks that it's going to use eight servers. One thinks that is just gonna be a local server. One thinks that where it's going to be a business run, like it's gonna be used mainly by business people. While someone else thinks it's gonna be used mainly by consumers. That would be a big problem if you're trying to get like a whole bunch of people to work together on a project everyone would build in a different direction and it would fall apart . So with the requirements, what we're trying to get is the what what are we building? And there's a whole bunch of different little steps in each one of these, and that's what sort of this entire course is gonna be about is jumping into the So this is just a top down view and I'm gonna do a deep dive, a little bit later. So anyway, requirements is 1st 2nd is design. Design is the How so How are we going to build it? What are we going to use? What sort of technologies that we're gonna put together? How with the server gonna be set up? How is the front in going to be set up? Should the front end do this or that? That's where design comes in and design is very important. A lot of people skip this step. Ah, lot of people will do the requirements, though they'll do requirements, But then they won't actually go down to design. They're just sort of jump straight into implementation. So you know, they'll be like, OK, we kind of have a good idea of what we're gonna build. Let's jump in implementation. And that could be dangerous because again, there are still some variables out here, and there's still some things that we want to make sure work before we implement them. Because, for example, let's say that you built a eight server giant masterpiece or at least you think it's a masterpiece. And then when you click, you know the play button, you finally get it running. You realize, Oh, this doesn't work with eight servers. It only works with to service. It only works with this sort of technology. I'm gonna have to restart and start from the very beginning. That's the sort of things you want to work out in the design portion. The how portion After you go design, we jump down into the implementation and everyone knows what implementation is. Implementation is you just build the thing. So you've done all the planning. Everyone's on the same page. Now you're gonna divvy it up into Maybe you have teams. Maybe it's just a group of three people. Maybe it's just yourself, and you're just gonna did get up into certain, like, tasks and milestones. But the implementation part is the building part you're gonna you're gonna build the product, you're going to create what you have set out to create, and then the next step is verification. So, with verification, what we're doing is something called testing. So we are trying to figure out a crucial question here. What we built is it what we wanted to build? This is often times ah, couple different things. So, for example, is what we built what we wanted to build is what we built. What our client wanted us to build is what we built working properly. Is it Is it the input going in? And it's, you know, creating the proper output. And this is why testing comes in a play, and usually with testing, you need to know the requirements. You need to know what was it supposed to do and then with testing Utkan test against that doesn't do what it was supposed to dio. So this is a very important step. And this is another one that's often times sort of for gotten. If the time crunch people like, Oh, no, don't worry about testing will just do some quick major tests and then we'll move on. And that could be a big problem because then you have those giant bugs in your program. Maybe they don't manifest themselves for a couple of years, and then it leads to a giant data security breach. Or maybe it's just something very small over time. Maybe all the data going into the database is off by one, and it sort of skew your data, and then it will cost a whole lot Later on in the maintenance phase, which is this phase right here to end up fixing it. So verification and testing is important. We'll cover some techniques on that and some of the ways that you should be testing. And then finally, what we have is we have maintenance. And this is that sort of that end cycle where you're going to be fixing bugs. You're also going to be sort of maybe even doing more testing may be implementing some other things, maybe redesigning things. Maintenance stuff is sort of the way this cycles back a lot of times. If you're for example, developing an additional feature, you would actually cycle all the way back to the requirements and then start this process over. But the maintenance cycle is typically just fixing bugs, making sure that, like little adjustments to make it more in line with the requirements and keep it running to make me not do server updates and update this technology in that technology. So maintenance is important and maintenance can be very, very sort of difficult if you don't go do all of these steps. So there could be a ton of bugs if you don't have all these, and especially if there's no documentation in this. So you didn't write anything down? You didn't actually have this whole plan written out. Then it could be very difficult because you can't really bring in other programmers. It'll take them six months to learn the code based, etcetera, etcetera. But anyway, this is the top down view off the typical software development cycle. Now throughout the rest, of course, we're going to start breaking these down a little bit by little bit and then sort of deep diving into each one of these and then looking at neat things like models which are all, like, how you combine these different steps the best way to do it, you know? Do you do it like a V where you sort of put some of these on each side of it? Do you do it? There's these things called Scrum in the waterfall meant that will go over all of that. But software development cycle, uh, really good to know. And you're gonna be seeing it a whole lot 4. 1-3 Software Cycle Example: Let's go through a little example to help submit this just a little bit more before we start deep diving into each of these areas. Let's go over an example here. The example is gonna be simple. It's just gonna be how to build a form. Or mainly what we're doing is we have this goal. We want to build a form, it's gonna have a email address place, and it's gonna have a comment place and that's it. We just want to go over what went. We do it. The requirements design, implementation, etcetera. On. This is a very basic example. You could actually get really in depth and actually come up with a big documents for something this small. But I just want to go over some of the basics. So you understand what? How each of these areas works a little bit more. So the first area we want to look at is the requirements. So what do we want this form to dio? We wanted to collect email, address and message. That's what we want the original form to do. It's gonna collect an email address and a message, then sinned, too, and store in a database. So it sends that information across the Internet into our database. And then we want the prevent the user from bad input in this means in the email address, putting all these random symbols and not actually creating an email address in the comment section. You know, trying to insert code or do a SQL injection attack or something like that would prevent that sort of things. So three basic requirements here, then we're gonna go into our design. What do How do we want to design this now, with the design, you can come up with a document or you can actually sort of drawl it out. A lot of times you need a front end and back in design. So, you know, maybe we just have a quick box. Here we have the email place and then the larger comment place, and then when we draw it out, we would go, Oh, actually need a button to to submit that. So maybe we want to put that into our requirements. Needs button. Exactly. So you know, just something toe. Uh, you could always go back and forth between the requirements of design, depending on the model use and we'll talk about that more later. But with our design, we want to use HTML and CSS for building the frameworks of the form. So we want to build the sort of what we actually look at as HTML and CSS. Then we want to use JavaScript for verification of the input. And then we want to use Jake weary in my SQL for contacting the backend and Jake were you haven't heard of. It is just JavaScript, but sort of adjusted. So you can send sort of post requests to a database, and then my SQL is just a database. The next part is implementation, and this is really, really easy. This is just code and document. The work will easy. In this sense, this will actually be where most of the time is spent. After we do these two things is just sort of working it all out, setting up a server, setting up the front end and the JavaScript etcetera. Now into verification A lot of times the verification, the testing is just sort of an extension of the requirements. We ask questions of the requirements, so collect email addresses and message. Does a form collect information. So we would create a test to test of the collect information, send you and store in a database. Does the form send that information to a database? We could do tests on that. We can see, you know, in, put it in the front end and then go check our database and make sure it's making it in the back end. Do maybe corner cases trying to insert 100 different browsers at the exact same time, or trying to insert them all in sequence, maybe half a second after each other. Maybe there's a queue that gets overloaded or something, so those sort of tests will help make sure that you don't lose information and then finally prevent user from batted. But try to do a SQL injection attack on yourself. Try to put really random characters throughout. That wouldn't actually be a message, maybe even spam prevention. Maybe we want to build a spam prevention thing in here, and we need to put that in a requirement to design. But we test that as well, and then finally we have the maintenance, which is just create a lifecycle plan and fix any bugs. Lifecycle playing could be a simple as check on it every six months to make sure that all the technology uses most up to date and same with the database updated every six months. Check any bugs, maybe update that every six months. Or maybe you have a weekly schedule of how bugs come into your company or whatever. But a maintenance is just kind of coming up with a plan to make sure that we can adjust it to meet the requirements to meet what we wanted to do and also to make sure that it isn't vulnerable. And there we have it just a very, very simple example here of how you might go through these steps, how you might sort of categorize just building a simple form. Now, in these next lectures, we're gonna start jumping into the really the in depth part where you can actually sort of use some of the tools that we talk about to build to do this. But for something much, much larger in scale 5. 2-1 Requirements Definition: let's begin our deep dive into requirements. The first I'm gonna go over is the requirements definition, something that we are all on the same page with. So we all understand what I mean by requirements. So requirements are a way of figuring out the exact specifications of what the software should do. You can think of requirements like a definition. You're defining what the software should do. It's like you're looking it up in a book and you're able to read exactly what the software should dio. That's important. We're not trying to figure out how it should be created. We're just trying to figure out what it should do in the end. If the user interacts with it here or for, you know, and user interacts with it there, what is going to happen? What do we want toe happen? What is the purpose of this system? And that is why it is a process for finding out the goals of a system. So in the end, the requirements are just trying to find out the goals of the system. What we wanted to accomplish it captures the what and not the how that's important is we're just trying to figure out what not how we're trying to create it. The how is for design. A lot of people might come up with a requirement of will use C, S S and HTML to build the front end. And that's not a requirement. That is three. How that's what we're going to be using to build the front end. And so, therefore, that is a part of the design requirement. Might be. Uses a email address field to capture email address. Or we want to capture the email address and a comment. So we're not telling how we're going to do that. We're not trying to define technology on how we're trying to do that. We're just saying, What do we want the user to be able to do? What do we want? The end goal to be? And overall, the requirements usually creates a document which lays out all of these details. Usually there's like there's bullet lists or there's, you know, if he's real official, you have, like, requirement for two A or something like that. But a lot of times, if you're just working for like, medium or small companies, it'll just be sort of a list of the things that you want to accomplish and the use cases that you want the users to go with. So then let's cover the importance of requirements. Why did we use requirements? What? What is it saving us in the end? It just sounds like, you know, we're just spending more time. We could be coating well with all engineering. And this is important. Is that any engineering? You dio any engineering you dio you have this sort of golden rule and the golden rule is that spending time strategically upfront reduces cost and time later on. Now, this is data from a study that showed if you spent strategic time out from the reason I say strategic is are not just talking about, you know, before we designed the thing just talking back and forth for, you know, 40 hours we want to actually be, you know, focused work here, designing it, finding potential problems, finding all of the possible use cases, you know, creating basically the code before we even touch the code. That's what I'm talking about. So spending time strategically upfront reduces cost and time later on, and this is sort of the trend here. No, Lotus, that the trend is a little bit of a sort of like this trend of wasted time. So there is a point where it doesn't, you know, help you to use more upfront time. So, you know, if we're going within 50% of all time, it's not going to do much of a change here. It's not actually going to reduce the overrun cost. You notice that this doesn't go down to zero. That's because most projects always go over 40% over. The budget is kind of the norm, and a lot of times it gets up in these big numbers because people don't plan accordingly. But this is just saying of the total time here. So this is time total. What we're talking about is if we spend 0% of our time, so we're spending absolutely no time up front. The typical cost over on is 200%. If we spend roughly 3% and roughly 5% we had 100% and 50% so we just been 5% of all of our time very, very small chunk of time, you know, if he spent 100 hours We're talking about five hours up front, just going over this thing. We can save ourselves 150% of extra overrun. And this is cost over on in both dollars and in time. So it's also it's both of these usual because the two go hand in hand with one another. If it takes longer, it's gonna cost more. You're paying your engineers your paying for healthcare, your pain for taxes. You're paying all this stuff. And the longer it takes for you to start making your money back, the more it's gonna cost. And then if we go 10 to 20% we get that golden area where we get just the 40% overrun. And so you know, what's the difference between this? Let's say that we spend 0% up front and the product should have taken 200 hours. Well, that's just some simple math here is gonna have a 200% overrun, which means we're looking 100 overall will be 400 so a 200% over on it's gonna be about 600 hours to complete this project when it should have only take in 200 That's giant giant jump right there of time that it should have taken where if we just put 5%. So in that 200 our project, if we had just designated 5% or 10 hours, then we would be on Lee at a 50% overrun, which means our total would be 300 hours. So with 10 hours of of effort here, we actually saved ourselves 300 hours of back end problems. And that's just sort of like the power of all of this is that spending time up front helps out requirements. Document is one of those things to spend the time up front and same with the design document. But both of these are very important. They get us on the same page and they get us working efficiently. 6. 2-2 Requirements vs Specifications: There are a couple of different categories whenever we talk about the entire arching step of requirements. And these categories defined different aspects of the system that we're trying to build in this lecture. What we're talking about is requirements and specifications, so there's a major difference between the two and you'll see at first they look pretty similar. But whenever you start diving into this stuff, you understand that there is an importance between the two. The verse that we're gonna talk about is going to be the requirements. So with requirements, what our requirements will. A requirement is a non technical definition of something the user requires from the system . So what this means is it's put into layman's terms. It should be understood by just about anybody. So no jargon. Now this this sort of no jargon is talking about no computer science, no programming jargon. If you're doing like a medical form, you know our quest for treatment form. You can put in jargon in the medical field or in the construction field into the user requirement, because our audience is going to be either, you know, the medical field of the construction field or the app Development field. That's perfectly OK. However we don't want to put in is jargon like my SQL or Jason anything that this should be able to be read by the construction manager or by, you know, the automobile factory manager. He should able to read this and understand. Yeah, that's what we want in our system. So with the requirements, we don't want any computer science jargon. So, for example, a requirement might be ability to submit a request for treatment medical form. Do we know what a request for treatment form is? Not really? Doesn't matter for us. What we know is we've talked the client and they say they want the ability to submit a request for treatment, medical form and with this weaken Inquire about that later. But we know that it was going to be a medical form, so therefore there should be some security on there. It's gonna be some sort of contact form from the request for treatment, and so that's gonna be our requirement for this step. And then, like I said later on, we can clarify with them exactly what they mean. Then we have these specifications, so the specifications are basically technical notes, notes about what needs to be done to meet the requirement. So in this situation, it's a technical definition of what is required from the system. We're gonna keep it simple. We're not trying to design it here. That is very important. This is the biggest mistake you were not trying to design it. What we're trying to do is just, basically, though some top level keywords in here. So we understand the importance of certain aspects of the requirement. So in this situation going off of this requirement, a specifications might be to send in A s to 56 encrypted form data from the front end to the backend server. You'll notice that we have a little bit of jargon in there. We got front and we got back in. We got a S C 2 56 encrypted, but none of that is defining the technology. We're gonna use none of it saying that we're going to take it and pass it over like this through this medium, like, you know, sort of that very deep explanation. You'll notice that this is the incorrect. This is what we had put in the design document we're going to use encrypt, which is a technology to encrypt data within JavaScript to send A S to 56 encrypted. Jason formed at it again. That's a way of formed out. We don't need to know exactly the technology we're using formed out of from JavaScript. That's a technology to my SQL server, etcetera, etcetera. There's too much jargon in this. There's too much basically defining how the project is going to be built. That's not what this phase is about. All we're trying to say is that we need some encrypted data. We would prefer it to be the Secure A es 2 56 And you know, nowadays it it's probably we would want to use a different technology, but this is just for the example. But anyway, we want to use A S to 56 we want to take it from the front end, where the user can connect to the back end. No more information needed after that. When we get to the design set, then we can start bringing in the technologies that we're going to use. So let's go over a couple of examples here. First example is let's go back into the real world. Let's talk about creating an SUV tire. And with this SUV tire, what we're gonna be talking about is basically just a simple requirement and in some specifications that might go with that requirement so that we can again see the difference between the two. Typically, whenever we're talking off this stuff, we will say user requirements and system Sessa vacation. What this means is it's sort of defining it. So everyone's on the same page whenever we're talking about requirements were talking about what the user wants to be able to dio. Never. We're talking about the system specifications. We're talking about how the system should operate basically, so some of the constraints some of the requirements with the system itself. So the user requirement were saying the tire must work on an SUV type automobile. Or maybe the user must be ableto put the tire on an SUV type automobile. Any warning of that captures the point. We have a user. He wants to be able to take this tire and put it on to an automobile. That's it. Now the specifications. What does this tire have to do? What does it mean? to take a tire and put it on an SUV type automobile. And again, you see, this is a tiny bit of jargon, but that's OK because we're in the automobile industry. Therefore, we can use automobile industry jargon up here. We're not talking anything specific until we get down to this part. So what we're gonna just going to say is the tire must be able to support up to £7500 of downward pressure. The tire must fit all us dot standards for mounting the tire must fit all ust safety. Uh dot safety standards and the tire must have tea or greater speed quality rating. You don't need to know what any of you know this means, But what you can see is that up here we have the very basic requirement. And down here we're just specifying some of the things that the tire should dio. We're not talking about the exact, you know, chemistry of the rubber that should be used. We're not talking about the the air pressure inside the tire to acquire the £7500 of air pressure. We're not talking about design. All we're talking about is just some of the constraints, some of the things that we need to implement into this tire. Finally, let's take it back just a little bit too back into the tech world. So now we have this other requirement. The users should be able to upload a video to the website. We have this big website. There are 100 of these requirements and this is just one of the requirements. These should be able to upload a video to the website. So now we just have some specifications down here. What should the user should accept? H 0.264 move and mpg files for upload These just categories. We're not saying how they're gonna be, except we're not saying the technology we need to use to accept them. Just how are they? What should we be able to accept? What what we mean by a video. And so we're sort of specifying that with this just a little bit, and then the upload the up loader should compress the video and save three different copies to the server again. That's not something new user really needs to know about. That's just something that we as designers of this website are looking at and saying late, we're gonna be wanting to take this video and use it in certain ways. We should compress it and save it to the server again. We're not mentioning the type of server. We're not mentioning the dimensions of the three videos. Just it should have the ability to do this. And then finally, a link to the compressed video or video is depending on how we want it to be. Should be sent via email to the user after completion. Again, we're not talking about email servers or how we're gonna format the email or you know what the link should look like. How the video player, any of that stuff. We're not talking about that. We're just talking about a specifications here. The link, after it's done should be sent to the user. And of course, this might not be all inclusive. There might be more that we need to sit down and start marking out some more. This and then maybe we have another requirement. Therefore, we need even more specifications, etcetera, etcetera. But I hope overall you get the idea of what the difference between a requirement and the specifications is requirement deals with the user. It's very basic. It's in layman's terms, something that a client can look at and go. Yes, the program should definitely be able to do that or no, Maybe that that doesn't define exactly what we want. And then the system specifications is like our notes. It's like the developer notes were saying, Okay, so the user wants Bill to do this, and what he really wants is he needs to be able to upload these types of files. He needs to be able to do this with the tire needs to fit these standards, and that's what the system specifications come down to. 7. 2-3 Functional vs Nonfunctional: the other two categories that we really need to discuss when talking about requirements are nonfunctional verse, functional requirements. So what is the difference between these two? Will the functional requirements are requirements and specifications pertaining to the function of the program? That's the key word here. It's the function of the program here. So what we're talking about is what should the system due? In the end, what should the system be able to accomplish were building a form. We go down the list of the things the form should be able to dio It should collect data. It should send data it should protect against input. It should do this. It should do that now. Nonfunctional are the requirements and specifications on what goals should be met. For example, security. What should the form now to be encrypted like or cost? How are time constrained? Maybe How long should the form take to submit? So maybe the form should submit data to the server and down here in the nonfunctional requirement. On top of that, it should submit data within 500 milliseconds. Let's say that that is not something that this that the system overall does so Therefore, it's not functional. It's something that is it constraint. It's something that needs toe happen with the functional down here, we can take a look at unexamined that went over earlier. So remember the Send A s to 56 encrypted formed out of yada yada. We can break that down to sort of break thes into functional and nonfunctional. So the 1st 1 is sinned, formed out of from front and a back end server. What is that doing? Well, it's a function. It's taking data, and it's sending him its defining. What exactly are products should do? And so for this one, we're talking about a functional requirement. Now the bottom one is a non functional. You can see I've taken out the whole encryption part of this to sort of break them up and you'll see that whenever you're right requirements things got a little wishy washy might actually combine to, and this isn't an exact science. However, going through it, you might be able to knock out some of these things and figure Wait, We should put these in two separate categories. Sort of things. Any hope. The bottom part. The encryption part is the non functional, the non non functional. A lot of times is referred to his NFR nonfunctional government, and this is fr. A lot had to take off the are so nonfunctional functional, uh, but anyway, this is not something that the program should do. It's not an operation. It's not something that the user is doing that you know. If he can't do it, then there's something wrong with the product. It's a requirement. It's something that should be happening with the functional requirements. So the functional requirement is sending the form data. And then the nonfunctional requirement is that it should be encrypted that it should only take 500 milliseconds, that it should send it to three different servers before it gets to our server. For some reason, it's the nonfunctional behind it now. Nonfunctional also has a couple of different little categories, and what these categories are are basically some of the different sort of tears of nonfunctional, and you'll start to understand them just a little bit here. More so the 1st 1 is the product requirements, something that the product must do again. It's not something that product is, you know, acting with the environment with its not changing something. This is just a way that the product should be designed, a way that it it should integrate with the world. And let's say that you have a client that is, maybe he's leasing out the ability to create this software, but at the end, he wants to maintain it himself. Therefore, he needs it coated in specific language. Java. There's no talk of design here. There's no back and forth. This is a requirement. It's something he says. The program must be coded in Java. That's it. There's no discussion on this point. Therefore, that becomes a requirement now. Is it the way the problem the problem functions? For example, we could create a Web page that has a form we could created in Java or CSS and HTML and JavaScript, or maybe even python or ruby. We can create in all these different ones, so it doesn't matter what the coding language is. That's not part of the function of the program that is a non functional requirements, something we have to do. But the program doesn't react because of it. Therefore, we have this nonfunctional and it's a product requirement. Then we get into organisational requirements, and this comes down to usually the policies and standards and the styles and the rules of the organization you're working in and with. So, for example, maybe the organization you're working with is a military organization. And they say any time data changes hands, it has to be encrypted. Doesn't matter if its internal or external it has to be encrypted. Therefore, one of our organizational crime. It would be the product data must be encrypted by ES 2 56 And again, I use this all the time. Um, just because it's an easy encryption algorithm, of course, military standard. There's probably gonna be something way, way stronger, but doesn't matter. That's that's the technology here. What I'm talking about is that they're telling us we have to use this. Or maybe it's our own company policy. Whatever it is, it's not talking about the function of the program and how it interacts with the world around it. It's talking about how it should be developed and what should happen within the program. And then finally, for the organizational we have, the project will be developed using the scrum methodology. We're in a company that uses scrum and there is no arguing about that. There's no talk about this, so when we get to design phase, that isn't a question that's not something that a bunch of engineers come together and come up with. Therefore, it's a requirement. We're in a company. It uses scrum. Therefore, that's a requirement. And it's not talking about how the program interacts with world, which I keep saying, but I'm trying to drill this home. Therefore, it is a non functional requirement. Then finally we get into the external requirements and this is just something. Whenever we're talking about external things that sort of push onto our product and this could be external laws or regulations or even trends that we need to follow and therefore what we have is we have these that come together into these requirements. For example, let's say that the U the European Union has some law, you know, the Freedom Act, Article one, Section two, that states at all data must be using this sort of encryption SSL encryption between data points or whatever. That must be a requirement, because if we're gonna design up, he's a software that we're selling in the U It's gotta fit that. Otherwise no one's gonna buy it. And if they do, we'll get sued by the government, and our product will be basically a liability to us instead of an asset. And we don't want that. So that's an external requirement. There might be also certain trends. Maybe there's a certain security trend or a certain trend, like the Web page must be able to load within two seconds. Ah, lot of people will actually leave Web pages if they don't load within two seconds. It doesn't show something that's not exactly, ah, law or regulation, but that's a trend. That's something we should have fault. That's something that should be implemented into our program if we wanted to be competitive in the marketplace so that we could put down here and external requirements as well. But that is the the last classification of requirements here. We got those nonfunctional. We got those functional requirements. Just remember a functional requirements how the program interacts with the world around it . It's changing something. It's moving something. The user is able to do something because of that requirement. While the nonfunctional requirements are the things that the program should be able to do their things that not necessarily interacted the world. But they constrain us. They make us have to do something. Therefore they have to be put in their requirements documents. 8. 2-4 WRSPM Model Introduction: So let's jump into the first model of the course, and this is gonna be a model that sort of encapsulates the entirety of software production . It's something called the W. R S P M model or, for short, the world machine model. And what this model, the pics, is the interaction between the environment and the system. And this is important because you have to understand there are a lot of different aspects that go into a piece of software that a lot of different things that you might not think of that you have to think of when designing a piece of software. For example, whenever you have an application on your computer, you have to have an input and output device to communicate with that application. So, for example, if we're using something like a photo editing software to actually edit the photos, we not only have to do the program itself, but we also have topped the hardware that it runs on, which is gonna be your personal computer, and you have to have input devices. So, for example, a keyboard and a mouse, and then on top of that, you have to have the human being that actually interacts with all that and understands how to use it all. So this is a way of categorizing that so that we can look at the requirements of a system and see if we're missing anything to sort of look at it. And are we missing an assumption that were supposed to make? Is there a particular element that we're not taking due account? It just allows us to put those end up to the right place. So then the left side of this Venn diagram is something called the environment, and this is where the system is going to be operating in think of. For example, a team is something that is used quite often to categorize this. So, for example, we have an A T. M machine here, and if you live in another country, it's a money dispensing machine. I know different countries called different things in America. It's called an a T M automated teller machine. Basically, you go up to it and you get money out of it. Pretty simple, but you've got to think that this is a team. It's working in the world, the sphere of the world, and then there's a program inside of it. There's a little program running, and then it connects to something outside. Maybe it goes to a big server or banks or something like that. But there's all these different elements that go into it. The left side of the environment. What is our system working in? And here we have two different sort of areas or two different things that we look at and the 1st 1 is W. And the W is We'll see that we're gonna be going through all of these letters. Here is world. It's the W right here. So the world, this usually comes down to assumptions assumptions that we have to make whenever we're making a software. And these could be really, really sort of simple and almost quote unquote stupid assumptions. But they need to be made, for example, within a team we have to. One of the world assumptions is that there's a bank on the other side that has money that this there's a purpose to this a team that there is an entity that is actually keeping track of these transactions, and therefore the team has purpose. So one of the assumptions might be that there are banks, that money exists, that their money is a sort of an entity. Now, of course, you might not be able to complete you know, a better way to design your program with that assumption. But by putting the assumption in there, you start understanding the program just a little bit better. And then you get to things that are important, like the A team. Must we have the assumption that the A team where this machine is always gonna be connected to electricity Now, that's an important one, because you might be thinking that you want to put it into ah city that has a maybe not the best power grid. Maybe it turns on and off every 30 sec are 30 minutes. Maybe it, you know, one or two days a week. It has a power outage of an hour or more. That's an assumption you gotta think of. OK, do we want the A team just to shut off? Do we wanted to have a backup battery? Do we want the program to reset? What do we want to do with all of this? And so that is very important. Whenever you are sort of going over this stuff is to understand these assumptions, so you don't miss any requirements, and that's the next part is the requirements. So the system is sort of this side of things. And before we actually build the system, we need to understand in a conceptual idea, What are we building? What is this system doing? What's the purpose? What is it trying to accomplish? What problem is it solving? And so that's where the requirements come in. That's part of the environment, because the environment has created a problem. The environment has generated a problem, whether it's just a passive problem, something that we think, Hey, this could be fixed or whether it's an actual problem, something where were something that maybe humans generated or that overtime society has created and therefore we work. We create our requirements. Then the next step is we get into this sort of the blending between the environment and the system, and that's where we get into specifications. So we put the S right here. Specifications goes over the sort of, um, the fine details of the system. So we're still in that environment thing. We're still in solving the problem, however, were also building the system were also determining what the best thing for the system is. We're getting technical details out of the way, so this is where the to blend we're actually building. This part is a lot of times referred to as the interface were building the branch between the environment and the system, the terminal for connecting the world to this program. And that, of course, leads us to the next one down here, which is program. And so now we're into the system. So the program is the code itself. The program is what's executing. It's the if else statements. It's controlling the hardware. It's grabbing the data. It's sending the data. That's what the program is. There isn't anything to advanced on that, but it's sort of the biggest part of software development is actually creating the program , and that's why we're gonna be talking about that basically for the rest of the course, and then finally we have the machine, and this is important because we need to understand what hardware is it running on? The machine is the A team itself. It see the actual entity Ah, the ram, the CPU the networking cables, the Internet service provider servers. It's all of that stuff. It's the physical entity that program will be running on. And this is important to know, because maybe we dissolve the program that needs to use an Internet. That's, I don't know, maybe 100 megabytes per second. And we realize that not anywhere carries that Internet for an a t. M. So we need to rework our requirements. Maybe we need to add a requirement where it has to be below 10 megabytes per second, things like that. So that's just important to consider throughout this now is also another little category in here, and we can create these other little circles like so. And what we have with this is we have something called E h E V. And then we have, um SV s H And so what? These are are they just mean environment, hidden environment, visible software visible and software hidden. So environment, hidden environment, visible software or system visible system hidden. And what these are is they just sort of determined a little bit more of sort of classifying the environment. So with the environment hidden, we have things like ideas and pieces of data that ah, human knows for example, e h would be a pin number. That's a piece of data. It's a It's a concept. It's something that we need to incorporate. However it's hidden, it's not actually gonna be available to. The user is not posted on the side of the A T. M. It's something on Lee. A human being knows in their mind. Therefore, it's an environment variable, which is hidden. Then we have environment visible. An environment visible is the things that are actually exposed to the real world. Whenever you actually enter that pin number into the system, it now becomes visible. It becomes quote unquote steel herbal. Someone could look over your shoulder and take that. So a lot of times environment visible is the data that's actually entered its those sort of those concepts in your mind when they're actually entered into the system. And then you have something known a system visible, and this is pretty simple. It's the visible parts of the system. It's the things we interact with on a computer that would be the keyboard and the mouse on an A T M machine. It's the place where you insert the card. It's the pen pad. It's the the ways to go through it. So this is the sort of the outside of the though the interface, the way that we connect with things. And that's why you can see that this is all part of that interface. Here we have data that's coming out of the abstract, which means, like not concrete. It's it's just information stored in our minds or maybe on some other device coming into the interface. And with that, we enter it into the visible part of the machine. So this is, you know, the visible part, the visible part of machine. So, for example, it would be that little area where he entered things in. And then we have software hidden and software hidden or keep saying software. But system hidden is the back end. It's that ram inside. We don't need to know the inner workings of an A t. M. We press a button. The A team inner workings do what they're designed to dio. Same with a lot of software. We, you know, if we grab two sides of an image that they were reading in an image and we want to. The image looks like this, and we want to rotate the image to the right. We click Whatever button is in our software that, you know, maybe has, like that arrow button on it, and it rotates. We don't need to know the code that goes into that. We don't need to know it. Taking all of the ones and zeros and applying a formula to it and doing all this stuff. That's the hidden part. The the system visible is that button that we can hit. And so those air again things that you want to consider whenever you're creating these variables or just, ah, these requirements or the sort of problem scope is just want to understand What's the environment hidden? What's the environment visible? What's the system visible? What's the system hidden? You're making a really big piece of software. These things are vital to understand the full nous of the problem. Next, lectures were actually going. We're gonna keep diving into this, so let's keep going 9. 2-5 WRSPM Deep Dive: Now we have a better understanding of the WRs PM model may be sort of a rough understanding of it. Let's jump into a couple of examples and sort of further explain each of these areas. So they were all on the same page here, and we could actually maybe implement this in if we ever had to do a requirements document . So let's jump into each one of the categories and just want to sort of define them a little bit. We have the world, and like I said, the world is basically the assumptions, the assumptions about what we are developing. They could be something that is very, very basic, like electricity is provided. Or they could be something pretty not basic. For example, with a car, it might be that humans know how to drive cars or that humans know how to use a pedal and a braking system. That would be an assumption that we need to know, because if we're inflating a new system, maybe we need to add a tutorial to it. Maybe we're assuming too much from the user, and that's going to make our product fail because we don't actually spend any time developing a system or a tutorial. Maybe that needs to be a requirement. A proper tutorial that is tested is presented to the user. That's very important for new software that's up decently complex. If you don't have a good set of tutorials, even if it could do amazing things, no one uses it. So then the 1st 1 is the world. The assumptions about what we are developing the next one. Other requirements defining our problem in generic, easy to understand terms. We need to know what our problem is. We could say we need an automated teller machine. We could say we needed to get money by not going to the bank. That's a great overview problem. But now we need to define. What that actually means doesn't mean we need to installed people around the city that we could go up to and talk to. To get money doesn't mean we want to make it. Automated doesn't mean that we want to have it, you know, extremely secure. Maybe we want to make use of access. More important, we need to define the problem. What's the problem? What solution do we think is best to solve the problem specifications is the next step of it. We're defining the more technical details of the interface where building. So we're actually defining that interface, where with the specifications we have this sort of problem defined. We know what the problem is. We know what the assumptions are, and now we're kind of looking at How do we connect the user with the program? What's the way that we do that? What technologies should we have to use? Like, what technologies do we have to use? What are some of the more technical details about how that all works? Then we get to the program, which is this the code frameworks and development process? The program you could sort of define as the rest of this course going over to the design documents, going over the actual coding aspects, the maintenance of it, the ways that you can develop, that that's sort of the program aspect. And then the machine is thief physical hardware running on. At some point, if we're building a new piece of technology like in an a TM, we might actually have to send it to a manufacturer and an electrical engineer to actually put the inner workings of this thing together. Otherwise, we just have this program that would be kind of cool. But there's nothing to run it on, so we need to understand the machine as well. Is their existing technology out there, or do we have to develop that technology ourselves? So let's go over a little bit of an example here. So what we have is a smartphone photo printing station. We've seen these at Walmart. Maybe if you haven't seen them, I'll describe it to a little bit. It's basically like an A T M, except it's a little bit different. You have this sort of, um, machine here, and you can go up, and you can either insert a USB drive into like a little port, or you can connect via Bluetooth with your smartphone. And basically, what you do is you transfer photos onto the machine. It's got this big interface that with, you know, maybe like a keypad or buttons over here, and when the photos go on there, you edit them, and then at the end of it, it actually prints out the photos at the bottom almost in real time. So this allows you to If you ever went on a vacation, you took a bunch of photos on your phone. You can go up there. You can pay. There's usually a pay slot here, like with money or with a credit card. You pay, you get the photos and you're good to go. So that's the machine we're talking about here. Now, I would strongly recommend you pause the video right here and just go through this. I'm not talking. You need to define this entire thing. I mean, that would take a team, maybe maybe four or five days to be able to figure out every little idea of what this needs to dio. I'm talking. Go through each of these and put down a couple of things where some of the assumptions we have to make. What's the problem here that we're trying to assess? What should the user be able to do? What should the machine be able to dio? What are some of the specifications? How should machine contact things? Um, the program and the machine. I'll give you a hint. There's the machine is just this and the program is the software we're developing for us. You don't really need to focus on that we're really focusing on is the 1st 3 year deposit go over that? And like I said, I strongly recommend this and then I'll go over my answers to. So I've hoped you pause it and you went over your answers again. I can't dress. It's enough. The more that you put into the course, the more you're gonna get out. So please, just if you want to learn as much as possible, just do a little bit and it'll help you a lot because you can actually sort of start implementing this thing. It'll make you remember it a lot better. Anyway, let's jump into this. So the world, what assumptions do we need to make? Well, what I was Some of the assumptions that I came up with is some very basic and some things that we might take for granted. So people have a standardized photo formats, the print that's very important. Imagine if there were no standards or if people are coming up with really, really random one. Maybe every single iPhone or every single phone had a different way of storing photos. This would be there would be no way to create this. We could not have, Ah, system that decodes you don't 800 types of photos. It just wouldn't work. So I'm making the assumption that there are very standard photo formats to print from. People will be able to read the prompts and tutorial. Uh, have humans are basically literate. That's kind of what this comes out to is that there will be in a language that people can read and understand. If you went to a more illiterate part of the world, maybe somewhere that there's not a lot of education or reading knowledge. Maybe that's a problem for you. Maybe there's some other way that you can implement this with pictures or something that would help them better. Now, gladly. You know, severely a little It parts of the world are disappearing with further education, but that's something you might want to keep in the back of your head. Um, the next one is stories will re further materials. We're assuming that someone is going to go into this and refill the inks and the paper and stuff like that. We're assuming that we're gonna put these in stores where people actually do that otherwise would have to come up with some solution and distribution network to make sure that these air always refilled. So that's a good assumption. That's something that we would actually need to make sure. Is it a proper assumption or, well, we need to develop something like that. People have debit cards that work with standard debit card tech or in this credit cards or any card technology or money. In that case, there's gonna be a common currency that we can use on this machine that will work. There will be readily available electricity that's important. Without electricity, this machine wouldn't work and they will be available. INTERNET. Maybe this machine needs to contact servers. Maybe it doesn't have the hardware on it to do the photo edits and actually sends to a server server. Does the photo edits and then it sends the data back. That's actually pretty common nowadays, So in that situation may be we need Internet. And if we run a like the back country that might not work, we might not have available Internet there, and we might either have to put in a secondary, a little bit of processing power, and this just in case it doesn't have Internet, it can try to do it here. It'll just take a little while. Or maybe there's other solutions we can come up with. That's an important assumption to recognize next part of the requirements. What is the thing supposed to dio? So it's a user can connect a smartphone to the system. And if you notice maybe you want to go over the requirements first before you jump into the world, maybe you want to sort of define the problem and then understand sort of work out from that and see, like, what are some of the assumptions I made when making the requirements that might be a good set to these things could be done in many, many different ways. Just some ideas here, anyway, requirements the user can connect a smartphone to the system. The smartphone in transfer pictures over user can edit photos. The photos could be printed out by machine, and the use can pay for the service. In general, if you're ever in doubt about requirements, just go over a use case, basically a way of using machine. If you walked up to this machine, how would you want to use it. And how would you want things to interact? That's a great way to start with it with requirements every step. Just write it down and then you could sort of build from there the next part specifications . So then now we have this sort of this idea here of some of the requirements. Now we go into a little bit more of the nitty gritty. How do we connect to it? Will blue to technology? So a smartphone connect. That's the most popular way of connecting. So Bluetooth would be a good idea. And we need a proper Bluetooth transfer protocol to be installed and to make the transaction secured so that no one else can sort of jump in there. We need a proper or the system will have an editing suite from emulating photo data. That's important. We need to sort of define our editing suite. Do we want to buy it from someone else who want to design it ourselves? This system will use encryption and chip technology to contact financial servers. That's a great thing to know. How's it gonna contact the banks? How's it going to use it? We're using this encryption and this chip technology. So we're specifying the exact way that the financial transactions are going to take place. And then the system will have standard printing device for printing photos. So there's gonna be a way to print the photos out. We might be able to define that even more in depth once we start developing it. And then finally, we have the program, which I said it just system code and machine, which is just the system specs, the ram, the processor, etcetera. Overall, though, this is sort of what you do with World Model in just I mean, this took me maybe 10 minutes. We actually have a sort of a blueprint for what we want to do with this thing we have in a general idea. No one's going all over the place with how it should be built. Everyone could get on the same page, and we could present this and work this out even further. We could really start going through these things and actually developed, like a little bit of documentation, maybe like a 20 page thing defining the problem to finding how we want to solve the problem defining the specifications the technology needing and maybe even the system specifications of what it would be from that we could develop a budget. We could develop what teams need to be on it. It's a great starting point, and this is all very important for requirements to finding our problem. Getting them set and then getting ready to move on to the next phase is like design and actually coating the thing. 10. 2-6 Requirements Example: So let's finish off this section with another example of examples are really important because they allow us to actually get our hands dirty and to do the thing to actually go through some requirements. That's very helpful, because a lot of this information can kind of go in one ear and out the other. But if you actually do an example, then you can really cement that in your mind. And whenever something comes up, you'll remember maybe not every bit of the requirements and the definitions between the two . But you remember enough that you leave the bail to do an intelligent Google search for it, or you'll be able to do an outline and then look up maybe some other things that you should include in your requirements documentation. So with this example, what we're gonna dio is we are basically just gonna take, like, a real world scenario and just work through it with these examples. Remember, we're not trying to go 100% here. We're not trying out. Think of every conceivable possibility in the real world you might, but that usually takes weeks to do so in these things were just trying to get out. The 80% were trying to knock out, you know, the 80% of the requirements that might go into this and then, you know, if you really want to, you can sit down later and do the rest of it. Or we could just move on and sort of build on it as we go forward. So what we have is we haven't already built chess app. So let's say that we have a phone and where we've been tasked with an app, basically chest. So you know, chess, the game of chess. If you don't know what chess is, come up with any game that you do know. And so we have a game app, and we want to monetize this app to start making money. So that's our objective is to take this app this whatever it is, however it works, Maybe there is. Maybe it's an online at. Maybe it's really anything. We're gonna take this game and we're going to start monetizing, so we need to think about what other steps we should take. How should we define the problem and what will benefit both the client and the users and with all of this, we can use that world model again. Remember, we're gonna look for the world. So the assumptions we're going to look for the requirements. So what exactly is needed from this app, And then we're gonna look for these specifications. So what are some of the technical details of how how we want to implement this at what are some of the limitations that constraints that we have to follow? Let's say that the previous app is built in Java and the client wants to keep it that way. So that's when the constraints that I can give you as well, anyway, it would be very beneficial for you to pause the video and just sort of go through these three right here. And if you notice we didn't talk about how to monetize the out. So come up with something come up with an idea about how you might monetize it. Maybe there aren't ads in it and you want to add ads May be your idea of this app. Is it already Hades ads And you want to add some subscription model? Or maybe you want to create a paid version. What would go in the paid version come up with an idea about an app and then how you might advance that app and then kind of come up with the assumptions, the requirements and the specifications on that. And again, it's an exercise. Just be creative, have a little bit of fun with it, maybe spend five minutes on it and then come on back and you could see the way that I went with it. We can compare, uh, see the differences about how this and you also see there's a bunch of different ways we can do all this stuff, deposit video, do that and be right back. All right, So I hope you did it because I think that doing it by yourself and then seeing it again it's gonna be a great way to cement this information into your head. So the first thing I went over was the world assumptions, The things that we assume about this app, the assumptions are important because it allows us to define the requirements with the assumptions were then able to figure out we don't We don't have to define, you know, silly requirements like phones exists or something like that. We're gonna need to create a phone that it that can support apse with assumptions. We assume the world is a certain way and it allows us to sort of just put those things in a box somewhere else and actually work on the things that will help us. So in this situation we have that there is a way to pay on smartphones. There has to be some financial servicing on smartphones. For us to be able to do these transactions, there are ways to make money from an APP. There has to be some viable marketing technique out there to make money from an APP. If it these two don't exist, then we're gonna have to invent all that ourselves. And this task suddenly gets really, really large because now requirements is gonna have to detail how you know what the market is like, what the potential risks are, things like that. But if we can assume that both of these things exist, then we just have to think of Okay, what are the best ways to do it, then? The app is extendable. Maybe the code basis so bad that there's no way we can extend the app to something else, so we're gonna assume that it's extendable. Otherwise, this project is just gonna, you know, halt in the water. It's not gonna go anywhere. There will be an ability to contact the Internet and the financial institution. So the phone has Internet capabilities again. We don't need to define a new way for phones to connect to the Internet. We're just gonna assume it has Internet capabilities. The trashing the transaction could be made secure enough. We're gonna just assume that there is some way to secure transactions. People are doing it all over the place with different transactions, so there's probably a way out there to make them secure. The phone will have processing power to handle the request. We are hoping that these requests are gonna be low end and that the processing power will be there. If they're not, then we have to wait for new technology. Different currencies will be able to be accepted. We have a worldwide app. So maybe we're hoping that there's going to be currencies from all of the world that will be able to be transferred somehow. Maybe, for example, it Let's say the at market only accepted us dollars. That would change our approach a ton. But if we assume that there is a way to accept currency from around the world, then we don't even have to think about that. Hopefully the market will do it itself, and then it's legal to accept payment over a phone. This is important because maybe there's some country where it's not legal to accept payment without them being in person or something like that. So we need to understand the laws so we don't get into legal trouble. We need to understand that it, whatever we're doing is a legal process that we don't need to get lowers involved. We don't need to change laws or fill out some forms to get it legal. So that's an important one to assume and something you should think about with the requirements just in case. For example, if you're thinking about collecting data, maybe you need to make sure that there's a privacy policy. Maybe that needs to go into your requirements is that it's legal with a privacy policy, So now you have to put in that the requirement. So we know so then we have our world assumptions. Next up is the requirements. So I just went, do things that I thought would work. I just thought of an app that had ads already. And then a subscription model would remove the ads Something very, very simple. So the pro feature removed ads for the user I'm defining. What exactly are pro features? Gonna dio is gonna do something simple. It's going to just remove, add So that's gonna be our pro feature right there. So the next step is that the feature must accept payment from a user. This is pretty important if it doesn't accept payment from a user than there's no way we can actually charge them where there's nowhere we get buddy. Therefore, we shouldn't be giving the user anything. The feature must provide pro features upon successful transaction. We could accept the person's money and not do anything in the APP. Then our app probably gonna get shut down in the APP store, so we must be able to provide the pro features upon a successful and that's important a successful transaction. We need to check whether it's successful or not successful. The teacher must complete transactions in a secure manner again. We don't want data breaches. That's bad for really everyone. That's bad because it allows other people to get exploited and is bad because it makes us look bad. The feature or vote pro features once a subscription becomes invalid. So if someone stopped paying, we should remove the features. Otherwise, someone will just do it the first time and then just never pay again and still get all the pro features. The feature will provide a cancel button within the APP. That's not something that you have to do. Maybe nowadays, in the app sort that's starting to become something you have to dio. But maybe with our app, we value trust in our company. So we're gonna have that cancel button within the app that will send a signal that cancels the subscription for all future months. The usual extend off existing code base. We don't want to redesign this app, so we're going to try to extend it off the current code base. The feature mustn't add more than five megabytes to the overall download size. Maybe that's something that the the overall bridging boss said. Or maybe it's something that the client said that our app is already really large and people are complaining about it, so it cannot be more than five megabytes, something that could happen. So I threw it in there, and the feature must complete the transaction in a timely fashion. We don't want it to be a very, very slow feature. So we have this idea that it should be completed in a timely fashion and then with their specifications, we can actually sort of go into that a little bit more in depth. So now we have the world assumptions. We have the requirements, and now we have the specifications. The feature will be coded in Java with the existing APS language. Remember, what we talked about is that the APP was coded in Java, so that's a specifications at the technology. When you views is the existing APS language, we wouldn't maybe we don't have to specify job in this specifications. We could just say the existing APS language, but I like to be sort of blunt and really, really transparent and these sort of documents, the feature will use the Android play store for its transactions. This is something that we you know, there's a bunch of different ways that you can accept payment. You could like, for example, implement something called stripe, which is a technology that accepts payments. It's a transaction software. But for this situation, what we're gonna do is we want to use the Android Play store to do all of the transactions on. If we wanted to do this happened, maybe IOS as well. We use the apple store there. The Futural check for active subscription daily using Google's provided a P I. This is very technical, but something that is important something that the developers need to know is how often do we want to check to see if a subscription is still valid? Were saying that we're gonna be using the Googles AP I to check daily. If description is valid, don't do anything of it's invalid. Take away the privileges. Or maybe put a grace period. Something like that. The feature will turn off. Add mob. Once the subscription key becomes valid, add mob is a way of advertising inside of your APS. It might be moving to some new technology by the time you watching this. Maybe this is a technology that sort of defunct that no one uses anymore, but that's OK, All I'm saying is that we have this technology in our app, and we're saying that once the subscription key becomes valid, we remove that sort of. We remove that technology from the APP so that the user has those pro features. And then this is that last one, that one down here in a timely fashion. Let's say that we, for some reason we have a timer that it must be able to complete in 500 milliseconds. Once you click the OK button again, maybe this is passed down from the client. Or maybe it's just something that your company likes to do. They have this sort of idea of Fastness and they want to define it. So in this situation we have the requirement that it should be timely into the specifications. We sort of give the exactness of that and this. Like I said, it's not a 100% example here, but imagine if you had just this document to go off of, and someone handed you this document and said, I want you to code this. You suddenly have a very strong direction of what you want to do. And you also now have the ability to ask questions. They defined maybe 85%. And maybe you come into a situation where, like, there's nothing in here and now you can actually ask the appropriate questions to your client or to your business of Hey, what color should the buttons be, or something like that that wasn't defined anywhere in here? Is that something I should choose? Is that something you guys want to choose, etcetera. So coming up with this requirements document, it's a great way a great foundation to build software. Next, we'll be going into the design face. So once we get all this, it's time to actually get down a little bit into the nitty gritty and start going over how , exactly we want to build whatever piece of software we're trying to build. 11. 3-1 Architecture Introduction: let's start with the highest level of design and by highest level, I mean the least specific. So, for example, if you're maybe designing a city, you might start by zoning out the different areas. We want some residential over here. We want some commercial over here. We want some industry down here, nothing else. That's just a very, very basic plan about how the city might work. And that's sort of how the architecture goes. We're taking it from requirements and now actually kind of coming up with an idea about how the app should function. And so that is why architecture is the highest level, or the very top level of design. Architects are the link between idea and reality, so architects are people who implement architecture. Let's say that you have a building you're going to build before you break ground. Before you even have any idea or any people on site to build this building, you're going to come up with some blueprints. There's gonna be basically engineers that test the different parts, like saying we need at least a 15 foot ibeam here or we need this type of construction over here and you're going to be using basically this blueprint to build the building. Nothing's actually being implemented yet. It's just a design, and that's what the architect is doing. Someone had an idea for a building. The architect takes that idea, and they build a plan to put it into reality. That's why they're the link between it. They're not actually the ones creating it, and they're not the ones you usually came up with. The idea. They're the ones that are building that link between the two so that a construction team can build it, and the person who had the idea can see it built. So that's the importance of the architects and in software engineering. A lot of times we have to become the architects, so we have to take our requirements document, and we have to transfer it over into a plan about how to actually build it so that we again maybe with a software programmer as well. We can implement the idea. That's the importance of architecture is providing that link. Now architecture is important. It's something that cannot be fixed, once implemented or in software in the world role that cannot be fixed and software engineering It might just be really, really, really hard to fix, but sort of view it as something that cannot be fixed. Once implemented in software, bad architecture is something that can't be fixed with good programming. If you design the architecture of an app poorly, no matter how good your programmers are, it's still going to come out as a poor product that takes way too long to maintain, and that is very hard to extend and make better over time. Imagine trying to fix the foundation of a skyscraper after it was 20 stories high. So let's say they they begun construction on this skyscraper and they're about this high. You know, they're still cranes going and actually building the thing, but they realize that there's a foundational problem. The thing that the skyscraper is built on has a problem. What do you do to fix that? It's so much harder to fix him when you're 20 stories up, Then when you just have the foundation toe, look at it go. Actually, this foundation is not gonna work. Let's destroy and let's rebuild it really quickly. It will be really fast turnaround time up here, though you have to design some way to fix the foundation while not destroying the skyscraper. Or maybe the only way to fix it is you have to tear the whole thing down before you can build it again. That's a lot of times what happens and software engineering as well. We have to scrap a project and start over again. So architecture is really important. Let's sort of break this down and just jump into maybe a little bit more of a software oriented example. Let's say that we have this server right here that takes in our app. Let's say that we have a component over here, some something our app does, and it contacts this server rate like so. And let's say that we have another component over here, and it contacts the admin. It gets feedback, and then we have another one down here contacts this one. It contacts that, and then this comes out and goes into here, and this one goes up to there and you know, so we get this sort of really complex app that doesn't have a lot of, um, sort of things. It's got a lot of these, like crossbars that maybe go in and around. And so you can see that the architecture, this app might not be the best. And why might it not be the best? Well, let's say that we have a problem with our core interface, our core server, that the way that we designed it, maybe it's insecure. Maybe that there's a way easy for hackers to hack into this, and the only way to fix it is going to be to replace the server and change all the protocols. Well, with an architectural like this, imagine taking this component out and putting a new one in because of the way it's linked with everything in here, we're going to have to re program every single one of these little steps every single sort of Lupin here that contacts this central server. We cannot hot swap the server out. We have to re program our entire app. Every single component has multiple areas that we would have to basically re program to get working correctly again. So in this alone we would have to maybe road program three or four different endpoints, and then when they come in here and go out, the other side would have to re program that how this data receives, how that data receives it could get very, very complex. And you get to a point where you look at the software and you go, there's no way we can change this out, either. We're gonna have to stay with an insecure software or just going to have to destroy it and start completely over or abandon the software and basically just don't support it anymore. That happens a decent amount as well. So architecture, very, very important. We're gonna go over some ways that you can sort of come up with the idea about the architecture and sort of refined that down. So you have at least a good understanding about this stuff. 12. 3-2 Architecture Overview and Example: Let's begin our discussion on architecture with the reason that we want to cover it. And thats software architecture. How does architecture apply to the software development process? We'll software Architecture is all about breaking up larger systems into smaller, focused systems. This gives us a lot of different benefits, not only to reduce costs, but you help make it easy to develop to help make it so. Our engineers aren't standing by idly waiting for other people, people and so many other different things. So the some couple key aspects here is that good architecture is hard. It's not something that's easy that we can all do. And that's why a lot of people avoid doing this part because it takes some some thinking, some creativity to come up with good architecture. And a lot of people just want to get in there and start coding so they don't even think about the architecture. And when you do that, you build something that's known a spaghetti code where you start building one file and then you build another file and you're like, Wait, that needs a link there. So then we have another file and, like, oh, that needs to link there too. But it also needs to link up to this file. And slowly you start getting this web, this spaghetti web of code going together and instead of having this nice, you know, maybe organized architecture where maybe everything contacts a central server or there's ah , constants page that has everything. So if we want to change something, we only have to change it. One place. You start getting this really strange web of of calls and things like that and becomes very hard to trace down problems because maybe the problem starts here, and it calls the wrong function here, which then makes it break an aspect here, which makes it go back in the here and call another wrong function, go up to here and then over here. So this is where we think the bug is. And now we have to back trace it through all of these calls to figure out that Oh, no, It was actually a line of code Over here. We're over here. We have less of those connections, and maybe the break is up here. Or maybe the brake is down here and it just manifests Here we can do a quick backwards look and we see it's right here. Now, of course, those air just like very hypothetical things. But that does happen. A lot is that if we have a very clean architecture, breaks are easy to find. Good architecture also allows for faster development and smarter task allocation. This is important because it and then say it's the point that it's going to save us money over time. If we can break up our architecture into something like this, then we can say we're gonna have engineer one work on a task in here, an engineer to an engineer. 34 and five. We get five different task developing at once where if we just have one giant file, or maybe even, like just two giant files that sort of communicate back and forth with each other, how we were going to get five engineers working on different tasks. Well, we could have them, you know, maybe all work on the same file at same time, but that would actually cause usually merge conflicts, which means, like I worked on code up here, he worked on code down here, but to get his code toe work down here. He or she had to go ahead and change something up here. So now I push my code, he pushes his code, and suddenly there's this big conflict. I'm changing code. He changing code, and we actually have to come together and go line by line to fix it. It's a very painful process. So in that situation, what a lot of times happens is if we both need to work on the same code, you just have to wait. So, you know, Engineer One completes his task, engineered to completes his task. And now engineer three can finally jump in there and start completing her task. So it's something that reduces the overall idle time. If we get good architecture and allows the company also decide where to buy and where to build. If we have something like this and were like, we only have maybe four engineers, well, maybe there's a good solution out there, and we don't need to spend all the time developing it So and said, we just say OK, we'll work on these and we'll just go ahead and purchase something that fits that. Maybe it's like a form or something. There's many, many great form things online form little projects that we could buy and integrate into our software that allows us toe shoes the buyer build. And then overall, we always need to remember that architecture mistakes are almost impossible to fix once coding has begun. Once we begin, it is impossible to sort of take this and make it that and whatever I say impossible. I don't mean it's like, just not possible. There's no way you could ever do it. What I mean is that it would cost Maurin both time and money to fix this, that it would be to build a new product like this. So, for example, if we had an existing product right here to make it like this, we would have to spend more money than it would take to just start over to delete everything and just begin from new. And that's what I mean when I say impossible affixes that cost despair Insee between the two. So let's go over like a little example here, something that we can sort of just have an idea about. Let's say that we're creating a website, and so we start with this bad architecture at first. So we have a single web page that has maybe 1000 lines of code in it. Or for this example, it's him. It has 10,000 lines of code in it. If I tasked you with finding a certain element in here, how easy do you think it would be? How many different calls do you think? Where you'd have to go from here, down to here, Over to here. Do you think would happen whenever you go to a 10,000 line document? And this is a small website? I mean, they're their websites that have 100,000 lines of code. Imagine they're all on a single one. How would you break it up so that I don't know, maybe 15 engineers can work on this. Think about that. Let's say that the next step of this is okay. We don't want our entire Web site on a single page, So instead, we're gonna be like what? We need A let's say, a front end. So we have the front end, and then we need a back in. So now we create to folk files. We have the front and the back, and they communicate with one another getting a little bit better. Now we can actually put a back in engineer over here, a front and engineer. And if we have, for example, a button shows up as the wrong color, we know maybe we're gonna look at this folder instead of this folder. You know, this one's got maybe 5000 lines or in this situation, 50,000 lines. And this one has 50,000 lines. Makes it just a little bit easier to find out. We don't have to go through 50,000 lines of things that just don't even matter. We have only front and stuff. And then now we can start breaking it up and do instead of just front end. Maybe we have the Web pages broken up, So we have a main web page here. We have maybe the log in page over here, and then we have the form over here. And maybe the form is on Lee Ah, 100 lines. And then the main page is, you know, maybe 49,000 lines and then the log in page is something like, you know, maybe 900 lines. So it's still those 50,000 lines, but we have and then we'll just keep the end over. Here are the back end. Yeah, that should have been back and not just end eso front end back end. So we have the back end over here that's still communicating. But now we have a little bit better of an idea about how it's communicating with things. Now we have this broken up just a little bit more. So we have the ability that if we say the button color is wrong, we can go into the file more like, Well, it's on the form page. Let's go check out the form page. We read through the 100 lines up right there, make the change. So you see, as we break it up mawr and more and more, we start to be able to maintain this project a little bit more, and we start to be able to basically create a better product that we can expand over in the future. So now we have just sort of this very, very general idea of what we're doing with architecture. By breaking things up, let's start going over a couple of their they called patterns or models different ways that you can take your project and break it up and some of the sort of tried and true methods of doing this. 13. 3-3 Pipe and Filter Pattern: Let's go over our first architectural pattern. So the architectural patterns there's never really a one size fits all approach, meaning we can't look at a pattern and develop every single piece of software with that pattern. So with these patterns, what we're kind of creating here is we're creating a toolbox that we can build off of. So if we understand, maybe five or six popular patterns whenever we get to a problem will understand how exactly we should go about it, or at least a general direction of where we should go. And then for that specific problem. We can actually develop a architecture for it. So don't think that you could just apply these patterns, you know completely and totally toe a project. These are again. They're sort of ideas, their ways that things could be done. And you could think of a problem. Be like, Oh, yeah, I'm going to use a pipe and filter and then a client server and then, you know, sort of link it together with my own architecture. So just with that little disclaimer, let's get started on this. The 1st 1 like I said, is the pipe and filter pattern the pipes are the connections of data. And the filters are things like these. Like divisible by 10. Even odd. So, for example, if we had a little data set right here, if we have, like, a little data set of 357 we could send it to our first filter, our second filter. And then maybe that's the output. So these right here are the pipes. So this right here is the pipe, and these right here are the filters. Now, there's an important aspect that we have to go over. There's something very important with these pipes and filters. The input must match the output. And what I mean by this is I don't mean that, you know, 357 has to go in every filter, and then 357 has to come out. What I mean is that the same type of input needs to come out from each one of these so that we can make thes completely and totally sort of intermix herbal weaken. Take this and put this one here. We can take this and put this one here. We can add five more. We could only do one. That's the important part. So, for example, if we have 357 and it goes into one, that's for example, Times 10 it's gonna come out with an example of 30 50 70. And then that's going to go into the next filter. Have you noticed it's the exact same thing? It's just another number set, maybe for this one instead of times. Ted, we say Onley want maybe Let's put another number here so this works. We only want odd. So this comes out and now it's gonna be 357 and that's gonna go in the next one. The size change. That's perfectly fine. But the type stayed the same. They are still just number sense, and again, I'm gonna keep driving this home. That's the pipe and filter is all about. You take in a certain type, you put it through a filter and you get a certain type back out the other end. And then with the pipe and filter, we can also apply actions. And what those are is they just take the data and they do something with them, and then they return the exact same data. So, for example, said the boss, maybe we have the 357 We put it in. Judy, send the Boss, so he put it into the boss. It's going to take that it's gonna send it to him. But what? What is it? Output will outputs the number sequence again. 357 so we could send it to the boss, multiply it by 10 and then send it to the clients or something like that. So inaction is perfectly fine as a filter, as it will do something. It'll take the data. Maybe it'll send it to a server. Maybe it'll do a calculation and set another variable. But the important part is the output must be the exact of the input if it's in. If it's an action, I mean you could change in the action to and have it come out differently, but there needs to be an output that we can work with. So let's go over a couple little examples here and how you might use this. Let's say that you have a an investment company and you are working with, you know, stocks that went up and down. So you have this list of profits and losses on your stock so maybe the 1st 1 Maybe they're all in dollars. You have the 1st 1 is a positive 10 and then maybe a negative 30 and then maybe a positive 11 and then negative 15. Let's say that these are just the numbers that you're working with. So now what we can do is we can actually sort of build a model to help us with this. So we want to take anything that is greater than zero. So we're gonna take the greater than 01 right here. And then we want to send that to the clients. We want to show the clients that we're doing great, that we're doing really good stuff here. So anything greater than zero we're going to send to the clients and then anything less than zero we're going to send to the boss like So? So we're gonna grab this, we're gonna send it to the boss. And now what we're gonna dio is we actually take this data and we put it in. So if we put this data in here, it's gonna go greater than zero. And what's gonna come out is only the 10 and the 11 that's gonna be passed in the Senate clients. Those are going to be sent to the clients, and then it's gonna pass an output. There's nothing left, what stops right there, and then we also pass it into less than zero. And then we send that to the boss, like so and then that's all that's going to be. Here is negative 30 and then negative 15. So the clients are getting what's going good, and our boss is getting what's going bad. So maybe he can help rectify the situation. And a lot of times, pipe and filters will do this. We'll have this architecture where you go out and you sort of break into these separate things and maybe even the data comes back together, and it keeps working. Maybe these all start their own little chains or something like that. But the pipe and filter just allows us to take the same data and throw it in any way that we want. For example, again, just for clarity's sake. This will make a little less since, but let's say, instead of sending the clients for some reason, we only want to send clients odd numbers. So we take the center clients and we move it over here and then we go up here and we say we only want to use odd numbers. And again, this is a weird example, but this works perfectly fine. The code works because there's little store little black boxes. As long his numbers come in, it doesn't matter how you set this up. So now it's gonna grab all the numbers greater than zero is going to then only take the odds. So that means that we're only going to be left with 10 right here, and then it's gonna send those to the clients. And again, you can mix these up in any way, shape or form. But that is over all the pipe and filter approach. A member of the key points here are that the input must match the output. So if you have a set of numbers and needs to come out as a set of numbers, if you have a set of strings that needed to come out as a set of strings or any way that that would work with the same sort of types here and then also, uh, even if you use an action, you need to also output that action as well. Everything needs to be customizable where you can drag and drop them in any order that you want, and they'll work out perfectly fine with that order. 14. 3-4 Client-Server Pattern: So now let's talk about the client server pattern. This is also sometimes refer to again as the client server model. But the client server pattern is a pattern that we have all used before, and a lot of you might look at this and be like, Wait, that's a pattern. That's something we can learn about that just sounded like common knowledge. But yes, it's a pattern. It's a way that things are set up. So with the client server pattern, what we have is we have a central server. So, for example, will have let's keep with a color scheme of this little image on the right here. So we have a server right here, and then we have clients that contact the server for information, so we have little clients here and there. So let's again, let's go with the color scheme here. So we have clients client client client, and they all asked the server for information. The server then distributes that information back to so weaken back to the clients, so requests come in and the server distributes the requests back out, and this is how basically the entirety of the Internet works. If you go to facebook dot com. You contact the Facebook server. So this, for example, could be Facebook. You contact the Facebook server, you ask it for a whole bunch of information, and it gives you every single piece of information it gives you. For example, the newest updates on your timeline. It gives you the HTML so that you can load the Web page. It gives you all of the images, tells you where everything is at, and it actually sends you that data. And every time you update a page every time you go to a new page, a new request is sent to the server and a new response comes back from the server. And so what? This why this is a pattern is it's because it's a way that we can all connect to a central piece of data or a central hub of information. Let's say that Ah, away a good way to sort of explain this is on a game server. If, for example, you're playing a online games like call of duty or players Unknown battle grounds or fortnight, all of those games you are all playing on the exact same time on the same server, and this is where a lot of people understand. They've heard the words server before. So you have all of these people and they're all playing the game at the exact same time. Now, what the server is doing is it's calculating everything. It's taking an information, so it's taking in every maybe second, or maybe even every 10 times a second. I don't know how many times it updates the server. Your client. Your computer is sending the server your location, how faster moving, what items you have. And the server is updating its little data log with all of that stuff. It didn't takes that data, and it sends it to each of the clients every X number of milliseconds or seconds. In this way, when you're playing your game, if someone walks into. So, for example, let's say this is the map in the game. You're right here. If someone walks into your vision, you get a message that tells your computer where his locations at this helps, because this now allows your computer to render or to show that other person in real time so you request it sends you request it sends and there's 100 or 200 people doing it this at the exact same time. And that's what builds the map and allows everyone to run around. Now if you ever have server lag, if there's ever a lag in game, that's because this is taking too long. You asked for data, and then by the time the data gets back to you, that person has already moved really far forward. So now your computer tries to display them here. And then it gets another message that no, the person's actually way up here, so they lag across the screen, and that is a common downfall of your servers. To slow is that the clients can't get the information. But the client server pattern is a pretty simple pattern that again we all use. It just has a central server, and you have a whole bunch of clients that all have maybe client software that contacts the server, which usually has server software. So there's usually two types. You have the server software, and then down here you have the client software on each of these, Clement's request data and in the data is sent back 15. 3-5 Master-Slave Pattern: Our next pattern that we want to talk about is something known as the master slave pattern . So as the description sort of goes, there are two elements to this. Both the master, which is usually represented at the top of sort of a hierarchy and then beneath it, a whole bunch of slaves. So we have in this situation will just create three different slaves here, So there could be there could be three. There could be six. There could be 1000 different slaves. It doesn't really matter what this all that matters is that this this sort of way of controlling is uni directional, Which means that let's say that this color right here is the commands. The commands on Lee go downwards. So the master always tells the slaves what to dio The slaves never, actually, sort of. They don't control the master. They don't tell it that way. It should do something. An example of this is for, um with database replication. Let's said this is our main database on our main database contacts. Let's say our server, so are our server contacts. A database vice versa, and then our server delivers the data out onto the web. So with the master, it's always the one that's going to be the most up to date. It's gonna be bringing in data updating data, sending out data now with the slaves The slaves need to duplicate the data from the master . So the master tells it may be at midnight or 3 a.m. to update. So it'll send a command down to s one slave one here that says slave one. Begin copying my data to your data. And so it'll take it. It'll grab all of the new changes, and it will update itself. And then slave one will go quiet. It won't do anything until it's commanded again by the master. Uh, USB drives or peripherals also uses. So let's say that we have a computer right here and we have, you know, the central CPU and then the ram and etcetera, etcetera, etcetera. But what we have is we plug in a USB drive here. The USB drive is acting as a slave. It doesn't tell the process or what to dio the processor. In this situation, we have the processor rate here, never listens to this USB drive. It doesn't listen for, you know, it's commands or anything. The processor contacts the USB drive and tells it, OK, do whatever task we of science. Let's say we're copying data off it. It says, Okay, take your data and offload it, too, are hard drive. So the USB drive off loaded to the hard drive, and then the processor keeps doing its other tasks. And anytime we need to actually contact the USB drive, it does exactly that. It contacts it, and then the U. S. B. Drive does whatever it tells it. USB Drive is never trying to control anything else unless it becomes a virus. In that case, the master slave sort of breaks down. But in this situation with a normal USB drive, the USB drive is a slave in this situation. And so this. You know, we were talking about hardware here, but with software, we can do that as well. Typically, we do this with something called a controller. So the controller is always the one that's going to be contacting all of the little pieces and telling them what to dio. So with this sort of architecture, we don't have communication between our little pieces like that that never happens. So with a controller and a master slave pattern, what we have is this controller that gives orders out. So the controller gives the orders. Then we have messages that come back up so the messages come back up. And then if data needs to be put into these other ones than the comptroller does that itself. So basically it's a way of sort of isolating each unit here, each module, completely isolating it from one another so that we can either a weaken, swap them out. We could tag them out or swap them out and be it allows it so that we don't have this crisscross communication here, where it's very hard to track down information flow. We know that if there's bad information coming into here, it must be coming from the controller. The controller must have an error, or there must be a chain, and it allows us to sort of backtracked. That changes a little bit better instead of having like this looks a little complicated, But imagine if he's communicated. You know, like this where there's just communications over here and here than this one comes down here. It's impossible to track. So what we like a lot of times is toe have this controller. So the master slave is a very important pattern. It's used quite a lot, and one of people don't even realize they're using this pattern. But it's very good to tackle Ah, whole bunch of different problems. 16. 3-6 Layered Pattern: Our next pattern is the layered pattern. So the layered pattern is basically just that it's a bunch of different layers and this soft for Rome. What that means is that we have these layers of technology, so the layers of technology only communicate within their own layers. So, for example, this is a layer, and this is a layer, and this is a layer. So what we don't have is we don't have cross communication. We don't have these trying to call information from there like that. What we have is we have the ability to communicate back and forth on the ability to communicate back and forth like so. And then these Onley call within their respective layers so you can see that maybe a slight disadvantage is if you have something here, it might have to trickle up to another layer. You might have to go through a couple of extra files, right? A little extra code. What it does is it classifies out the data so that if we're looking for let's say that, uh, you know, we have This is our front end. This is our back end, and this is the connection between the two. If we have a back in problem, we know we're looking at, you know, the program within this layer. And so this is still pretty abstract, so it's actually go through a little bit of an example right here. Example I want to go over is a very popular, layered pattern, and you might call this one a model because it's an actual thing you can implement. So it's called the model view controller. So, for example, we will put the controller right here and on the right side we will put the view and the left side. We'll put the model so the model view controller breaks up the three different aspects here on the right side. Like I said, we have the view. The view is what shown to the user. The view is what we can click on, what we can interact with. So in this situation, let's say that we have a profile page, so you know there's the profile picture, and then we have a little form here to update the profile. So we have ah, box a box and then the ability to actually submit that box. And maybe we're changing the name here. So this is what we're going to be trying to change the name and the email now with the model view controller. What we have on the left side is the model. So this is the database. This is our database that has the user here. So it's gonna have the line for the user and then his name and email address. So we have the user name and then email address right there. And, you know, it has a whole bunch of these. A whole bunch of user name email, user name, email, etcetera, etcetera. This is the model. This is the actual entity itself. So on the left side, we have the model, the entity. A lot of times, it's the database where the the the sort of the data is actually stored. Now, we don't wanna have Is this cross communication this ability for the view to talk to the model? So what we do is we create something in the middle called the controller. So in the middle, what we have is we have the controller and the controller handles all across communication . So the model will contact controller and the Cullen Troller will contact the view and then vice versa. The view contacts a controller and the controller contacts the model. So, for example, we clicked the submit button here. The data that we updated is going to go to the controller. The controller isn't going to have some function like maybe it's gonna be a function called update user. And then with that function, it's then going to call down to the model. The model is in going to grab all that information that was put in here and it's going to update the user. What does this do? What does this help us accomplish? Well, it helps us figure out where problems are. We have this data base layer on the left, and we have this controller layer in the middle. And then we have this view layer on the right. So now we are able to figure out problems. We have the front end. This is the Java script in the HTML. So, uh, the sort of the view of things. And if something is messed up over here, we just look at the HTML. We look at the website itself. If we have a problem with data that's being inputted here, and it's not making it to the model. What we know there's a problem with the controller. So we look in the controller class. We look at the main thing that is actually controlling both of these sides, and then if the database is messed up, if we have that is coming in, we know the controller is doing right. But some, for some reason the model isn't updating properly. What we know to go look at the data bases to look at the my SQL, the the different sort of ways of the databases storing things. It allows us this layer. It allows us this ability to classify and also build different elements. We can have front and developers here we could have middle end developers. Here. We get back in developers here. Usually these two classes are covered by back in developers, but you can also have a little bit of overlap where the the front end developers know a little bit here as well. Overall, though, the layered pattern is used quite a lot to classify our programs, to break them apart so that they could be easily maintained so that there isn't a whole bunch of spaghetti code and so that it makes sense to everyone involved 17. 3-7 Software Engineering Pattern: so do out all this. We're trying to sort of create the software architecture process, the process by which we can come up with an architecture for a problem for a program we're trying to design. Now, this is a pretty difficult task and that were very far into the creative world here. What I mean by that is there isn't going to be a laid out x y Z First step second step. Third step to this process, we're going to have to be creative. We're going to think about our problem. We're going to think about other problems that have been completed, and they sort of grab from that and designed a unique solution for what we're trying to do . So in that sense, instead of having a process a 123 we sort of have a list of objectives that we're trying to accomplish with our architecture, and this could get as in depth or as high level as we want so we can make this very un in depth. And by that I mean, it's sort of just a general blueprint. We can get very in depth about how exactly each piece of data is going to be communicated. Usually with larger projects and larger corporations. You're going to get Maurin depth and with sort of faster moving corporations or faster moving Navy startups. We don't spend as much time in here, which is trying to get the product out there. And then we sort of decide those things later, which could be, Ah, be very costly. Or it could work for your project, depending on how it's all set up. But anyway, what we're trying to do is we're trying to control how a program is decomposed and how it interacts with itself and the outside world. This is important the outside world as well. So we're trying to figure out how the program is going to do. It's all little connections. And also how does it communicate with the users? How does it communicate with other software systems? How does it do that as well? And we're trying to figure out how does it basically incorporate itself into the world? And then how do we build that as well? How do we structure that so that it works properly and we're also trying to model how the control or we're trying to model the control structure of the system and how it will behave . The control structure is sort of all those patterns we've been doing. Are we gonna have a control structure, Which is sort of like, you know, maybe this or we're gonna have Maybe that slave that master slave one where we have something like this Are we gonna have the pipe in filter control structure where we're gonna keep putting data in and then filtering it down a line? Or maybe maybe we're gonna have something like this where we kind of have these subsystems all put together. We're gonna have a pipe in filter coming in. It's gonna go to a master slave. The master slaves isn't gonna go to sort of like a model view controller, etcetera, etcetera. So we're kind of taking all of this and we're trying to combine it into a way that work for our solution. And like I said, there is no clear cut. Problems are solution. We could have a team of engineers. Another team of engineers and another team of engineers all try to come up with the best architecture for our project. And they're all going to be completely different. Some of them may be completely, completely different. Like maybe these guys think what we should use a pipe and filter. These guys are like, No, no, no, the master slave. Plus this and this models how we do it. These guys have a completely different way of doing it, and that is the importance of basically architecture. Is that it? Sort of something that we have to design by ourselves. We have to figure it out. It's a creative process, which is why a lot of people skip it. It's hard. It's very difficult to design. Well, the next step that we have to do is we have to break the project in the subsystems and modules. If you can just do this step, you're in a pretty good situation for your architecture. So what I mean by this is that we have the two things the subsist, Um, and the module and the subsystem is an independent system which holds independent value. And what I mean by this is that you could take this system and you could plug it into another program and it would work properly. Or you could even sell this system. Someone might actually want to buy the system because it has some sort of independent value . Ah, module, however, is a component of a subsystem which cannot function as a standalone or if it functions as a stand alone. It's very inconsequential. There's nothing it really does that's revolutionary. So let's say that we have, for example, a little module that divides by 10 then adds 30 and then multiplies by 62 some weird little module down here. And the reason I'm using module is cause. Think about this. This is a is a piece of information. We can now passed out into this and pass it out and it gets a new number. It's it's got some importance for us, and we can combine it and maybe an important way. But do you think anyone would buy this? It's very specific, and it also doesn't really accomplish a task by itself. There's no task that we have. Maybe it accomplishes a very small task in a large system of tasks, but by itself it has no independent value. Now let's say that we have a whole bunch of these little math equation modules, so we have a little one here one here, one here, one. Here we have all these little modules working, and now they're all crisscross communication, whatever the structure is of this subsystem. And we have now this subsystem built and let's say this subsystem calculates maybe our taxes. So this subsystem is now good enough that with all of these little math equation So these are all you know, like times 10 you know, minus 62. And maybe this calculates our home mortgage insurance, etcetera. You know, all those crazy little equations all going together here, And then it finally outputs how much you owe in tax. So it inputs your maybe your income, maybe you your income or something, and then outputs how much you owe in tax. That's an important module. That's something we could actually use. That's something that we could sell to someone that they maybe don't want to spend the time developing. This has a business value. It has an independent value. It's made up of a whole bunch of components that have no value by themselves. I mean, we the calculating, you know, your home mortgage might maybe has a little bit of value, but when you put it in this giant context, we get to the ability that we can actually, you know, get to a point of selling it. And let's say that this is just our personal taxes. Over here we have the exact same thing. We have a whole bunch of little modules in here and you import it out. And now you have maybe business tax. And so you import business, taxi out port business acts and then now and it's gonna get a little sloppy here, but I just kind of want to drive this point home now. What we have is we actually have sort of this subsystem of subsystems. So in this case, we have almost our entire software. Or maybe our software is like a entire personal finance thing, so there could be other ones as well. But we have this other system that we could sell to people as well. So this could be an entire subsystem, and each of these could be maybe more subsystems again. You can design this anyway that you want, but just sort of trying to drive the point home modules component of a subsystem which cannot function of stand alone. So if there are these little equations or one offs that can't really be sold, then it's probably going to be a module. And then also what we have is we have the subsystem, which is at that module when they're all put together and sold. And even with just this little bit of thought and planning, we now have a way that we could sort of maybe even divvy up. Howard teams work. We're gonna have a team work on the business side. We're gonna teamwork on the personal tax side. We're gonna have maybe a teamwork here, a team work on this one, a team work on this one. Maybe a team will work on this section and a team will work on that section and you can see we're already getting the ability to divvy out the task and become more efficient. And finally, with the software architecture process, we have to keep a whole bunch of things in mind. And you could see this list is really, really, really hard. It's actually from Wikipedia, this website, if you don't put that in to take a look at what these links go to, but they're all these sort of terms that we wanna we want to think about. Maybe we only want to think about five or six of these terms really, really in depth. But we do want to make sure that we're thinking about things like, you know, Is this dependable? The dependability of this architecture? How effective is it at solving our project? How durable is it? Maybe we'll it stand the test of time. Will it be broken with more data in it? Uh, maybe we want to look at the reproduce ability. Is it going to be easy to copy again to another problem? Maybe we tackled the same problem over and over and over again. So maybe we want to design a solution that can be reproduced multiple multiple times into different parts. The vulnerability. How secure is it? Is it going to be hackable? Is it going to be something that already has a known risk in it? Each one of these consort of pose some new questions that maybe lets us go back and refine our architecture a little bit as well. Next section, we're going to sort of jump into the next layer of architectures. So maybe we've we've designed just a little bit of how our project works and have a control . Full flow works and the next Now we're gonna start jumping into just a little bit of the design, going a little bit more in depth to sort of hashing out these modules and thes different parts and how they should interact except 18. 4-1 Software Design Process: our next step along the software engineering journey is going to be designed software design. So we've gone through requirements. We've done the requirements, the requirements naturally into the specifications, which are again are just sort of more of the technical requirements from the specifications . We then move down into architecture. We have sort of an idea with the requirements specifications. So we try to come up with a large game plan. How are these giant modules? How are they going to interact with each other? How the subsystems going to be divided. But through that, we haven't actually talked about things like, what code are we going to use? What actual software we're gonna use, what database software we're gonna use. And that is where this next step comes in, and that is gonna be design. So design is a step where we start applying our plan and idea to the real world solutions. So what I mean by Riel Rose Solutions is we start coming up with how do we take our architecture, our overall plan and how do we design it? How do we come up with different solutions to create that architecture? So if our architecture for example, called for a back and server. So we'll do like a server sort of symbol there. And then we have in front of that we have maybe some sort of controller class and then maybe a web page. Maybe that's how our thing is. We're doing like, a model view controller sort of thing. So what technologies are we gonna use? What's are back in gonna be Is it going to be running on a Maybe Lennox based operating system? And from that is our server going to be running some database? Maybe something like my SQL is What's our middle gonna be? Is it gonna be Ah, Is it gonna be the JavaScript? Is it gonna be maybe on the server itself, maybe something like PHP or which is sort of on both these, which is why it's usually a middle thing. It could be on the Web page, but it actually execute server command. So maybe it's a PHP controller class on our Web page is gonna be HTML. Is it gonna be a framework? Maybe we're using something like, if you've heard of it, WordPress, which is this sort of a framework? It's like a dragon drop front in creator or even, ah, company like Wicks. W I. X is a company where you can sort of drag and drop and design your solutions, but it kind of covers all of this as well. So maybe that's an idea. So you can see that we kind of come up with this overall plan of how we wanted to set things up, even if it's more complicated with, you know, Ah, whole bunch of boxes move in different ways and stuff, and now it's time to look into each one of these boxes and determine what is the real world solution that is going to solve that now again, just like in the requirements where we didn't want to overstep our bounds and accidentally walk into the design the design has a limitation to. We don't want to accidentally walk into the implementation, which is the next step down here. Design is not coding and coding is not designed, meaning we are not starting by building the framework out or anything like that. All we're trying to do is come up with what real world solutions exist. What do we need to create, what technology we're going to use to create that. And what sort of our game plan of doing that? That's design. Now, of course, you do a little exploratory coding here and there. See if an idea works be like, yeah, you know, these three lines of code here, they do do what I think. So we're gonna put that a design. There isn't, like, a strict limit here, But what we're saying is, don't jump straight into the coating from this step. That is not what design is. Um, design is purely coming up with a more detailed plan from the architecture. And also, whenever we talk about design, we also have to understand that it has sort of a dual meaning here. Design is both the activity and the product. So the activity is working to design a software as where you have a team of people and they are all actually actively working on, you know, coming up with how this software should interact. So people here, how these offer should interact. Now the product is also the design. It's the design document. And so it's a noun, meaning that it's the document itself. It's the final product, something that you could handle so on house and they'd understand how exactly your software works. So when we talk about designs, we can talk about, those two things were both designing the product, and we're creating a design for the product. Next step, we're gonna start going into the stages of design going into what questions we need to ask in what problems we need to solve. 19. 4-2 Stages of Design: let's go over a general set of stages of design for software. So why I am saying that, the General said, is that this is not a one size fits all solution. There could be another sort of set of design principles at company A Uses versus Company B . However, if this is your introduction to design, this is a good start, a good place to begin whenever you're thinking about design. So we have eight steps here, and these steps could be as detailed or un detailed as you want. Sort of. What you put in is what you get when you do something like this. If you spend more time here, you'll spend less time and implementation and coating. So it really depends on what you want to do. Because a lot of times you'll actually find bugs and architectural problems and design problems within the design here that you wouldn't find until you've already coated the thing until you've already spent, you know, 400 hours coating and then you realize you have to go back and redo something, so if you spend a lot of time here, you can a lot of times save a lot of time in the future. So our steps work like this first is we're gonna break the larger problem into smaller problems. If we're designing, for example, Amazon if we want. If we have this idea of this company called Amazon and we want to develop this website where it's gonna be an online e commerce and people can, you know, send their products to us and a bunch of companies and come in yada, yada, etcetera there's gonna be a lot of many problems within their This is one problem that's gonna have a ton of sort of overarching problems. And from those overarching problems, we're gonna have smaller problems and smaller and smaller until we get down to something that's a little bit more manageable. If we go with a slightly smaller example, though, for example, say the one with the working, which is creating a website, let's say one of our problems is the database the way to store our data in the back end. And so with that, that's our problem. That's gonna be the The big problem broke it down into a smaller problem, which is how do we do the database? What do we do to get the database going. So in this situation, we have now broken it down into a problem of database design. Now we need to understand each of these problems. So, for example, if we're doing this, we can do this one by one. Or we can break it into a whole bunch of little sub problems and then moved to step two. And then once we break it down any further, we could move to step three, etcetera. I'm just gonna go sort of aim or top down approach meeting we're gonna have one problem may be one of many problems, for example, And then we're going to just move down, step by step by step, over and over like that. So then we need that. Now, understand this problem? What's the purpose of this problem? Why do we have this problem? The requirements document might come in handy here because the requirements documents should be telling us what we're trying to solve. And so now we have a sort of a way that we could go back and look, maybe requirements. Document says something like, we need to store user information. So if we need to store user info. Well, of course we need a database for that. Maybe it. We need to carry out transactions. If we want to do transactions, we're gonna need a database for that. And we can sort of list all of the different parts of this problem user info, transactions, images, etcetera to fit our problem. And once we understand all that, we now have an idea about what database we need to design. So now we need to identify potential solutions. What solutions are there out there to help us? There is something called AWS Amazon Web services. We have we could build. Our own servers are maybe our own server. We could purchase server space on another country company so we could purchase it somewhere . We kid build our own, but then send it to a purchase place. We could use different technologies like a my SQL database. A regular rescued out of place, maybe a no SQL database. Are all these different options And this is where we need to really open up our minds and come up with as many solutions to the problem as possible. We don't want to come in with a sort of mindset of Okay, We're gonna be working with AWS, and it's gonna be this this and that without any reason for it. Maybe the company says maybe like the design company or the client says we must use eight of us. That's fine. That's a requirement that something that constraint, we don't have a choice over that. In that case, that's going to go in our design documents, just eight of us. But if we don't have that constraint, if we have the possibility of coming up with different solutions, then we need to find this mini solution as possible so that we make sure we choose the best one. Because if we're just tunnel vision ourselves and don't focus or ah, focus too much, we're gonna have a problem where a better solution might have been available. The next step is to describe solution abstractions. So what are solution? Abstraction? Solution? Abstractions are things like design documents that aren't technical. So it says we have a model X here that contacts, model, why and what this control flow. It goes back to maybe model W. And that contacts this. It's sort of this this way of using graphs and models sort of like this right here to come up with an overall plan for our software. So this is an abstraction. This is how we were going to set up our database so you can see that we have ah users column a main posts or users table main post employees post, admin post. And then all of these and they all connect in these ways. Now, this is a little bit farther on the technical side than maybe some abstractions might go, but that's fine. We have you know, instead of, you know, putting all of these down here, we could just come up with the table names. That would be a good abstraction so that we can describe how we're going to store the data . But you can see what This table right here. We have a very good idea about how the database is going to work. So we sort of chose him. We're gonna use the my SQL database in this situation, and the next step is the sort of abstractions is coming up with these models. Maybe this is how the controller works. And that graph I just showed you that graph is maybe this module right here. And then maybe down here is the, um maybe how data is gonna come in and out the organizational things, and so we can sort of break that up into further ones. And basically, what we do is we repeat this process over and over and over again until we go with all of those problems. Memorize said we had, like we had. Maybe these problems that broke down into these problems, etcetera. So we're gonna try to abstract everything out until we get to basically finished. Until we have this really, really top down sort of level about all the different components and ideas about how everything works together until those abstractions are done. Then once we do all of that, once all of those abstractions are sort of figured out here. We're going to then move on to the next steps here. So a lot of times we want a loop up here until we figure out everything and then we can move on to the next step and the next steps a little bit more advanced. Next up. A lot of people skip just because it's kind of difficult to do and you need to have the experience to do it, but that is gonna be to actually basically code the thing without coating the thing. Remember, we said design is not code. It's not code that's important. However, it doesn't mean we can't determine how everything's going to interact. So what I'm saying with this step is we're actually going to create the components like like this, and then with each of these components were gonna come up with maybe it's going to use this class and this class is gonna have this method, this method, this method. You know, this method talks to hear this method talks. To hear this method talks to here and then we're gonna look even farther. What's this method transferring? Maybe it's transferring in array. And how are we sorting that array? Maybe we're using an algorithm called T sort. Maybe we're using an algorithm called Merge Sort. So then we get into, like, really, really nitty gritty details of this. We start going piece by piece and coming up with this giant sort of class tree, which could be really, really, really large if you plan the whole thing out. But in the end, we actually have this big document where everyone can go and look at it and understand how the program works without ever spinning up a server or development. They just see all the code there, this process. It's important. But I will. I'll sort of profess it with this, and we're going to talk about this later on. In the course. It's very, very tedious. And there's a whole bunch of overhead and most the time. Once you design this, things change and then it isn't updated, so it becomes out of date and basically useless. So even though these are quote unquote important steps in the design process, newer models nowadays actually sort of forego this for developing quicker, faster solutions. On, we sort of throw away the documentation just a little bit because we don't need books. We don't need books about documentation of our software stacked high and then not actually have software that we can show for it. We just have this really, really good design, so there's a balance there, and this is where we start talking about the agile methodology later on, but just sort of want to throw that in. There is if you're just going to this course, you know, lecture by lecture. Don't think that you need to do this 100% because a lot of times isn't realistic, and people sort of just throw it out. However, understanding maybe the core principles helps you when you get to that other part, cause now you understand what you're giving up to get that speed, etcetera. But that is the stages of design. Like I said, these change all the time. Your company might have another set, but this is a good set to sort of take it from that idea level and really start breaking it down into getting a good idea almost on a code level about how your program should work. 20. 4-3 Modularity: So we talk about good software design. What we're trying to get to is this idea of modularity. So modularity is this idea of taking our program and breaking it apart into different modules. Remember, we talked about subsystems and modules. It's the same terminology here, but with modularity, we have a set of goals in mind. We don't just want to break it up willy nilly. We want to break it up in a smart way. And with this what we're trying to do is to main goals. So with our module, let's say we have a piece of code right here with our module. We want this module to be independent, and that is the coupling part. Independent means that all of its actions and data on Lee effect itself. We don't have a module over here controlling it at a module over here controlling it. And then maybe it's controlling a module over here. And this one's controlling that, etcetera, etcetera. Then you get into this really big problem of an error here, might actually represent itself up here. Or actually, it could go and represent itself all the way over here. You get a problem when they're not independent, so that's one of our goals. And that's what coupling is. We'll have a whole lecture on that. And then cohesion is how singular does a module sort of exist? Like what I mean by singular is, is it are its goals singularly designed? If the goals air singularly designed weaken, take that module, we can remove it from the program and put it in another program. If we had a Web page and this Web page had this controller in it, and this controller controlled everything, I mean, it's talking to a whole bunch of other controllers. So maybe maybe it's got actually pretty good coupling in the sense that even though it's controlling all of these, nothing controls it, and its data is very sort of encapsulated within itself. But the problem here is that it's very, very fine tuned to exactly this problem, meaning that if we ever try to take this out or put a new piece in, it wouldn't work. This is very, very specific to this exact problem, so it doesn't meet a singular design goal. It's doing everything. There is no goal. I mean, you could, you know, say control website. That could be your goal, but that's a very broad goal, and it's not something that's very singularly designed, and that's what we talk about cohesion. So with modularity, we're trying to get those two aspects. We're trying to get them both as optimal is possible. We're trying make it very independent and then very singularly designed. So the goals of modularity, the goals of modularity are as follows. There's a different set. Me, if you look up the goals, is gonna be different sets. For any people who talk about this, however, this is a set that I like to go off of. The first and foremost goal of modularity is abstraction. It's basically taking our module and putting into a black box to remove complexity. We're talking about that in information, hiding in a little bit, but abstraction is very important because it allows us to design a higher level ideas. If we had to, for example, work on machine language, which means we're actually, you know, controlling ones and zeros all the time. We wouldn't want to get anything done. It would be too complex, but someone has abstracted that out to an assembly language, so this is assembly, and then someone has actually abstracted that assembly language up to probably another one and then up to our language, like Java so we can use Java with its. It's relatively easy to use functions it, then decompress it down into whatever this language that goes to the assembly language that goes to machine language. Machine language actually controls the ram etcetera. So when we're talking abstraction, we're talking the ability to take these complex ideas and slowly bring them out on remove that complex city so we can build more and more advanced programs, decompose ability in compose ability. It means we can take the thing apart and put it back together. This helps with debugging. This helps with adding new features. This helps with basically, anything that has to do with maintenance is we want to be able to open this program up, take parts of take everything apart and then put it back together again. And that really helps when you have both of these. And line is because you can take this controller out and it doesn't break the entire website. You can actually, you know, sort of hot swap a new controller and maybe one that does stuff slightly differently more efficiently. It becomes very easy to maintain after that module, understand ability or just understand ability if you want to keep them all. Is one word here. What understand ability means is that I could jump into a module and instantly understand what it's talking about with this one. It's very, very in depth. This might be maybe, let's say, 35,000 lines of code. Do you think you'd be able to understand what this module is doing right off the bat? Probably not. But let's say we have this small module over here, and all it does is do maybe updates on the database. So all it does is update database, and maybe that's its name. And there's, you know, functions like update, integer, update, string up the user update password. We look into it. We say there's a problem with updates within our database. We easily can go well, let's check the update, database, folder or the file, and it's very easy. Very quick to understand. The next one is continuity. Continuity is a little bit of an idea where you have, let's say you're using Constance Constance is of a very good way of putting this. We have X equals three. So instead of having in each one of these aspects, a variable of X equals three X equals three X equals three X equals three X equals three X equals three. Imagine if now, in our situation, X equals four. Well, now we have to go through each one of these and change them to four, which is gonna be or we were going to miss one and then we're gonna have weird errors start popping. It was gonna get hard to maintain. But if we had a constant folder, we had a constant file up here with that said, X equals four. Well, then all of these could just reference that Constance file and this is getting a little bit messy now. But I'm trying to, you know, bring home that point right there. Is that if we had that constant folder up there, then all we have to do is change it in one place, and it be continuous throughout our entire project. So having that in mind is very important as well and finally protect ability the the way that we can protect data is if we keep it very, very sort of unlock in specific files, we don't have, you know, 85 different files contact in the database. We have a single controller or a single set of controllers that do it. This not only helps us with unintended consequences, it also helps us against hacks and stuff. Because if we have 86 different entry points into our database, all that has to happen is one of them has to fail before someone jumps in. So getting that under control is very, very important. Um, and modularity helps you maintain and get a stronger security. So that's the introduction of modularity. In the next lectures, we're gonna be talking about information hiding and data encapsulation, which are other key tenants of modularity. 21. 4-4 Information Hiding and Data Encapsulation: So the next sort of steps of modularity or the next tenants of modularity, our information hiding end data encapsulation. And both of these are really just ways of abstraction and importance of abstraction. So the 1st 1 is information hiding, and that is, you hide the complexity in a black box. But when we're talking about abstraction and we're talking about how you can take it from machine language and bring it all the way up so we can do a higher level things, well, that's what information hiding does. It hides the complexity in a black box. Each one of these is a black box that hides the complexity. When you write stuff for assembly language, you're using things that this language down here, the machine language exposed some AP eyes. Some command some functions. You're using this code to build this, and then with assembly language, you create a new set of functions, controls and commands, which this next language will bring. Once his next languages done, you create another set of codes and commands, and then Java. On top of that will start calling those codes and demands which will call those codes and commands which because those which will do things like move memory around. So with this over here, what we're trying to do with information hiding is hide that complexity in a black box. We could do this with things called like functions macro library classes, method thes air, all just the technical terms that we use whenever we're programming. But let's say that we have a proper black box right here and another proper black box right here and what they are is an encryption device, encryption and then a decryption device. So if, for example, we put in 35 here and it comes out with I don't know, t why 62? So that's the output. And then now we take t why 62 put it in the decrypt er. And it comes out as 35. Do we need to understand how it's encrypting and decrypting to be able to use these two boxes to be able to use these two programs? No, not at all. All we need to know is, what is it? Input. And was it going output? And we are completely and totally fine with using it for all of its purposes. The internals are not needed to be known, and that's very important. That's that's something that's very helpful. Whenever we're designing programs, especially with let's say, we're designing a program for a let's, say, a car manufacturer. We have all this code that maybe self generates code in the background would say that it's , ah, self driving car something. But we're not car people. We don't understand what cars are supposed to be made like. We don't understand how it's all supposed to be programmed. So what we do is we program a set of buttons, a set of tables and switches and stuff on, sort of like a little control panel right here and with this programming. We then abstract out all of the nitty gritty of actual programming. The four loops, the while loop the functions of Macron's libraries classes. We abstract that all out, and we allow a technician to just press buttons and enter in values, and then our code will do the rest. So we have sort of given the automobile engineer Mawr control. We've given them the power to use our code with their stuff, and that's the importance of information hiding is it allows more and more complex things to be built. It allows you to sort of create a foundation and then build on that foundation and keep creating stronger and stronger things over time. And that's how programs are getting more complex over time is that we're slowly getting better at this abstraction and going more and more but information. I think it's the idea of hiding complexity in a black box. The next one is something called Data Encapsulation, and this you'll notice these are actually pretty close. This one is sort of information hiding, while this one could be known as data hiding, so they do have a relationship. But this one is all about hiding the implementation details from the user and Onley providing a set of tools to manipulate the data. What we mean by this is, let's say we have a class right here and one of its variables is, let's say, um, transaction data. So maybe the amount of money, so we put transaction here. Now, why would we need to put a get function and the set function? Why don't we just have what's in this class is named banking. Why don't we just allow Maybe this program over here to call something like banking dot transaction equals 50. Why don't we just allow that? Why? Why don't we allow this to make a direct call to transaction? Well, this sort of breaks the idea of data encapsulation. If we do this, then suddenly our data can be manipulated in any way, shape or form, and we don't have any control over it. We can't prevent the user from in putting invalid data and screwing up not only our algorithms, but maybe the entirety of our database. So, with data encapsulation, what we do is we create thes getters and centers. So if over here we want to know what the transaction is. It calls the git, so it would call the git, and then the get function would return the value This get function could be very important , because maybe it has a layer of authentication on it. Maybe it has a layer of authentication with that. That means that a password would need to be input before this class gives out data. And that's very important in the banking world. You don't just want people to be able to program things and grab directly off the server. Anything they want. So get her Helps protect in that. And then a center is a lot of times mawr important. The center will prevent us from doing certain things. So we'll call a function to set. Maybe we say we want to set the transaction to negative 50. Well, the center is gonna have a just a simple little if statement in here if you know less than zero return. So if less than zero return, I don't know, error something really, really simple. And this is a less than simple, less than zero return air. And why is this important? Well, we're doing transactions and we see keep charging people negative. $50. Well, we're gonna actually start getting money our way, and that's a problem. We don't ever want a transaction to go below any money because then instead of charging our account, we're actually just taking money from people. So a simple center would add another security layer there as well and would also protect the integrity of our banking in the sense that it can have more checks in here. And we couldn't deposit, say, a $1,000,000,000 by accident, either there might be an upper end that potentially escalates it to like a manager or something. But overall, the idea of data encapsulation is sort of protecting data, making it. So we we only expose this sort of set of tools to manipulate the data instead of just allowing data to be access and changed any way, shape or form that we want. And so, with with good software design, we think about that data encapsulation as well. We think about why. Why are we just letting people just grab this data? Why don't we make a getter in a center function? Why don't we protect it in some way, or create a whole class that deals with this sort of thing to protect the integrity of our database? 22. 4-5 Coupling Introduction: In the last lecture, we introduced this idea of coupling. And so with coupling, What we're talking about is the strength of connections between modules and sub systems. Now, with the term that strength, we kind of have this idea of a positive connotation. However, with coupling, we don't want this strength. We want an actual a weakness between models. We don't want models, modules and sub systems to be tightly coupled together. And so when we're talking about coupling, we mean almost like they're depending on each other. So, for example, if we had a whole bunch, a little set of modules and sub systems here, let's say there's just this this sort of link and chain, like so and, you know, as complex or or non complex your program is we might have a section that is tightly coupled together, and when a section is tightly coupled together, that means that if we make a change here, for example, we're going to then have to go to this file and make a change. Go to this file and they could change. Go to this file and make a change. Go to this file and they could change etcetera etcetera until we have basically everything changed so that it makes the change up here actually work. This has a a whole bunch of downsides. The 1st 1 is just time. It will take us time to figure out what exactly is coupled with this Usually do trial and air. We run the program, it says. Hope there was a break here. So we go change it there, run the program again. There was a break over here. Go change it there if you have better documentation, maybe a little bit quicker, But a lot of times you can. I got to go to that break and fix. The next part is, is that it's just going to take basically the ability to maintain the program and decrease it. Because now, when we make this change, maybe we made all of these changes. But we forgot about this case up here. And this case Onley operates, you know, maybe once a month, maybe it's some weird code that is like, ah, server thing that operates once a month, and we forget to change it in here. So we go through all the tests and stuff, and it's it's looking great and then in a month we have this giant bug that comes up. We don't know where it's from. Well, it's because you are tightly coupled together. It's because of this change that this happens. And it's even worse when we get to something like this where it's actually down here is where that problem is because now we have to think, What do we change? Maybe we only are looking at these two files or like we didn't really change much here. Oh, it was actually this major change up here that caused this cascading air so tightly coupled . Programs are generally bad. You're not going to really get to the point of no coupling, but you want to try to get it as loose as possible. So with tight coupling, we have the idea of shared variables and control information. So all of this over here is the idea of control information. So we have these methods and classes that are all talking directly to other modules are all controlling directly other modules, so changes in one will require changes in all the others. And then if we have the idea of shared variables, that's where we have this sort of giant list of variables, and each program on the bottom is using those variables. So if we make a change here, there's a lot of times we're gonna actually have to make changes in all of the bottom files as well. And this structure can actually be beneficial in some situations that can help reduced other areas of problems. But it might also create problem. That's why this whole idea of design we have this sort of balance that we have to draw. There's nothing that's going to be perfect. So we had to figure out what's the most perfect that we can get it. What's the most optimized we can get it, and that's the direction we have to head. And then state decentralization creates shall be one see their creates loose coupling. So what we mean by that is state decentralization is where we have sort of these little segments here. Maybe these two are coupled together, But then we have another section where these two are coupled together and, you know, etcetera, etcetera. But overall, we don't have the entire program being coupled together in, you know, every which way. We have almost these tiny little states all doing their own things with little communications in between happening. And that helps us again with the whole debugging and stuff like that later on. So in the next lecture, what we're actually talking about is we're gonna be talking about the three levels of coupling that's gonna be tight coupling, medium coupling and then loose coupling. And in there's little categories in each one of them content couple in common external control, data structure, data message and then none. And again, like I was saying earlier, none is pretty impractical. There's probably almost no applications that will use no coupling. But we want to be able to go through all of these steps so that we can look at a program and understand how, coupled to this program, how tightly knit is it and, you know, is that good or bad? 23. 4-6 Tight Coupling : Let's talk about our first sort of classifications of coupling, and that is going to be the sort of worst case scenario of coupling. And that is the idea of tight coupling. So a tight coupling we have a bunch of modules who are knit together. A tightly knit together with this means is that if we make a change in one module, we're going to have to make a change in a whole bunch of other modules to make it so the program doesn't break this could be it sort of broken up into these sort of sub categories , these air common tights, of types of tight coupling and that is going to be in content, common and then external. So we're gonna go sort of one by one duties and you'll see that they're very easy mistake to make. But they can cause very large problems. The 1st 1 is with content coupling. So what this is is it's when one module modifies over lies on the internal workings of another module. In this scenario, we have module A and then module B and module A is grabbing directly from Module B. It's grabbing the data rate out of Module B and using it for its own things. Let's say, for example, that module be the data in question is some sort of distance. So it's some sort of distance. Let's say in B, it's represented as meters. A typical thing that might happen. Maybe we grab it from an A p I. Maybe it's just the way we've programmed it. But the data over here in B is meters. Well, the module A wants to convert that to Miles, so it's gonna take it from meters and try to convert it to miles. So it all it does. Is it grabs directly from be. It sends a do no conversion algorithm and then does what it needs to do with it. Now can you see the problem here? The problem is, is that if someone goes in and wants to modify be, let's say we also have another one down here who's doing the same thing. Grabbing beat out data may be converting it in some other way, but it's assuming that B is going to stay the same. And that's the problem. Here is the assumption that B will never change. Well, Like I said, another programmer comes in here to be. He realizes that we're converting two miles all over the place. Maybe the standard nowadays is to represent all distances in kilometers. Maybe it's to represent all distances in centimeters, even just within the metric system. You start having this ability to change things around. We could also represent all distances in miles. Let's say though, that we just decide to change this from meters, two kilometers, something that might be a very simple change. So in B, he goes and makes the change, Maybe this little quick conversion algorithm and now beat out data. The data in here represents meters. The problem is, is that you cannot see who is basically relying on that data from here. There could be 1000 people calling or 1000 modules calling that little data snippet. Now, whenever we change that, suddenly all of these air going to break a A and C and then whatever else is connected will break because each of these was assuming it was meters and then was converting based on that assumption. So because of that, now A is gonna have a problem. It's gonna break, is gonna represent this weird bug where things are. Maybe, you know, a magnitude a little bit to larger magnitude, a little bit small, however, See, Converted it. It's not gonna be way off. Maybe it was converting it to something else over here. So because of the change again, it's gonna be a magnitude off our indifference here as well. So because of a single change, we've now broken a whole bunch of modules. And now we have to go through each one of these modules and change them around and again. Two modules, not the biggest deal in the world. But if we had 100 modules, that becomes a big problem, because we're gonna have to manually correct Ah, 100 modules. And where do we don't have blueprints to tell us which ones are broken? We just have to fix one running again, See what brakes fixed, one running again, see what breaks and so on. Ah, better way to do this. Sort of the way that you get out of this is with getters and centers. So what this is is you create this sort of interface that basically other modules can grab fun and why this is important is because if we changed meters here, we would just go change the two functions down here, get mile and get kilo for kilometer. So in this situation, if we changes from meters two kilometers now all we have to do is just return that directly . Before, Maybe there was like, a times 10 or actually ah, divide by I think 100 to get tow kilometers and then send that out and then a mile. There is a big equation for that. Now All we do is we change this to represent kilometers change these two getters and centers and every single one that was grabbing from this Everyone that was grabbing all these are perfectly fine now because they're getting the same information. We've made a single change in a single file and everything is updated instead of we having it instead of having it so everything is broken. The next thing that we have right here is we have common coupling. So, with common coupling, we have this idea of when several modules have access to and manipulate the same global data. So this you can see these we're all gonna kind of be similar. But just a little bit different in this situation. What we have is we have maybe a big Constance file or we have this sort of almost internal database where we're sort of storing data and taking it out. And we're doing this all from all of these modules. The problem with this is we have the ability to, for example, if this one writes to it, and then this one grabs from there and then during the process of the calculation, this one writes a new value, and this one grabs that value and this one writes a new value. We're gonna start getting these weird inconsistencies, these bugs, these sort of changes are going to be moving all over the place. Eso you sort of have this this lack of data integrity, you don't have the ability to control the data that's coming in and variables can start changing. And let's say that we have a little error in this one right here. So this module right here, all these other ones are working and somehow it's not airing out. But this one does just a slightly wrong conversion. And so when it sends that data up, it makes this variable corrupt. This variable is now. There's no integrity with it. It's actually an incorrect variable. Well, the problem is because everyone's grabbing from the same global data reading, writing, pushing, pulling this that sort of little air that this one creates is gonna propagate here and here and here and here and here and here and here and so on and so on. And you're gonna have this this problem where you're gonna have a bug that's incredibly difficult to track because the bug is going to represent itself in every single module. And you won't know that the little tiny line of code here was the air. And so that's why common coupling, having this idea of everything manipulating the same global data is bad. If you have, for example, though, like a list of constants that never change, that isn't okay, the time to have this sort of everyone grabbing from the same sort of giant list of Constance. Now there might be better ways to engineer a giant list of Constance, but I want to sort of differentiate that as long as you're all just getting from there and this is never changing, that's perfectly fine. The problem appear is that role manipulating it. And if we're manipulating it, then we have that problem where tiny heirs can cascade and break all the modules. So just wanted to make that little difference. The last one is external coupling. External coupling is when several models have direct access to the same I owe. So what this is is this could be an A p I. This could be, for example, controlling the mouse. Maybe you have a program that that uses a whole bunch of modules to grab mouse data and do stuff with that. But we're gonna talk about this as if it was an AI. The problem are the A P I. The problem with this is if the A p I changes its external, that's the kind of the key word here that means we don't have control over. We have no control over how the external works. Therefore, let's say that we're working with Google. We're using one of their AP eyes. If we have 1000 modules, 1000 different modules, so we have a modules. Um, listen to the thousands of men here, and they're all contacting this Google a p I, and calling a single function. What happens when Google decides we don't like that function anymore? We're gonna change it and we're gonna change. It may be drastically or maybe just a little bit. We're gonna change its output just a little bit. The problem is, is that now we have 1000 modules again that have broken. We have to go through and change the way that our modules handle data 1000 different times throughout all of these. And that could be a really, really big project and a big problem, Especially if you're using a whole bunch of AP eyes and this happens weekly, you can see the overhead that would be here. What if the we had instead ap I controller. So we have this little controller here, and they all talk to this with proper getters and centers. And then this talks to the cool ap I. So Google makes a change, then all we have to do is make a single line change. And then all these air updated accordingly because they're just they're talking to that. That function that delivers the Google a p I. And so that's that's a way that you fix that sort of idea. And again, this is your starting to be coupled by the A P I hear. But it's one step better than this, and we can sort of break it down with a little bit more thought process later. But these are the worst case couplings. I hope there are different. They're more cases, of course, for tight coupling different Vincent scenarios. That can happen. But I hope you understand. Do this. The problem on the overall theme here is that we're all accessing. The same data were riding and grabbing from it. And if we have this idea where a single line of code can break 1000 different modules, single line of code can even break just two modules, then there's probably a problem there. There's probably something that we could do to extract that controller, extract some of that information out and fix that problem. The next lecture will be talking about the next level of this, which is slightly better, and that is gonna be medium coupling 24. 4-7 Medium Coupling: So let's move to our next sort of tear of coupling. And that's gonna be a slightly better set of coupling, but still some problems, and that is medium coupling. So as we get sort of closer and closer to lose couple, you'll start seeing that maybe some scenarios might actually work for these areas. And maybe we're starting to get into the nitty gritty of, you know, over optimizing our code. And that sort of a decision that designers have to make is, Do they want to spend the extra time, you know, extensively designing things, or is it better just to get the product on the market? A lot of times it's better to get the product on the market, so people might put some of these things in there and hope to fix them later or just say, you know what's a problem. But we're going to deal with it anyway. And so just keep that in mind is that we don't have to be perfect when coding software and there are different requirements, depending on different projects. But anyway, the next level of coupling that we're talking about is medium coupling, and so the first sort of classifications. On the side of this, that common issue that we have is this idea of control coupling. So it's when data is past that influences the internal logic of another module. What this does is it sort of breaks that black box mentality. The module no longer just takes input, does something and then produces output. Now we have this idea that we have to actually look into the black box to figure out what we need to dio. So instead of just being able to input three, we now have to input flags and controllers and switches so that we're actually controlling the internals of this, which again it breaks that black box mentality. And it requires every module that we sort of communicate with this toe. Have those switches involved? Now, where does this become a problem? Well, let's say that we have this idea of set data, so we have those getters and centers were working good, but instead of in the center instead of beaches deciding its own fate, doing its own things, it's waiting for a flag from a A is telling it how to operate by sending this flag. If you haven't heard of a flag fighting just true, false or some other value you send their. And depending on that value, it changes behaviour. Flags internally are perfectly fine. However, when we're doing them externally, Like over here we have this problem where now the user needs to know exactly what's going on in this module to control, whether true or false, should be activated. And this becomes a problem because again we could have 1000 different modules sort of communicating and calling this set data function. What if then we change this around instead of true, We maybe just made a little thing instead of true. We're going with just tea instead of, um, false. We're going with just EPH. So instead of those two, we're going to just sort of change may be just the semantics, just looking at it, the aesthetics of it instead of, you know, real meaningful change. But anyway, that would break every single module. Because every module is trained, it's now tuned to call that flag. So any changes within here are now going to break every module and you see that pattern again were unable to change one module without breaking. Ah whole bunch of other modules, and that's sort of the overall. The arching problem with with tightly couple things is this idea that if we make one change , we break a whole bunch. So this idea of control coupling is again when we're sending flags or control signals to another module to try to control the flow of data or the operations over in that module. This needs to be broken apart in a smarter way so that maybe we have a set data, certain type in the set data, other type and then set data different type. You know, I'm saying we have three different set data is and that allows us to instead of having to put control flags in, we can just call whatever set data we need in that situation. And so instead of this having this sort of weird control module where everything's controlling it, we now have a p I. And we're all just calling the a P I. So if you make changes, we can make smart changes to that, a p I. The next idea is this data structure coupling and with data structure. Couple in what we have is it's when multiple modules saying share the same data structure. And so data structure is just like this in array or a linked list or some other sort of structure way that we keep data together Now the problem with this is if we are directly calling from that data structure. What if we want to change the data structure? What if there's something smarter, a better way to implement it? Well again, going down that line of of bad coupling? It's going to break multiple modules. Let's say here we're using a ray calls. So we're saying, You know, um, Array, let's just say this is a ray A So we're saying like a five. So we're doing direct calls here. A of are actually doing a of two and then zero. It's deletes. That's a 101234 four and five. And so this is a of three. Maybe we're setting an equal six or something yada, yada, etcetera. But the problem with this, the problem that we have whenever we directly call from this array is what if we want to change this to a linked list and a linked list? Looks something like this will the linked list. These calls don't work. So if we changed us around, we now suddenly have this problem where all of these break every single call like this is now broken. We have to go change a whole bunch of modules. A smarter way of doing this would be toe have almost a data controller control class. So instead of calling direct functions into the array, what we do is we would call a getter and a center in here, and this would talk to the data structure. That way, whenever we change the data structure around, we just change every getter and setter in here. And these would all work perfectly fine again. Eso like instead of, you know, this sort of a of five were making a direct call. We'll say, maybe get index and then we'll pass it a five. This way. The internal workings of how we get number five. We don't need to know. We're not calling it directly. Instead, we're actually taking this sort of we're raising this dependency, and we're allowing this to control all that control logic. Therefore again, if we just swap it out to another data structure inju leaked list or some other sort of way of storing information that we've created. We cannot just do a quick couple of updates in this controller class in all of our modules worked perfectly good again. So that's data structure coupling. This is a little bit more sort of common. It's not the worst thing in the world cause, you know, swapping out data structures isn't something that happens all the time, and we don't usually have a whole bunch of module is talking to the same data structure, but it does happen. And in those situations we want to think about instead of maybe directly contacting that data structure looking to build a control class so we abstract that that control out just a little bit. So these are two main ideas of medium coupling. You'd see how they're not as bad as the other ones where we're making single changes in breaking thousands of things. However, they can be bad if we're making small changes in certain areas in certain very specific ways, we still do break a whole bunch of modules. Next election, we're covering the last sort of side of things, which is gonna be the loose coupling things that were sort of going for areas that we want to use a little bit of coupling for strategic purposes, but keep it as loose as possible. 25. 4-8 Loose Coupling: So the last tier of coupling is that of this idea of loose coupling. So with loose coupling, what we have is this very optimal state of communication between modules. So in this situation were only having very pertinent information being passed from one module to the next. So the very loosely coupled together, meaning we could sort of change one out for another one and there wouldn't be a big problem . Maybe we need to change a line of code here and there to make it work. But it isn't gonna be this giant project. Also, we're not gonna have that problem of those weird cascading bugs all over the place because the train of data being passed is going to be very easy to track. Now we're not aiming for is no coupling. So there is this category of no coupling. But that just means that there's no communication between modules. Or maybe we just have one really, really, really large module. So you know, this module that just has information all the way down, It's completely and totally crazy. And you can already, you know, understand that that would be a problem too. Is it? Just have a single module and be like, Yep, there's no couple in here. That's a problem that's not a That's an anti pattern. That's what we call an anti pattern, which is the opposite of a productive pattern. And the little also break what our next tenant is, which is cohesion, because this would not have a singular purpose. This would have basically the purpose of the entire application. So that's also not we're gonna dio. So no coupling is not where we went ahead. That's no communication whatsoever. And our modules, they need to talk to each other. They need to communicate in some way. There needs to be linkage between them. So that means we're sort of left with these two areas of coupling. And that is gonna be the idea of data coupling and the idea of message coupling. So what? They a couple in what we have? It's when two modules share or past the same data. And what that means is that we just have data in one, and we're passing it to another data or another module passing that data to another module . Remember, we're talking about putting a getter or a center well for the center. What do we have to pass? We have to pass data to set the information over here in this module. That's a passing of data. That's a linkage between the two. If we change the data over here, something's going to change over here. If we decide that we want to pass a different type of data over to be, well, then that's going to happen. We might have to make a change over and be to accept that new type of data. So even though the change would be small, that only a little line of code there to change, there is still a tiny amount of linkage. However, we can't really get past this because modules have to communicate. We have to be able to pass data from one end to the next. So this this coupling is not bad. This is just sort of the optimal state of coupling again. There's gonna be a little bit of it. That's perfectly fine. The other idea is message couple ing, and that is when messages or commands are passed between modules. What we mean by this is if maybe we have this is our initial Isar so we have an app, and this initialize is the app. And then maybe down here we have Maybe this starts the background services or something, and then this calls and do the This is gonna be the notification manager. This over here is maybe the backup manager. This over here is potentially, I don't know, maybe like some back in calculations. So calculation Just couch for short right there. And so you can see this is actually a pretty good set up here. We haven't in it. It calls down to a command to start up the background stuff, the background stuff that partitions it very smartly to the background calculator task, the background backup task, the background notification task. And those all start up. And they passed commands on their telling, you know, be is telling this to operate every 12 hours. This operate every three hours to stop rate every 14 hours, etcetera, etcetera, their commands being passed, their messages. They're saying Hey, see, you should begin this task. Hey d, you should begin that task. They're not going in the nitty gritty they're not controlling, Remember, that's the difference. Is not control coupling meaning? We're passing flags into each one of these to change the control, were just telling it what needs to be accomplished. So in this situation, we're telling it, the calculation process should run. And then this figures out given on the set of parameters in the current state of the app, what that means and same with the backup. We're not passing commands or not. Passing flags were just telling it, Do the operation that you're supposed to dio and in the backup manage will do that just that it will look at the state of the APP and it will do. It's it's job. It'll back up the state of the APP to wherever it needs to go. And so that is what message coupling is, and you can see what the combination of messes, coupling and data coupling. We can create any application that we need. We don't need any of that other couple ing to basically work our application or our our program in any way, shape or form. Well, given a little bit, there is some situations where you're going need to maybe couple it just a little bit more . Maybe if you couple that just a tiny mitt more. Maybe you went up to the medium coupling for a section of your application that might save 200 hours of work. Or it might actually be Mormon maintainable. And those situations are fine. But our objective here, our idea is we want to get as loose as possible. We want to reduce the web of dependencies within our our application. And that is the sort of the objective of all this are loose coupling here again. We don't wanna go with no coupling. We want this idea of loose coupling. 26. 4-9 Coupling Conclusion: one of his wrap up coupling with a couple of final thoughts here. So we're all on the same page. Measuring coupling as we design and develop is important. That's what we've been going over this whole time. That's where you focused on a lot. And it's not just enoughto plan the up we need to plan it. Well, what I mean by that is we can have a really in depth 1000 page blueprint. But if it's just really horrible designs of really tightly coupled modules, it doesn't matter that we have the blueprint of it. We've designed it poorly. We haven't thought about couple in. We haven't thought about cohesion. We haven't thought about the idea of maintaining it and being able to move and change the app over time. All we've done is we've just sort of put our ideas on the paper, not thought about a smarter solution, and then we're gonna go develop that. So just because we have a plan does not mean it's a good plan. And that's what the idea of design is is to not only planet but to make it a good plan. And then finally, we're trying to aim for loose couple coupling and weaken justify in writing anything stronger. And so, like I was saying in the previous one, Maybe there's a situation where you can't think of a better solution than to slightly, uh, strengthen the coupling straight, you know, make it just a little bit tighter in those situations. Don't beat yourself over the head, trying to make it as loose as possible, trying to add, You know, 85 additional modules so that you don't have to, so you can get it down to that very loose coupling. That's not where we want to head. So in those situations, just justify it in writing, Just, you know, explain to someone else who might be looking at this. Why did we use a tighter coupling, even if it's just, uh, the other plan would have required additional development time without saving us maintenance time. Something like that. Write it out and, you know, move on, move on with the design. But overall, we're trying to aim for that loose coupling. It's our objective. It's like a target. We're trying to hit as close to the center as possible. If we're out here every once in a while or maybe out here every once in a while, that's perfectly fine. But we're aiming for the center. We're trying to get it as close as we can to that centre objective. And if we do that, we're doing our jobs correctly. In the next lecture, we're gonna be going over the other side of this, which is the idea of cohesion. Cohesion is interesting, and it's sort of almost goes against coupling in a certain way, which will require a little bit of a balance. So let's jump on over there. 27. 4-10 Cohesion Introduction: So let's go on to the other side of the coin, if you will, and talk about the other really important idea when breaking up things into modules. And that's this idea of cohesion. So in the last lectures we've been talking about that idea of coupling where we don't want the modules to be too tightly associated with one another, but with cohesion. What we want is we want each module to be as defined as possible. Meeting it only carries out a single task. So we don't want to have a whole bunch of modules doing a whole bunch of things, meaning we don't want either really large modules or this module does a little bit in this category. This model does a little bit in that category down here and in this category. And then, of course, the other example is just a really large one, where you just have a single file doing everything. We want them to be very focused so we can take things out, and we can sort of almost mix and match them. Uh, we have that idea of modularity where we could take a module and replace it with another module and it would work perfectly. So, for example, if this was the color red module and this was a color, maybe Green module, we could take the red module out and stick the green right in its place, and it would work perfectly fine because of how defined and how specific these two are. And so that's what we're looking for with cohesion. Now these two. Like I said, they work against each other. You can have a really, really strong, cohesive set of modules that are very, very tightly coupled, and you can have a very, very loosely coupled set of modules that is very, very weak in cohesion. The example that I like to use for this is if we have one giant file, If we have a single giant file doing everything well, by definition, we actually have very loose coupling. There's no linkage to any other files here. This module is loosely couple that doesn't have any link ings. We could actually say this is no coupling in this situation, so that would be fine and coupling. But with this we have the weakest of all cohesion. So what we have here is a file that does everything and therefore has no purpose. It has no defining factor of what it's supposed to dio. And so because of that, instead of just looking for one or the other, we have to try to get the two to meet. We have to find a balance. And that is where we go with this principle of strong cohesion and loose coupling. We're not going to be able to get perfect on each side but what we're looking for if they were both like graphs like, uh like this right here, we're looking to try toe mah, maximize it right in the center here. We're looking to try to optimize our program so that it is pretty nicely and loosely coupled and at the same time, pretty strongly cohesive. If we can do that, we have a great program. We have a great design and it will make the process of maintenance and building it so much easier. So the next lectures, let's start getting into some of the different levels of cohesion like we did with coupling and see some of the common pitfalls and stuff that come with building with respect to coupling 28. 4-11 Weak Cohesion: So let's start our first category with weak cohesion. So we cohesion is the quote unquote worst form of cohesion. It means that we don't have a lot of cohesion. And remember, we want strong cohesion and loose coupling. So with weak cohesion, what we have is we have these modules that are built, but they don't really have a purpose. This creates this idea of speak spaghetti code, which means there might be maybe 1000 different modules in a file. But none of them have a purpose, and none them are linked together in any conceivable way. Therefore, anyone else trying to join the project would have no idea how anything works. There would be no set or guideline, nothing that they could follow to figure it out. They would just have to play around with it until they learned it. And that really slows down production because you can't hire additional people without all of this time that it will take to get them up to speed. So with weak cohesion, we have a couple of categories to start off with. The 1st 1 is his idea of coincidental cohesion, so coincidental cohesion means that the only reason that these ideas and activities and things are together in this module is just because they're in the same file there, coincidentally together. So we have a file, and we just put in a whole bunch of different random stuff into it. So coincidentally, they have this association. They're group together because we say they're group together and you know an example of this might be clean the car seat Restaurant right Book report Flight of Dallas, Texas. There's no logical combination of these things. There's nothing focused on this. It's just a random bunch of tasks here, and this is actually this could actually be one step farther than coincidental. Just because these are all activities, we could even have something like where we put E right here. And it's just something like like a noun like dog. And then now you. Now they're not even all activities. Now they're just even more random. And so when you ever you get to this point of just randomness, that gets you down too coincidental. And like I said, it's impossible to debunk something like this because you'll have, like, a whole bunch of files at all. Do this and then they're all linking randomly, the other files and it doesn't make any sense the flow of the program. Some examples of this are like a single file program. So like we're talking about with that giant single file on the whole program runs from that one maybe Java script file or Java file or something like that. That is a coincidental cohesion. There's nothing linking that together except that they're all part of the same program, and they're all in the same file, the mismatch controller as well. So if we have, for example, like a model view controller, we have a controller class that we're trying to, you know, pass everything into. We have these ideas and we're trying to create better code. But if we don't actually sort of give it a purpose, and we just put everything into that controller class, it becomes coincidental cohesion as well. And maybe the little bit over the logical if they're all controllers, if they're all actually do activities. But usually there's something in them it doesn't and it kind of falls back into this category, and then, like I said, spaghetti code where we had just have all these modules that all have absolutely no purpose talking to one another. So that is coincidental. Cohesion just file. But over the has is that it's in the same file. The next one is this idea of temporal cohesion, and that means that were linked together because events happen around the same time. And so if we went for a real world example here, it would be like brushed teeth. Take shower, eat breakfast. Wake up. What are these? Is there like a morning your teen? So they all have been right around the beginning of our morning, so they're kind of there is a link together. They're better than this over here. But again, it's not very helpful because there's still activities that are all over the place. Here we have something happening to things happening. The bathroom. One in the kitchen. This one's in the bedroom. Um, some of them are consuming items, some of their just using others. Some of them are cleaning. Some of them are an act change of state. So we're going from sleep to waking up. They're all completely different in their there. Amount of control, their amount of changing things around them and If you're thinking in program, you can see this is well like Imagine if something was happening on the front end front and this is and maybe like, the database over here. This is purely on the back in may be at the cashing servers. Some of them are changing front invariable, someone changing back invariable. Some are grabbing from the database. They're all over the place, even though they happen at relatively the same time again, it's not very cohesive. And an example of this is like a program, like do shut down activities or do, um uh, maybe start up activity. Stuff like that is these sort of things that activate at a certain time around the same time, and that is temporal cohesion. The next one is logical cohesion. So we're sort of getting a little bit better with logical cohesion and in this sense, its activities which are linked in the same general category. So what we have is we have drive to Dallas, fly to Dallas, take train to Dallas and take boat to Dallas. So these are all activities in which we're heading to Dallas. But the problem here is that they're all used in different places and see what I mean by that is that we don't we could have a program written. Let's say that this over here, this grouping is into this controller right here. We could have a bunch of different modules calling one offs from this controller one at a time, one at a time, one at a time. And the problem with that is that they're all sort of forced to change their interface so that they will match the other ones. Like, for example, if we're taking a train, we might need a ticket. However, we're taking a boat. Maybe we don't need a ticket, but we still have to pass it an empty variable saying that there's no ticket for the train , but we're actually using a boat. And so we have this sort of locked interface that doesn't allow us to communicate clearly with this, and a lot of times we might not ever use Fly to Dallas, for example. And so now we have this this method that isn't really used, but it's with other methods that are frequently used, and so it becomes in an issue where we can't we can't edit it becomes hard to track certain things, and it's just not a very useful file overall and something Ah, that might be a real world example of this would be something like a backup controller that has a whole bunch of different areas it should back up to. So maybe one of them is to the cloud. One of them is to like some backup, hard drive or something. Um, one of them is a local backup, etcetera, etcetera. We have all of these different backups in here, and we're sort of just calling them one at a time and having to provide these different interfaces for each one of these calls. So instead of this, we might look to, you know, break it up later on, and that's what we'll talk about a little bit more later on. But these are some examples of some very weak cohesion, things that are just not very well organized and that are all sort of only together with a very small amount of thought, either their coincidently together. So they're just together because of the fact they're together, that temporarily, so we kind of like put them in the same time, or the logically so he sort of put them in the same general category. But again, there is a very good specialization in here, so that is weak lesion. Next, we're going to talk about medium cohesion, which is kind of the area we want to be aiming for, and we have. We'll move on from there. 29. 4-12 Medium Cohesion: Our next sort of level of cohesion is that of medium cohesion. So medium cohesion is the next step up towards strong cohesion. With medium cohesion. We start to have a little bit of an idea of what our modules are doing. They're doing decently focused tasks. However, they're still reaching just a little bit too far in a bunch of different directions. And let's start with procedural cohesion right here to sort of bring that point home a little bit. So a procedural cohesion. What we have is where order of execution passes from one command to the next. That means that we have this set of commands in here. We call one which goes to the next. That one goes date the next and the next into the next until the task is completed. Now, the problem with procedural cohesion is that these tasks don't have to be in the same area . They just have to accomplish the same overarching activity. And this overarching activity is to clean the car. So in this situation, what we have is we have we first spray the car with water, Then we fill out a form. Maybe it's some business form Or maybe we're accepting money or something. And then we scrub the car insurance and then we dry off the car. As you see, the task of cleaning the car has been completed. It's done now, however, we have this problem where we're doing. We're reaching too far. So this module, instead of just doing car related activities, it's also doing potential financial activities and and maybe administrative activities, maybe organizational activities with databases. It's going into other areas that it should not be going into. So if we look at this, if we look at this module of clean car, we don't expect clean card to be manipulating financial data. That's a big no no, that's a big thing that we look at more like. Well, why is that touching financial? That it shouldn't be doing that. That should be, Ah, very set number of people and commands that do that so we don't run into problems with either the law or our own bookkeeping going awry. So that would be a very big problem if it did that. And so what we don't want is to have this module where we look at it. We don't know that it's doing these very important tasks just from looking at it. So in this particular situation, we have that slight bit of cohesion where it is accomplishing a single task. However, it's reaching way too far and do a bunch of different directions. An example of this would be updating all databases and logs. So you see that we're not only updating all the databases, which means we could be using, as we could be updating ask you well and my SQL and maybe maybe Mongo. And then we're updating all the logs, which could be really any set of text files, etcetera, all in one command. So it does accomplish a task, but we're reaching in a whole bunch of different areas here. The next one is communication on cohesion, and that's when all activities support the same input or output data. So in this situation we have basically the the sort of glue to this module is the article we have article, article, article, article. So we find the author we find the date, we find the lengthy off their article, Um and then we set the content of the article. So all of these are they're all relating to article. However, they're doing a whole bunch of different operations on their all sort of touching this same data set instead of having the Gators and centres may be in different modules or, um, or breaking it up into a little bit more understandable. So in this one week and both manipulate end read, data, weaken, sort of changes around, we can actually get race conditions if to try to set at the same time. There's just a little bit far, and now we're starting. Once we get to this level, by the way, we're starting to get to the point where this is pretty common in programs. There are a lot of times we're going to have a stack, and that stack is gonna contain all the operations for the stack. However, we also must note that it could be a little bit better. We could sort of break that up even more and make them all very, very focused modules. And also I just sort of make a note here is that we don't have to have just a single one. A program could have communication allow and procedural cohesion. At the same time, it could have communication, Elin, temporal or all those other layers of cohesion at the same time. So what we're trying to get we're just trying to get the highest level of cohesion and remove all the little bad parts of cohesion. So even if we have the highest level okay, he cohesion, it doesn't mean we have an activity which deviates from and actually breaks the overall cohesion. Anyway, that's communication when all activities support the same input or output data. But that's about it is that we were just talking about an article here, but we could do really anything with this article we could like I said we could use. Maybe there's a commanding here to send it somewhere. Just store it in the database. Teoh, make a purchase with the article again, we're touching financial data, which is, ah, problem to set the content to find the content. We're doing everything with the article. It's it's all the same input, not the data, but we have a lot of different operations here. Then, finally, what we have is sequential collusion, which is a lot of times confused with procedural cohesion, with sequential cohesion. It's when all activities work in which the output data for one is the input data for the next. So it's sort of a combination of procedural and communication. All we have this idea of this shared piece of data, the article in this situation or the car in this situation and the nature of procedural where we're going, one to the next to the next the next. So in this situation, we are sanding the car, applying the primer, spraying the main coat and spraying the clear coat. So are we doing? We're repainting a car or just painting a car. So in this situation, we could put paint car, and we know that the only thing happening in here is we're painting a car. It's not reaching anywhere else except the domain of a car and paint being applied to the car. So we don't have the financial that we don't have the administrative data. We don't have the database data, all we're doing and I'm gonna repeat it one more time is painting a car, and that's why we're starting to get into from really good cohesion right here is this is a very well defined grab, Ah, sort of area. Well, defined module, and it's also procedural. So we know one operation will carry into the next week carrying the next will carry in the next meeting that we're gonna be taking care of. Each one of these points is going to be touched, so there isn't gonna be like a part that is abandoned or part that is called from somewhere else there. It's a very defined module on The whole module is used, and in this situation, it might be to update a specific database roso in this place. I just put database row, but we might want to be more specific here. So maybe a my on him there when you didn't s there My s Q l so update my SQL database role . So as we noted, over here, we're updating everything. We're completing this giant task that involves all of these different areas. But here we're doing something very specific. We're updating a single row of a my SQL database were using a single technology. We're working with a single update function and that's it. We're not the leading were not we're not adding a new row were just updating. We're only using my SQL. We're updating ah database and it's gonna be a row so you can see very specific. There might be a couple steps to that procedure, but overall, it's going to be very, very focused. And so, as you can see, we've gotten a little bit better. Cohesion in the next article or the next lecture were to be discussing sort of this strong cohesion, and this is where we get into what we're trying to aim for with our cohesion. And it gets a little bit into unrealistic Rome where it's a little bit harder to get to that area, and maybe a lot of people fall back to these areas and again, like I said, that's pretty fine. But we want to aim for that. We don't understand what we're aiming for so that we can actually came there and try to get the best software possible. 30. 4-13 Strong Cohesion: so our final level of cohesion is going to be that of strong cohesion. So a strong cohesion. We have to sort of categories with us and these air both the top categories. One of these is not better than the other. It just were trying to get both of these within a module. So what we're talking about is overall object cohesion and functional cohesion, function cohesion, talks about the functions within an object. Or if we're not talking about object oriented languages, something like original just C, not C plus, plus just original C. Then we don't have objects to work with. Therefore, we can't get object cohesion, so we only go with functional cohesion. So with these two, you'll notice that they're very specific. It allows us not on Lee to look at a module and instantly know what it does. It also allows us to swap that module out. So, for example, in the left side over here, with functional cohesion, we have these really, really defined areas here, and it's one of module supports activities needed for one and one on Lee. One problem related task. And so we have this determine monthly payment right here. And the thing is, is that with a proper high cohesion, we could actually take this out. We could take this. We'll say This is the monthly payment and we could maybe drop in a new module of weekly payment And it be that simple because it's set up in a way where all its taking in is the proper input data. And it's out putting the proper output data. Therefore, if we put in a module that's similar to it, But with some things changed, it will change the whole program really, really quick and allows us to mix and match our program and sort of customize a little bit in that way. So with functional cohesion, all we're trying to do is get these modules that are very, very specific in their tasks, and the functions within the module should do the same. So we don't need a function in the module that does everything you know, like in sort of ah, lot of times will have like in a knit function, and we don't want that in in function to just literally do everything within the the module . We want some other functions in there. We want to break it up so that even if the unit function, even if it's going to go in a sequential order and it is going to call everything the module, it's not just a giant grouping of code. We have these basically function calls which go to another section of code and does the function goes to know section does the function goes, you know, section does the function and therefore we have this functional cohesion within the module as well. And whenever we build modules like this, we get to the objective. We're we're finally making it to this point where our program becomes easier digest and it becomes easy to maintain. And so just another example that is if, for example, we said to compute intercept off graph. So you know, we have just two graphs, and all we do is we feed it these two graphs of information. So we say we have this craft in this graph, we give it the points, and then it just gives us the point at which they intercept. That's a very, very specific thing. All it needs is to graphs as input data, and it'll do all the calculations within it and then just output the exact ex and why to get to that point. So again you can see how that's very, very narrowed in, and the other one is object cohesion. So this is when all activities on Lee modify a single object. And what we mean by this is, let's say that we have either like a mortgage payment or we'll go with this the 2nd 1 here , the user object. So what? The user object we have basically the object itself. So this is the user and then at the top here, what we have is a bunch of attributes of maybe the name email address. Um, how many times they've logged in current points. If it's like game system, as in the functions down here are only manipulating these data, these pieces of data. So you know, you might have something like new users. So this is, you know, new User, and so a New Year's or will initialize all of the data, and then maybe we have getters and centers. So if you can read that getters and centers, which means they're just something specific to get or set each one of these attributes. And then you could have something like, uh, maybe if you do a certain objective, it adds a point to one of these categories. So, like, for example, we could do like, ah, log in, um, sort of function here and what that's gonna do it is not gonna It's not reaching out to anywhere else. It's just updating the attributes of the user. So if we log in, we're just gonna get ourselves a maybe a point in that area or or something like that. And so overall, you can see that this is very, very sort of localized. The user has attributes, and its functions only do very specific things and on Lee update the attributes within the object as life gets us that object cohesion. So a functional, an object cohesion. We have a problem that is now defined really, really well and in a way, such that it's very easy to mix and match. And there isn't a lot of the spaghetti code of all of this stuff reaching out to everywhere else. We just have basically single inputs from maybe a controller class here telling the user, You know what? It should update you know a user logged in user logged out users got 50 extra points today , and then it's just gonna update all that stuff here, and it doesn't even need to send stuff back, because if we need to see it, we'll just grab the user object and look at the data with a getter from there. But we're trying to create this very small control flow here throughout our entire project . Keep it simple, keep it defined. And we have ourselves strong cohesion. Now, on a side note, you'll notice like I was talking about. If we have a really strong coupling, a lot of times will have weak cohesion and the same can be sort of linked here is if we start, you know, taking a problem and breaking it down into every single function, for example, is a module. We could have really high cohesion, really good functional cohesion. Each one of these has a very specific project problem. However, you'll also notice that now these things need to talk to each other. So now we're gonna actually gonna start getting this area where these are actually starting to a link. Even though the control flow is small, meaning that we don't having 1000 arrows going each direction. We still have these sort of areas that are just linked together, Um, a little bit tighter than you might want. And so in this situation, whenever we get to really, really strong cohesion, a lot of times we can lose our coupling and our coupling becomes stronger as well. And again, we don't want that. So we're trying to look for that balance between the two were trying to come up with a good sort of problem solving idea here so that we both have strong cohesion and weak couple ing . 31. 4-14 Importance of Design: I want to drive this point home about how important design is. A lot of people love to just jump into the code and start working on it. And I say, You know, I'll design it as I go. The problem with this is that design becomes more and more difficult with the MAWR code. You right? So on the left here we have a simple sort of example here. It's not even a lot of stuff going on, but what we have is five modules with maybe 3 to 5 functions in each module. However, there's this very strong split in between the meaning that each function over here is doing a little bit of a single task. So if we went back to something like calculate the mortgage payment or, you know, find or sort in Excel spreadsheet or something like that, we have that sort, that single function of calculate mortgage payment a little bit here. Then it goes over here and it calculates something's moves over here, and maybe there's a return value from this side that goes back over here, and then that one sends it to here and then, you know, maybe a complete salute. Maybe it goes all the way up and incomplete salute. And now we're done. But you'll see that it's all spread out over here. We have multiple, multiple different activities all going on within this. Maybe like I made because its mortgage payment, Maybe this is like a tax document or something, and or a tax program documents. So maybe not a document, but ah, program. So it was a tax program. And so we have, ah, bunch of different tasks that need be accomplished. However, you can see that there's just this cascading of all this stuff going on. Imagine if there was an air happening right here. Where would we have to trace it? We would have to check not only this function. We have to check that function. We have to check this function with check over here. Over there in this whole module. Imagine it is 1000 of these, It takes a while. Now, If we had just planned out beforehand about how all of these were going to work out, then we can sort of get this side over here. And like we're saying with the orange, maybe this is your mortgage. Maybe the green down here is stuff to do with your income. Maybe the purple is stuff to do with your business. And the blue is maybe something to do with, like, dependence Children. And so you can see now we have a very good split. There is a little bit of communication happening back and forth between the modules. We have this very easy place where we're like, Okay, income is over in this section of the program. The business side is over in this section. The mortgage side is up here. The child side is over here. And imagine if we created a new Maybe the controller maybe wanted to create, like, a front end here. So let's find a new color over here. Maybe wanted to control create a front end that's gonna be distributing itself. So it's going to go to the income. It's gonna go to the business. It's gonna go to the mortgage, and it's gonna go to the child. And so now all we have to do is just basically create a single link in all of these sections. Grab all that data down there, and then we have that front end. Imagine trying to do that over here. How hard do you think it would be to try to get all these toe work correctly to find the proper in points, to send the correct data over here and then to do calculation and stuff? It's so much more difficult. And that's all. I'm tryingto with this giant web of color and stuff here. That's all I'm tryingto put out there across Is that time spent in the design is going to save you a whole bunch of time later on, because at some point this becomes so, Emmanuel that we have to scrap the whole project or we have to rebuild it to get it to work basically like this. So if you plan it out beforehand, you can get that out of the way. You could get at least, ah, good blueprint about how the general flow of things will go, and it will save you so much time in the future. 32. 5-1 Implementation Basics: our next unit after that of design is gonna be implementation. And this is typical in the software life cycle as well is, once we have to design, we can start working on implementing or actually coding the thing. So we're talking about implementation now, this entire unit isn't gonna be as in depth as the other ones because implementation is very specific to the technology you are using. So if you're creating a online app, it's gonna be very different than if you're creating a mobile app or very different than if you're creating a back in server application that talks the financial institutions and never interacts with the front end user. There are 1000 different ways that you can implement something. And therefore, like I said, that there isn't a lot that we can talk about here that wouldn't be really specific to a certain type of problems. What we're gonna go over is just some of the core tenants and then a lot about deployment and that sort of area, because deployment is sort of a theoretical area and there are some estates you can make in there. Some things you can learn there. So let's go over some of the tenants of programming. One of the main things that you should do, or that the company should be doing is to take care of the programmers. That is very important because implementation of where most of the time is going to be spent. And if it's poorly implemented, then it's where basically, most the time could be lost to If you have the most amazing design document in the world and your programmers don't design it like the document, well, it doesn't matter that you spent all that time on design because now you have a product that is just as inferior as if you didn't spend it on design. And so what you need is you need to have your programmers alert and focused. You need to have them focused on the task at hand and thinking of the best solutions as they go forward. Because even though our design might be pretty in depth, we don't have some of the nitty gritty designed yet, and there are still choices that could be made within this. There's still very poor choices that could be made, and what we get is this thing called technical debt that keeps coming back up. So if we start building up more and more technical debt, it's going to take more time later on to fix it. So if we saved 10 hours now, it might take 100 hours later on to fix that. 10 hours that we saved right now. And so we can kind of think of it like this. 35 hours of programming a week, difficult work weeks, like 40 hours with 35 hours of really focused programming could be just as productive as 70 hours. So if you have your workers, you know, work until eight o'clock at night every night, you know, really trying to get something out. It's probably you might be able to push the date that, you know, maybe instead of releasing way over here, it releases, you know, a few days earlier. However, the amount of problems and the amount of fixes you're gonna have to do to get it to that optimal state is gonna cost way more time later on to fix that. So keeping this in mind is that just because you had more hours, it doesn't make it. Mork Orrico productive is very important and programming takes focus. Constant interruptions will reduce the overall focus. So if you're at a company and your company is constantly calling meetings, maybe that's something that needs to be brought up. Maybe the production overall could be quicker if you don't go to meetings all the time. If you're allowed to have, you know, maybe a four hour block in the beginning, to really just sit down and focus on coding. And if you're maybe self employed or if you're working for euro naps, then you need to keep focus yourself. You need to make sure you know, you don't deviate off into social media or watching YouTube videos that you keep yourself very focused on the task at hand. And there's encoding principles there just sort of, ah, set of principles that you should keep in mind while in permitting. And that's use a style guide. So all the code looks relatively the same. This is very important if you have multiple different people working on the same project. Imagine something like Microsoft when they're working on the OS systems. Imagine if every single programmer put their own little style spin on things you would have code that every single file is different and therefore hard to understand. And it can come down to simple, as if we say, a function Soviet like function. That except a parameter a Do we put the curly brace on the same line and then the embrace down here, Or do we always indent and put the curly brace like that? There are 1000 these little decisions, and a style guide will help make sure that the code all looks the same. Therefore, it's easier to read and easier to get people up to speed on. The code code is written for people, not computers. That is something very hard that something very important understand, and a lot of computer programmers don't get this concept. They try. It sort of goes in with this one too. Short code does not equal batter code. A lot of people take it as sort of a pride thing. If they can write a function that could have been seven lines of code and then they try to write it in something like three lines of code, they try to use some really complex, you know, function of a of B times six x three of you know, multiplied by nine. You know, stuff like that, where it goes on and on on. It's a single line function where they could have actually broken it up into a really nice , readable expression that someone could jump in and be like, OK, so we're taking this function that we're adding free do it, that we're dividing the amount of taxes they have to pay and multiplying it by the gross income, something like that. And so they could be like, OK, this function is doing that. Where with this one, they're like, I'm not entirely sure what this is doing, and there's no comments to tell you what it's doing. Then this function is basically a mystery. It's a black box that this programmer is not gonna have to throw data through Gary that puts an input out in and then put some output data to figure out what the heck is going on . And so why was this implement? What's the purpose of implementing it like this? Then it didn't save any time. These air both equivalent. It makes it harder to read, and overall it just makes maintaining it harder. So there's no point in making it as concise as possible like this when you can. Now you do want to keep it concise, but when you can make it just a little bit more readable, always air in the side of more readable make modules easy to learn and understand as well. So again, this goes back to the modularity things, the coupling, the decoupling Whenever you're programming, if you have to come up with a new, I'd like some different methods and different classes all acting together, then make sure that you make them easy to learn and easy to understand. Make them, you know, high cohesion, low coupling. Make it so I can look at it. And I could immediately say, OK, that's dealing with our payment information that's dealing with You know, that's dealing with the user information that's dealing with the user itself, something quick like that. And then finally, we want to break up our actions in the methods. We were talking about modularity a lot where we have these big modules. However, inside the modules, typically we have these things called methods. If you're if you haven't taken a programming course yet, these methods are basically like little functions within a module, and we want to make sure that we create enough these methods and we don't code duplicate. So if we're doing the exact same task in this function and this function in this function, maybe instead of copying and pasting in three places, we create ourselves a new method so that it makes it more readable over time. But overall, we want to create code that is, four people we want to create code that is readable. We're gonna create code that is easy to maintain and easy to bring additional people on because we want our program to succeed. And if our program succeeds, we might have to bring more people on to keep up with maintenance and adding new features and such. And if we have very poor code, that's gonna be impossible. And even though our programs exceeded, it's going to fail over time because we can't keep it moving. So that is something just the core tenants of implementation. And now let's sort of jump into a little bit of the deployment thing because that's important is how to deploy our software properly so that we can either back it up or weaken . Basically, predict some of the bugs that might come out and make it as pain free as possible. 33. 5-2 Buy Vs Build: and last lecture. I said we're gonna jump in employment next, but I want to cover one more thing before we get to deployment. And that's this idea of buy versus build. So this idea is very important because it can save you a whole lot of time and actually save you money in the long run as well. So what? The idea of Ivers build? What we have is, whenever we have our design document, we have all these modules and subsystems sort of categorized out for us. We can begin looking at these modules and seeing if there's anything out there that weaken by instead of developing in house. Ah, lot of companies have this idea that they have to develop everything by themselves. They have to develop it in house, and that's the only way they're going to do it. But that can leave you to a lot of problems. First off, it could be more costly, developed something instead of buy something. If we've bought something, another company has already developed it and they're making money because they're selling it to tons of people. So they're not selling it for, you know, a one off solution which is typically more expensive. They're selling it to a whole bunch of people, I think. Microsoft Office How much does that cost? I think it's on a subscription model of something like $100 a year now. Imagine if you, as a company, decided that you're going to build your own Microsoft Suite or your own, you know, excel, which is spreadsheets, your old word processor your own basically power point. So you're on slideshow processor itself. How much do you think that would cost? It's certainly not gonna cost $100 a year. It's probably gonna cost you somewhere around maybe 500,000 plus dollars to get a program that's even decently close to Microsoft. So in that situation, of course, you're not going to develop it yourself. You're going to buy it. And so that can happen within our own projects as well. Why reinvent the wheel when we can spend a little bit of money, save a whole lot of time and actually have a product that is developed and maintained by someone else so we don't have to even work on maintaining it anymore? It's it's completely maintained by someone else for whatever costs we paid. So in that situation, what we can do is we can actually go down our modules before we begin implementation and look at things. So, for example, in this one, we might say, Yup, there's something out. There is a great solution. It's really, really well regarded. We're gonna go ahead by this one. It says developing it, and maybe this over here and these were gonna buy as well. Everything else just doesn't fit what we want. So we're gonna end up having to build these things and so just sort of build all of these right here. But overall, imagine if this on the left here was, you know, maybe, ah 500 our project and this one over on the right here. Maybe it was something like a 2000. Our project to get that upto working. We've now just saved ourselves a a whole bunch of time. And now our engineers that would be working on these can help us finish off these. So we have this product that's gonna come out a whole lot quicker. We're going to save money in the long run because at 2000 hours cost a whole lot with software engineers, and we're gonna actually have parts of it that are maintained by other companies. So whenever you're looking to build your project, before you begin implementing, do a quick search, see if there's an implementation out there and a lot of times are actually free, which is kind of crazy, but they're called open source. Amazing, but do a quick search, see if someone else has done it already. And don't reinvent that wheel. Make sure that you look to see if there's something you can purchase, something you can even start with, a template somewhere to start so that you can save some time, save some money and get your project out on time. 34. 5-3 Deployment Overview: Okay, so let's begin talking about deployment. Unemployment's a little bit tricky in the sense that it's actually sort of a mix between two different things. And what do I mean by this? What I mean is that deployment happens in a time space after testing after building. So it happened sort of at the very end of the life cycle. However, in the building phase, deployment is a lot of times taken into account during implementation during the actual building off the project. And that's because a lot of times with deployment, what we have is it needs to have some sort of implementation created for it. So maybe we have to code. The project is a little bit differently. Maybe we have to set up an extra server. We have to set up some backup areas in all of that stuff. It happens in the implementation phase. So that's why a lot of times both computer engineering and I like to think of deployment within that implementation sphere, because the only way that you get the good deployment is if you build it into the project itself, and that's very important. Is that deployment? A lot of times needs to be planned out, and it used to be executed within the coding of the APP. We're not talking here about a sort of abated employment or just, you know, sitting it out to some internal testers or anything like that. We're talking about the final deployment. What I mean by that is it's the one where we have the project and it's actually going to go out to the end users over here. So it's going to be the final product that is paid for that people are going to use, and that is where we need to have a plan. We did have a plan for a couple of different reasons. The first, a major reason is we don't want to break things. We maybe this is, you know, one point. Oh, and in that case we don't have to really think about Rollback because we're kind of releasing the product. So if there's a problem with it, the only roll back that we could do the only way that we could go backwards is who stopped offering the product. That doesn't usually make sense, but what we really need to make sure of is if we're going from like this one point. Oh, and we're upgrading to two point. Oh, now this is where this idea of retreat comes in. The roll back the revert. If we are deploying, we don't want to break everything. If we have, for example, we're running one point over here. 1.0 might be making the company some money. Right now, 1.0 is getting us profit. We just tryingto upgrade it to two point. Oh, because we think it will be better. It'll it'll draw more customers and will make more money at the bottom line here. So we want to upgrade to to point out the problem here exists if a an error comes up during this phase, something that we didn't expect comes up will. Now, not only are we not making money from 1.0, to point out didn't didn't come out either. So we now have no product. We're offering in every second Mrs down. We're losing money. Imagine if amazon dot com imagine the giant you know, marketplace that Amazon is. Imagine if it goes down for five minutes, 10 minutes. How much money do you think they would lose from just those little periods of downtime. So in those situations, an idea of rollback is very important, and the idea of rollback just kind of comes into We don't know. We think it's gonna make it through, but we're preparing for at any step it to fail. And if it fails it, any of those steps, either our program or the person running the upgrade will know exactly what to do. There'll be a plan so that it can roll back and go right back to one point, and then we'll fix it later and try again later. That is the thing that we need to basically plan out the most is have that plan in place so that when something goes wrong, it isn't completely and totally unexpected. We on air pops up like, Okay, there's an error. We didn't anticipate this. Let's roll it back to one and we'll figure it out. So goes back over the one. We start making our money again and we figure out what exactly is going wrong to get it up to chew? And this level of planning sort of directly relates to how the deployment affects the overall project. So if this Is it a small update, a large update or complete overall, in this situation, we're talking about a complete overhaul, so we need every single situation covered so that no matter what, we there will be a product at the end of this rollback. If we're talking about a very tiny update, maybe we're changing the color of a button somewhere. We probably don't need to come up with a giant roll black back plan for this. There's not a lot that can go wrong. It's just a tiny HTML document update. And maybe the only plan we have is to just save the old one and a little backup folder and then executed. And if something goes wrong, just swap it back in. Its really, really simple. That's, you know, that would be exactly a really small update. When we get to those larger updates we need There might be hundreds of files changing. There might be thousands. There might be new databases that are coming online, new communication lines, new control flows, and we need to make sure that if in the middle of this it's building and we have this one going up and then it crashes right here. What happens? Do we delete this and delete this? Go back all the way just to the one. Is there some, like, backup server that has one point all running. And so we just kind of take this server, destroy it, and then just sort of switched all of the traffic over to the server, which works a lot of different things. We could go over, and that's we're gonna be going over in deployment. 35. 5-4 Deployment Planning: tonight we've covered the introduction, deployment. Let's go over actual deployment planning. Now with deployment planning, we don't have this sort of model that we can create that we can in a whole lot of other areas. And this is basically due to the fact that planning and the idea of deployment is very, very focused on exactly the problem at hand. What I mean by this is let's say that we're talking about Amazon and we want to add a new feature or something new to Amazon. Now, if we add something like a backend changers, new products or a new fee Jha Amazon, it's going to be a different deployment process. Then if we added it to walmart dot com, or if we add it to eBay or any other online retailer, and this is because each one is built differently. Therefore, there is no one size fits all plan for these and because of that, Like I said, we don't have models here. All we have are these questions that we need to ask ourselves while we come up with the deployment plan to actually create a deployment plan that we can then implement, So don't expect like any models or anything in this particular part, just kind of come up with these these ideas and these questions that we can ask. So the first thing we do understand is the amount of planning it dependent on the size of the change. And this is referencing Thean. The overview of the scope of the change is very important. If we're making a very tiny Tex change, let's say one of the products on Amazon is slightly misspelled. We don't need to go through a giant process. All we have to do is basically make a quick database update, and we have now deployed our change. It's nothing large. It's just a very, very small change now for adding new products we've taken up. We've gone up into the level, so we have changed the text. But now we're actually creating entire new products again. These are very independent. It's not talking about the architecture of Amazon. It's not talking about the backend servers of the financial data. All we're doing is adding and couple of products, there are a couple of things that could go wrong here. We don't offer things that we don't have. We don't want to, you know, infringe on copyrights or anything. So a little more planning goes into this if we're opening up an entire new section. So let's say we're opening up like a new section called Toys, where we're actually implementing a ton of new products and maybe even new features. So it's not just one product, you know. We have multiple products. All may be tied into their own little categories. Now, we start having this thing where architecture comes into play, how do we place them? One of these new features were implementing. Things can start going to go wrong in this section. And maybe after this we're not just upgrading, you know, a section. We're upgrading the entire back end so upgrading the entire way Amazon processes or any online retailer processes their information. So now we have these clusters of basically all of this data here that we're touching. So I'm trying to make, like, little boxes here. So, you know, we have, like, this box is here in this box, is here, and it's very, very detailed, and it goes on and on and on. So we're updating the entire back in here. We're gonna need a ton of planning for this and a lot of things that could go wrong. And we're getting to this point where critical things could go wrong. Where a failure here, Ah, failure at this point would actually make it. So we stop doing business, we start losing tons and tons of money and then so on and so on until we you know, our updating the entire website. So whenever we're creating these changes, we have to keep in mind that scope is very, very important. And we look at areas which will most likely have the biggest problems and some of the areas that look at her over here. This is not a comprehensive list meeting their arm or areas that we might want to look at. But these are just some ideas of things that might change. So we're looking for where the biggest problems might occur. And again, we don't need to spend a whole lot of time if we're making, even if in this giant update we're doing a couple of text changes, we probably don't need to make a role black or a way to turn back on those areas. What we do need to look at is stuff like this, for example, database activities. Maybe we're changing the way the database works. If we're changing the way the database works, there's a potential that when it switches over, the database could become corrupt. Maybe Power turns off for half a second while it's updating the database, and now we have an unfinished, sideways sort of database that isn't gonna work for either version. Maybe there's a typo in it, and the old version doesn't work with this new version. And now we have this big sort of data mishmash problem, and requests are constantly coming in. So we need to understand what to do with the database. Third party software integration. We're changing our program. But were we can't tell others three other third parties. That means that it's not us it's someone else's software were using. We can't tell them to change with us, so if we make a change, we have to make sure that we're still integrated properly. Otherwise, that change could break all of the third party software. And suddenly, for example, if we're working with Amazon again, maybe the eBay or maybe the PayPal payment system doesn't work anymore, and that's a That's a big problem there. Then we have run time changes. So, for example, during runtime maybes, things have changed. We've gotten the code to work, but when we actually deploy it and run, it may be something changed that we didn't anticipate. And that's important to understand, not to turn back from training on both the user. In the business side, the website usedto work a certain way. The program used to work a certain way, and now it's changed. So we need training. We need training both on the user side. Maybe, we know created tutorial to help people get through it so we don't lose business. And we need training on the business side. Maybe the servers are different. Maybe the backend is different. We need to make sure our business, our employees, are trained to keep up with these changes. Downtime, how we're gonna handle the downtime. Are we going to, for example, keep the front end up and just have orders? Maybe like stacking? If us again, like we're talking about an online retailer, are we just gonna have them put into a queue and wait until the servers are restored or we're gonna just shut down the whole website and not let anyone through. And what are the financial implications of all of this backups? Network memory. These are things that might change. Maybe the backups We're gonna go into a different location. May be the new website is too big and our backups aren't going to work anymore because we need to have larger storage, which kind of goes on with memory. Maybe we're introducing a new A P. I call, which is Ah, college of the server. And maybe with that call to the server, we start having networking problems. We didn't anticipate that. It's gonna go from maybe like one gigabyte per second to, I don't know, maybe maybe 10 terabytes per second. Maybe we made a really large change and maybe our cables are hardware itself, can't even handle that. And we have to implement a new server farm or something like that. So all of these things are ideas and areas that we need to look at, and we need to plan the steps and we need to plan how to turn back on these steps. How do we go backwards? What's a way that we can reinstate the good. The old website works perfectly fine We're trying to do is we're trying to enhance it, maybe fix a couple of bugs, but right now it's making us money. We don't want to burn the whole business to the ground. So we need to make sure that we're going forward at increments and then if anything goes wrong, jumping all the way back and re working the way that we do this, let the play it planning. There's some questions to ask and sort of have to work out to get this to be a successful deployment. 36. 5-5 Deployment Rollback: I want to cover the idea of a deployment roll back. So the idea of deployment rollback is like I've been saying in the other lessons, and that's the idea that we can go backwards. So if we have these steps, what's it it we have Step one and then that moves on to step two and step three four, and then let's say five is where it's fully deployed and working. So at this point, what we need to do is we need to look at the steps that we're gonna be using to deploy our new update, and then we need to look for a point of no return and we know the point of no return. We know whether we should push onwards, work through the heirs and see if we can't make it to you live side or if we should turn back and every step of the deployment process, we need to make a decision of whether rollback is a better option. So we need to have options on ways to roll back on everyone these steps and also on some of the bit big errors that might happen. How do we revert back to Let's ah, maybe this one is the beginning here. The master branch. How do we get back to master? So we're trying to make it from five toe. Let's say we'll put this overhead two point. Oh, so we're trying to make it through the steps over to two point. Oh, and we have master here. So what we're trying to figure out is at each one of these steps, one of the ways that we could turn back where the decisions that we need to make on whether we should continue onwards or to turn back, Let's say that we say our point of no return is at step three right after Step three. And the reason that this is important to know is that this is the point where it takes longer to go back than it does to just continue through. Maybe you've already spent more time than we were thinking at the beginning, but we're already at Step three. We now know that there is no reason that we need to go back because that's going to take even longer than it would to just continue and make it on or make it over to two point. Oh, so in this situation, if we knew our point of no return instead of someone calling off the deployment, we would say keep pushing forward were actually very close to finishing the deployment off . Now, at any point, if there's an error, we should roll back beginning no matter how long it's going to take. We don't want to deploy, you know it completely and totally broken piece of software. And also at each one of these steps, we need to make a decision of whether rollback is a better option. Let's say that we anticipated this one to take 30 minutes This one hour, 10 minutes, five minutes, maybe 15 minutes. Something like that. If we are going past this and this is already taken two hours, maybe we don't want to continue passed over here. Maybe we've already figured out that our plan was you know it Well, if this is taking four times as long as we anticipated, our plan isn't very good. So we should probably roll it back to the master and recreate our plan so that we don't end up spending, you know, eight hours on downtime when we're only anticipating just basically just around an hour, and so it's very important after every step to make sure that we need to if we need to roll back if rollback is a better option. But just to keep the idea of deployment rollback in mind will create better plans for deployment. A lot of people will just they won't even plan the deployment or they will come up with a plan. But they don't ever come up with a plan of how to go back. And going back is again the most important part of the planet process. It's to ensure that we don't break everything that we can start over, come over the new plan and do it again. So deployment rollback definitely keep that in mind when you're making your deployment plan . 37. 6-1 Testing Overview: let's move on to testing, which is basically the long for gotten step in the software cycle. And what I mean by this is that testing a lot of times is not done properly and a lot of times just not done at all. And this is due to a couple of different things. One of the main reasons for this is that testing is very difficult to find out exactly how your program works and to figure out what's wrong. And what's right is something that's difficult to do. And a lot of people like to just release it to the public and let the public be basically testers. And I mean, that is a way to do it. But you can get bad perceptions of your programs if you do that, especially video games. If video games are released with a ton of bugs. Ah, lot of times people will refund the game or they'll abandon the entire franchise because of the bugs. Having a solid testing strategy in place is very paramount to making sure that your product is released with the most quality that it can have, because even if we built everything about 90% if 10% of things break the program, or so the program down unnecessarily, or create errors that we have to go through. It's deemed basically a bad piece of work and people will move on. There's so much software out there that people will just move to the next one, so the testing process is very, very important. People also will abandon this step because of time crunches. If there's a due date. Testing is usually at the end of the software life cycle. That means that if the due dates coming up, people will basically skipped that last part. They'll skip the testing part before they actually release it. And again, that's how bugs are created. So both these things could contribute to testing. Being for gotten people don't usually do it, but it is extremely important. So testing is the process of finding errors. It's very, very simple. All we're trying to do is we're trying to see if our program does what we want our program to do. We contest basically everything we contest. The code itself, which is what a lot of testing is, is actually running the program, figuring out if it works, we contest the implementations. So going through different ways of basically how the data is being put together, how is, you know, data from the server being transferred over? Is it coming through basically with full integrity, meaning that if an update happens to the server is that happening on the local client? Are things working exactly how they should? We can't even test the documentation. We can look in the documentation even before we begin programming and weaken test whether the plan is something that is smart, whether it could be refined, whether it's going to work later on when we actually begin building it. And we can even test other testing. Because if we have a bad testing software, if we have software appear that even if we put an input, it's not giving the correct output, it's going the wrong direction or something like that. Well, that's that's pretty bad, because that means all over tests basically will have a good program. Well, it'll say it's bad, and we'll change it to a bad program so we can even create testing four other testing. And here's a neat little graph that I found provided by this college you I see right here. And this is sort of an idea about how testing might be done. So we can either do it in that sort of what we're gonna be. What's gonna be known as the waterfall method when we talk about methods or ways of developing software, where we go one step, then the next step, the next step, the next step. Or we could even do it like this. And here we are, their requirements step. And also the assistant specifications Remember, specifications and requirements. What? We can actually do an acceptance test plan, which means we're testing whether this is even something that we want to create. Then once we get into the specifications, we go to the design, remember talking about design, and then we can start discussing the system integration test plan. So what is the plan that we're going to use to test the acceptance? What's the plan we're going to use to test the integration? And then we're actually gonna decide, you know, with this how is this a proper use? Is this what we want to continue with? Then once we get to the detail design that we started looking at subsystem testing integration. So again, we're planning the actual integration tests, and so you can see that during this whole step were not only doing a little bit of testing , we're also doing a major amount of test planning. So we're planning what tests we should be implementing with each step that we go through. Then we have module and unit code tests. And that's of course, after the detail design laughter, we start building it. And then once we've built it, we can then go through the testing and this is against it of the waterfall method where we're just going step by step by step. Except these plans are then implemented down into the steps. So we start testing the subsystems than the larger systems, and then whether it actually does what we wanted to do, So we're gonna test basically, it's gonna go from, like, a bottom up method. So we're testing the very small, the cores, the lines of code, and then we're going to see if the the lines of code integrate well and actually start transferring data, how we intended them. And then finally, we're seeing Well, okay, we have this piece of software isn't doing what we set out for it to do. If we were, if we set out to create a word processor, we never checked the requirements again. And by the end of it, we have a spreadsheet manager. Well, I don't care how you know, few bugs it has. It doesn't actually accomplish the basically the problem that we set out to accomplish its something completely different. So we need to make sure that it's still accomplishing what we want to and then it gets released. We have a couple of key words throughout this. So the key words are going to be test out of test cases and then Oracle. So what these are are they are basically common terminology. The test data is the imports that are designed to test the system. So whenever we're testing for something, we have a set of inputs. We're trying something out, and that's gonna be the test data. Even the test that doesn't have to be like texts or numbers. It can be a sequence of steps that we do So, for example, over doing a financial transaction, it could be paying through PayPal. It could be paying through a credit card. That could be the input the way that we're going to be doing it. And then with that test data, we can then create test cases and ways in which we operate the system with the given data. And again, these two sort of go a little bit hand in hand. So if we're doing that financial thing, maybe the test case would be using PayPal, and the test data would be a known good and a known bad credit card. But these two together are what we're gonna be using these of the inputs and the way of using the inputs that we're going to be using to test the system. And then finally, we need to know, Is it a good outcome or a bad outcome? And that's what the Oracle is. It's sort of a unique terminology for computer science here in that we used the oracle for the set of good outcomes. So whenever we test something, we did have something to compare it to. We, for example, if we built a really complex calculator and it's supposed to be doing these math problems, maybe I don't know how these math problems work so I need a sheet of paper to tell me I should be able to enter in this math equation, and it should be able to give me this outcome. If I don't have that sheet of paper. Doesn't matter how much I put in. If I don't know what the expected outcome is, how do I compare it to see if it's actually good and these all sort of linked up in different ways. So usually we start off with something up here where it's like the test cases. So we're sort of we start off with. What are we going to test? What are the things that we need to test? And with this, we then end up with the inputs or the test data, and then we also have to come up with a sort of an expected output. So what is the output, the good output, and then Or let's make sure we put this as expected, A little sloppy, but that's expected output there. So what? The test data we're going to then run it under basically gonna put the software under test . We're actually going to do the test, and then with that, we're gonna get some output here, and then with this output, we're going to compare it to the expected output and what is expected out. But well, that's the oracle. So the Oracle is right here and then with the test data, we need to understand what was the input to see what the proper output was. So if we have the oracle of input output, so we have input output, and this is sort of the oracle here. This line of code should be this. This should be You know that, etcetera. We need the input data to see what the output danishes. So that's our test. That, as well goes to the oracle are expected. Output is the right side. Then we compare it with the output coming in. So the output comes in, we look at the comparison and we create the test. This is just sort of a little flow of how this should work. Here again, we have test cases which goes to test out and expected output. The test data is input into a test. So we actually run the test, it gets output. We compare it to the oracle to see if it's good and That's sort of the overview of testing , and now it's sort of dive into some more of the importance of testing in different ways we can do it. 38. 6-2 Testing Bugs: So let's go over testing in respect to bugs. Let's to actually discuss what a problem is. What are we looking for whenever we are testing and that is this idea of bugs. So bugs are basically a deviation from expected behaviour, and we have to kind of consider Is it a bug or a feature? Because if we don't have an idea of what the expected behavior is, how do we know if we're deviating from it? One person could look at the software and have an expectation of that software. And then they might think that the software is working perfectly fine. Well, someone else might have a different expectation of what that software should do. And when they click something, something unexpected to them happens. And therefore they think it's a bug. So we need to figure out if it's a bug or a feature. We need to figure out What is the software supposed to dio and is it deviating from that? And BookScan be both an air. So a basically a breakdown off the entire code, the part of the code that actually leads to the failure or, on this, the air terminology. Here it's not, You know, the specific level bug here. This is more I think they call them a defect. Is the like the technical term here. So bugs could be both a defect where an error is What? The common nomenclature of the common way of saying it is Onda deviation from expected behavior. So it could be both a system ending things that we click on it and the whole system crashes or just a slight deviation from expected behaviour. We put in three plus three, and it equals seven. It did some calculation because if we do three plus two, maybe equal six. So it's doing calculations. But there's a deviation in this expected behaviour. And it looks like maybe with this that there's ah plus one happening and off by one air somewhere in the code. But so that now if of course, we did like three plus three and we just got, you know, air and the whole program crashes that's also above those are both in the same category. So we need to look at again. What are we expecting? Is it deviating? Is it crashing? And then we could sort of categorize it and figure out how to fix it. And so we have this sort of specific terminology, this idea of a failure and air our fault. And this entire idea of a bug can again be sort of put into the category of a defect. So failure is the event by which the code deviates from the expected behavior. So the event meaning that the actual breakdown of the code so we have if we're writing a bug report, the failure is what we might put in the title of the Bug report Program crashes while doing this. That is the actual failure. The error is the part of the code that leads to the failure. So if we actually look in the code, the air, the code, let's say the lines of code here, this down here, maybe that is the error. That is the part where the code is actually deviating from expected. And then the fault is what the outcome Actually Waas. So we have an input and this is the expected output. The expected output is over here, but the actual what actually happened over here is the fault. This is the change. What actually ended up happening and that is what we might put in default. So we expected a We expected a but we got B. And so that is where the fault comes in. And so testing could be used to show the presence of bugs, but never to ensure the absence of them. That's very important is that we could test the program 1000 different ways. But what's never going to get to the point where we can ensure the absence of them? And this is actually sort of, Ah, little I need to put like a little ass tricks here because you can actually ensure the absence of them. But it's very, very complicated, and you have to mathematically prove every line of code, meaning you have to come up with equations that prove that each method each system cannot have errors in it. And this is extremely costly and usually only used in something like maybe missiles, defense systems, NASA. So, like a space exploration or high security things like government entities. And even then it isn't typically insured completely. It's like just, you know, 99% insured it very, very hard to ensure the absence of them on and again remember to say they ensure the absence we're talking about. We could get most the bugs out of it, but we're saying that we could never, you know, guarantee 100% of bugs have been checked Unless we do that sort of mathematical proof, which is almost impossible. So we wanted to talk about that. So just keep that in mind is that we can test it. We confined the bugs, but we're never gonna be able to say that. Oh, because all these test cases cases work. There are no more bugs in our program. We can never really get to that point. And here's just a sort of an interesting little graph here of the life cycle of a bug, and you can see that it's a little bit of a complex process. We sort of get a bug that comes in and it comes in an unconfirmed state, and then with this, we have to categorize it. So we we have these steps, we first assign it to someone to do it. Maybe you don't shit changes. It goes in this sort of fashion. And then we have to, you know, figure out the bug. We're gonna then put it into a category of, you know, whenever we're working on the bug. Was it fixed? Was it a duplicate as has already been reported? Maybe it's a won't fix, which means that it's not actually that important, and it take way too much time. There's there's more pressing matters at end works for me. This one is actually pretty typical. If you don't have whatever people report bugs, they need a very specific step by step to get to that bug. Otherwise, ah, programmer might look at it. Go well. I did this and it works perfectly fine. They didn't understand that all of these additional steps were used, and therefore, it sort of comes back as a work for me. You can't fix something you don't actually see breaking. So a lot of times that will happen with a bug. Invalid means maybe it's just not a bug. Maybe it's a feature. Maybe it's something that should be it. And we need to communicate with the client better about how the program works, remind and then later, that sort of putting it on the back burner. We'll fix it later on sort things, and there's all of these different flows in here off whether the bug was resolved. And finally, when it gets, you know, finished, we close it off and we wait for more bugs to come in. And this is a very typical bug testing or a bug life cycle. The bug comes in, we go through all this stuff. At some point, it's either going to be confirmed or basically put on the back burner. Um, or my dad is gonna be fixed or put on the backburner at some point and maybe we'll fix it later. Maybe we won't. But bugs are important to understand. They are the basis of what testing is. We're trying to find them. We're trying to figure out how to stop them, and we're trying to make sure that the user never finds them that we do first. 39. 6-3 Verification and Validation: an important discussion when we're talking about testing is this idea of verification and validation. So with verification and validation, we have these two words that sound kind of similar, and they both are looking at sort of similar things, and that's why they get confused a lot. So let's go through verification validation and make sure that we're all on the same page here. So verification is are we building the thing right? And you'll notice that validation is Are we building the right thing? Just ah, little switch of the word back here, but it's very, very distinct difference. So are we building the thing right? Are we building the software correctly and what we compare when we're talking about this? Well, whenever we're talking about verification we're talking about does the software work compared to the given specifications? We were given a set of instructions on what we should build. Does it work compared to that set of things that we should build Teoh? And so an example is this fast vacation that software will calculate next monthly payment using form. You can see this is a little bit ambiguous. So what we do is we take some creative liberty. Maybe we create a front and form we put in, you know, maybe something like this, something like this and a little button down here. You click the button and then maybe it sends it in an email. Maybe that's how this one works. So it sends it in like this. Email to, ah, back in server somewhere. And so this does it work? Does it work compared to this specifications? Yeah, it works. It's It's perfectly fine. It's verified. We're doing the correct thing compared to the given specifications. Now here's the problem. Is validation is Are we building the right thing? Are we building what the user actually needs? Are we building what the user wants to use? And there's a lot of times a breakdown in communication is that this was not specific enough. So we built it thinking we know what the usual needs or wants, and therefore the software is verified. It's working exactly how they told us that would work, but it's not valid. It's not something that the user actually needs at this given moment. They didn't want this type of form. They wanted maybe, ah, front end sort of Java script form. They wanted, you know, something we could put in right here. Click a button and then it will go to another page. And maybe it will show you something like a graph, or it'll show you you know, your monthly payment. Or maybe it's all on the same page here, and you'll notice that this does exactly the same thing as the specifications as well. It's calculates the neck monthly payment using a form, but they're two different implementations. So even though both of these are verified, they're not both validated. And this validation validation is the hard. Basically, the area that's the hardest to accomplish is because a lot of times we don't know what the user wants, and the user might not even know what the user wants. And therefore it's very difficult to figure out what the user wants and to build the right software. Because us, as software engineers us as a company designing solutions for problems. We are trying to build a solution for the problem, exactly what I just said. However, if the problem isn't defined correctly, we could be building a solution for a different problem, and I'm going to say that again. We could be building a solution for a different problem and therefore the user does no need for that because they don't have that problem. So we have Ah problem, eh? And a problem be we might be building a solution for problem A. And if a company comes along with, you know the problem A. We got ourselves a solution. Our program right here is the solution for a problem. A. But what the user actually wants, what the users paying for is a solution. The problem be so even though we built a solution that works, it solves a problem. It's not. It is not the solution to the actual problem at hand, and therefore it's not a valid solution. So whenever we're talking about verification and validation, we need to just understand that verification. Are we building the thing right with the given specifications? Are we building it right and then validation? Are we building the right thing are rebuilding the thing that the user that the client wants us to build 40. 6-4 Unit Testing: So one of the ways that we test things is we use this idea called unit testing. And so unit testing is the idea of testing to focus on the smallest unit of a software. And basically, what this means is we're tryingto isolate. We're tryingto isolate different areas over and over and over and test the entire program like that. So the program is essentially going to be composed. Ah, whole bunch of small modules all communicating with each other in different ways and that those small modules will probably packaged in the larger modules and so on and so on. But what we want to dio is we want to test the smallest possible. So we're trying to test these individual modules down here, and the reason we're doing that is because if we contest all of these on say that they all are working exactly how we want them to be working. Well, in the end, we can say that the entire thing should be working. How we want it to be Now, of course, this is dependent on if our software architecture is good, because even if all the modules work, if our architecture as a whole was bad, then they're still going to be bugs, and that's where we get into something like integration, testing or architecture testing. But the 1st 1 we're talking about is this idea of unit testing, and what we do with unit testing is again we try to isolate. So if we test this, let's let's say that we have a module here, here, here. If we test this one right here and they are all communicating like so well, what happens if there's a bug over here? It might propagate its way into this module, and we don't want that. So with unit testing, we try to isolate. So we're gonna be doing is we're going to be building basically dummy values and all of these dummy values that we know work properly that we know are working perfect. So it will put those inbred. So instead of just having that this module here integrated into everything else, what we do is we just put the module into an isolated environment, and we actually have to create tests cases. We have to create an integration that we know works perfectly fine. Maybe it's not as smart, but it does exactly what this thing needs and from that from building these ideas, these air drivers and Stubbs and we'll talk about that more incremental testing. But these will allow us to isolate this. And once we ice like this, we can test it flawlessly. Once we know it works, then we move on to the next one. So we move on to maybe, for example, this one. So we, you know, actually be testing this one, and then this one will be created as a a stub or with incremental testing. Maybe we keep this one because we know it works. So it's fine to use from now on, but anyway, that sort of gets a little bit ahead of ourselves. All we need to don't know is that the idea of unit testing unit testing is to test the smallest possible part of the software. We're trying to isolate that software. We don't want to accidentally test an entire subsystem or module. We need to make sure it's isolated so we don't have these cascading bugs that we think are potentially in here. Isolation. It is important 41. 6-5 Integration Testing : So we've talked about units and unit testing, but the next level of that is this idea of integration testing. So with unit testing, we were testing the very small modules, the smallest pieces of software, and maybe we work to 100% of them. We worked 100% of all modules, and they're all working. However, that doesn't mean we are absent of bugs because the program could still have been built wrong. The communication could still not be working properly. There could be, for example, maybe there's 100 modules in here. And maybe there's 50 modules in here. And these two subsystems talked to something that has 60 modules and so on and so forth. And maybe when all these air communicating in this large architecture with the databases over here and maybe with a front in server or something over here, there's still bugs that arise. And so with that, we need to actually combine them. We've tested everything in isolation, it always working fine in isolation. But now we need to start combining them together in this idea of integration, testing and with integration testing, we actually begin doing this sort of incremental or non incremental. So we'll talk about incremental in the next lecture, cause that's actually a little bit more difficult. This idea of non incremental is just sort of brute force testing the entire thing. So what? Not incremental. Maybe we have again that those sort of large subsystem modules like this and then maybe like a big controller, something class that calls these in these calls little ones and so on. It's a little bit of a complicated architecture, with integration testing non incremental. We kind of just test the whole thing. We just run through giant tests, and this is actually the most common testing that people dio is. Whenever we build our product, we just test the entire product. We see what's wrong with the entire thing. So for building an app, we're not testing. Individual pages were just testing the whole thing as a whole. So we downloaded onto our phone and we just run through it and do common use cases. We do common things on the app, and we see do these common things break anything to these common things. Is there something I can do to break it? And that again, that's like this non incremental integration testing we're doing. We're testing the entire program as a whole. However, that doesn't usually show us some of the areas because maybe maybe we do something and we get an error like it. This module over here. Well, how do we know that that wasn't propagated by this and air over here and maybe an era back here which propagates to an error over here and again? This this would happen if we have, like, tight coupling are low cohesion. But still, these things happen. And so if we're doing this entire integration testing, of course, with this now we can actually, we do have a little bit of advantage. We have a bug, we can identify the bug. However, it's a lot harder to fix the but because all we have is the inverse. It'll all we have is the the basically default what actually happened here. But what we need is we need to test where it happened. And that's where this sort of incremental testing will come into play. It allows us to build on top of each other and then c o. Whenever we add this module, we start getting errors up here or we start getting errors. You know, up here from an air down here, it allows the pinpoint it just a little bit better. So the next lecture will be talking about that, which is gonna be the incremental testing. 42. 6-6 Incremental Testing: let's go over the first idea of testing, and that's gonna be this idea of incremental testing. So incremental testing is testing. Where you create a module, you do some tests, you create another module, you do some more tests, and this word create is used loosely. So weaken Do testing in two different ways and we'll talk about this a little bit more. We get to software models, and that is we can either build a module and then test build and then test. Or maybe we can build the whole system. And then with this testing, we grab a module than test grab a module and then test. So when I say create, I either mean we're building it from scratch or were grabbing it out of the program we've already developed, and we're testing them a little bit at a time. So what the incremental model? What we have is we have these steps. So, for example, we might grab a module, maybe the top level module, the starting module, and then what we do is we test it, see if it works, see if it works, how we want it to work, see if it's doing what it needs to be doing. If it does, then we moved to the next step. Maybe it connects in these two areas. So then we add in another wa jal and another module and then do some more tests, make sure all of these air working together properly added another module. Maybe there's one right here that communicates like this. So then we'll test these and weaken, like, just do little, uh, little check marks to say where we been. So we can say here, here and here. So when we do two more tests now, we've checked here and here and so on and so on until we have basically tested the entire program and you can see that this is actually a pretty decent way of doing it just because we are testing it in this way in which we're slowly adding more and more in and testing functionalities. The problem with this is it's very hard to accomplish properly because maybe your software wasn't built, so that is completely and totally modular. Maybe there's a little bit too much coupling in it. Maybe there's not enough cohesion. And therefore, whatever you increment a step, maybe it's like you start off with 10% and then you increment one step and it's suddenly up to, you know, 40% of the code and one more step. And now you're up to, like, 95% of the code and that that happens a lot, which is why this sometimes isn't as practical, but it is very important this idea. Another shortfall of this is, for example, if we just wanted to test the relationship between these two units will by the time we get to this over here, what we have is we're sort of testing the entire system. Plus this. So in this situation, we might even have to add another step where we do the incremental testing. And then we do like a little bit of a unit test here where we test just a specific area to see if each one of these works and and that if this works and then if these work So it's like a a ton of different ways to do this, and that's why it makes it just a little bit difficult. Now. A couple of different ideas for doing a sort of incremental testing is this idea of top down testing. So with top down testing, what we have is we have this idea of basically we're testing the top level, and then we move down after each top levels completed, and we're gonna need a learning new terminology here. And that's this idea of a stub. And the stub is a template of the model that will be implemented, typically returned the hard coded values. So what we mean by this? Let's say we're testing this module up here and will say that this is, for example, level one. So we're testing the very top module now. The thing is, we're not testing anything beneath that. We're just trying to test this module. Therefore, what we create is these ideas of Stubbs down here. So these this next layer is gonna be a stuff. Everything in red will be a stub here, and what a stub does is it's just a template of the model that will be implemented. So instead of having all these methods that are fully realized, we might have the ability to call the function. So this is where you need planning as well, because you're gonna have to know exactly what method calls. What functions? What subsystems are in basically entangled in each of these little sub components. So, for example, over here, maybe this is, Ah, clock or something. So we might have a get our Maybe we'll have a get minute. Maybe we'll have even, like, I don't know, maybe, Like what's tomorrow? Get tomorrow. Just add a little get there, get tomorrow. Maybe we have all these functions, but we haven't actually implemented in them then yet, but want to see if they'll work in relation to this. So what we do is we create this basically this stub where we don't actually fill in any of the code beneath it. We create all the method calls, but we don't implement any. The method calls. All we do is we return some hard coded values or something that, you know, makes it so that we know it actually called that function and, you know, something like that. It might just be like a console thought Lawgiver working in something like JavaScript where we can say tomorrow it'll just return a random date in there. And so that way we know if it returns this exact date, we've accessed it and we've gotten the information properly and this helps because maybe it calls down here and then it calls back up and we do something with the data. So we need to make sure that it's this control flow is working. We need to make sure that if we call our method up here, it goes down, it grabs the proper method, and then it comes back up and everything is sort of flowing along nicely. And that's where it why you need these stubs. And again, this can either be a way of developing or a way of testing. So maybe with our development, we're doing sort of a top down development as well. So we build level one and then the stubs that connect to it. And then after this is complete, then we actually build out each one of these stubs. We implement them, and then we create a new layer of stubs that we have to use. So you know, more Stubbs down here. And this is also helpful if, for example, we have a database that we're trying that we're gonna use but the databases and implemented yet so we can actually create this stub that instead of calling the database instead of calling it, it just again returns that concert out log. So maybe we say something like Get user So we try a get user command and typically that would be the user will be stored in the database. But in this situation, all we do is we just return user information, fake user information and weaken test it without actually developing our database right now and then. Of course, when we get to the point of developing the database that will actually implement this and we'll keep moving from there, you can see there's a little bit of a nice organization here. There's, ah, flow. We have these objectives we can accomplish. We start at level one. Then we moved to level two. Then we moved to level three and we keep going and so on, and so on level right there. And that is basically the way that we do top down testing. So we started the top and we keep moving down The other way that we could do is this idea of bottom up testing, which is just basically the reverse here and what we need for this it was. We need drivers. So remember, back here we already had this module right here, which is calling command. It has the variables initialized. It has everything that we need for these to operate down here cause top down control flow is going top to bottom. So it's passing in certain variables, passing in certain information. This then executes, and then it comes back up. And this is controlling that execution flow Well, with bottom up testing, how do we test, for example? Let's say we have these bottom three down here. How do we test these? If we wanted to start at the bottom and maybe we want to start at the bottom because, for example, maybe the top is like the server, and maybe the bottom is like the front end, and we want to make sure the front end work before we actually get to the servers. So in this situation, we need to start at the bottom, will you to work our way up. And so what we do is we test these modules and we actually have these things up here called drivers. So we create a driver which is essentially the same thing as a stub except just the opposite side of the coin Here, instead of it being a template that has model controls, a template that has, you know, functions at my return. It's a template that has execution controls. So up here we might have functions that are going to do that aren't fully implemented. But that call the right other functions down here. So we might have, you know, a get time up here. And what this is going to do is it is going to make the appropriate calls. Maybe this again. Is that same clock one here. So the get time is gonna make a call to, for example, let's say it's gonna make a call to get our and then get minute and then maybe a couple of other things, and then it's supposed to combine them in the maybe returning even farther up. But in this situation, we now have this driver and weaken test whether the commands coming in are returning appropriately. And so what we do is we create this little driver would make sure that all of the variables up here, our initial A's, maybe it needs the past. In the time zone, maybe the time zone or something. It needs to pass it. So we go ahead and we create a variable called Time Zone and we initialize it to just something. So let's go with Eastern Standard Time, which is usually a previous E T is his United States Eastern standard time. So we set the time zone. Of course, if this was a real program, this would be maybe calling to a database to see what the user is or something. But in this situation, we're just creating a driver. So we hard code all the variables, we hard code some of the methods in here. And then now we can test to see if when when calls come in, do the appropriate data get you Don't return here. And then this one where we hard coded the concert outlaw, you know, tomorrow is a time maybe we don't. Maybe we say it's like February 19th of 2012 or something where we actually hard cut in this one because we're testing the module, the bottom, and it's going to return the actual get our and the actual get minute and the actual get tomorrow. It'll do those things, So all we need to do is we need to have something to call it to check, to make sure that those things are working. And then, of course, once we finish that out, we go ahead and we actually initialize this and we keep moving up the chain until we've tested everything. And so that is really incremental testing. In a nutshell, it's This idea of starting somewhere doesn't matter if its bottom top there's different other ways agreement and then just move to the next one. Once we're done, move to the next hormones were done. Keep checking them off and then keep incremental until you have tested every module in the program. 43. 6-7 Back to Back Testing: another way of testing is this idea of back to back testing. So this is something you do once the program is built or it could be a part of that idea of incremental testing. So we build one section and then we do another section and in no section solely incremental off of one another and saying what? Testing again? It doesn't have to be a build. It could just be. We're testing one section and we go toe Ah, larger section a larger section. But with this idea of back to back testing, what we're doing here is we're comparing a known good to a new version. So what that means is, let's say that we have a program right here or we have input at the top. So we have this input going into our program, and over on the left side is version one. This is the version that was before we made changes. So we run the input in diversion one, and then we get in output. So we get some sort of output right here. Now we can compare that to an oracle or some way of seeing if it's good or not, and making sure that this is okay. Once we know that all the output from this is OK, then we can do back to back testing because now what we dio is we actually create a new version. So we go in, maybe we add new things. Maybe we actually develop a new part of that software. Well, once we do that, we then have a version two. And so what we do is we take this same input here, the same set of numbers or sequences or characters or actions, and we put that in diversion to and get the exact same output right here. So we're gonna see now is, let's say, the left side, we're gonna have an outputs under, like 2357 and the right side will have 2357 And it's not. What we do is we do this thing called a difference report or we just look at the differences. So we see, does everything match up? And if everything matches up that we know that the program still works, we know that this new thing didn't break old things. This is not for testing new functionality. So we're still gonna have to test a whole other part of new functionalities, a new function, output. And we're gonna have to compare something a new oracle to test that. But with old stuff, we now have this way of making sure that we're not breaking things as we nuke add new things. So with this, we could actually do this, This thing where we compare the old one and then maybe we have a version three. So when we have version three over here, we put the input into there, and that compares against the new function output. So we know version to work this out. Put now we know version three works with that. We might even want to compare it to that as well. Do the same tests and we can keep going farther and farther, and it allows us to save a little bit of time because again, we don't have to redo all these tests. We just have to run the exact same input and make sure that everything is still the same because we've already verified that this matches the oracle. So we've already verified that this is good. So that means this on this side should be good as well. And of course, if you get a difference here. So let's say, for example, instead of a seven down here, we get something like, I don't know, in eight with that situation were then going to basically have this situation where we can now see which tests failed. So over here we can. Now, let's change the color here. And maybe we were right a little program to tell us this. But there's gonna be like an X ray here. We know that this last test failed. So now we know there's been a change with ever, what with whatever this test is. So, for example, if this is, you know, calculating a some Or maybe this is how many parts like how many things end up in an array or some in result here. We know that between all of this, it's working fine. But this specific area is breaking, so we could go in our code and fix it and try to get this back in line. But back to back testing is a great iterative testing that allows you to save some time and to quickly compare to make sure that you're not breaking old things with your new things 44. 6-8 Who Should Test : Whenever we talk about testing, we often need to understand who should test it. If we're coming over the testing plan, we need to understand which group of people should be testing our software. So the 1st 1 is the developer themselves. So the developer is, you know, the one who built the system. They understand the system, they can do these technical tests. And what I mean by that is they understand. For example, if there's a module here communicating with a module there, they understand, first of all, that these are two separate modules. They understand that protect. Maybe particularly, there's a array over here and like a linked list over here. And these are just some technical terms. They understand the implementation. So they might be trying to do tests that specifically break those implementations where a normal user might be just typing stuff in there, trying to, you know, type of really long things in or type really short things in or change it from number, the letters or something like that to break their specific implementation so they can do those sort of technical tests. Now the downside is is they may treat the testing lightly. This is sort of their baby. This is what they've developed. This is what they spent a lot of their time creating, so they don't want it to be bad. They don't want it to look bad. Data themselves don't want toe look bad. So the developer themselves are probably going to test it a little bit lighter than people might. You know, other people might want them to test it. And the developers are motivated by different things. They're motivated by a looking good meeting deadlines and building the software developer themselves aren't going to try to keep coming up with bugs. If they have a deadline looming, they just want to push it out and say, Hey, I finished it. And so their motivation again makes him not the best testers in the world. Now they do know the code which causes the problems. So if they find bugs, they're much more likely to fix them in a timely manner than if you have these two. Because they're going to have to basically write bug reports and go through the entire steps of how to get there, and then the developer will have to go through that bug report and they're gonna have to find the code that actually creates the bug. But over here they see the bug that like Oh, yeah, that's probably in this file doing this. The next step or the next layer is the tester. A tester is a professional, a professional who is specifically trained in breaking programs. So what they're gonna do is they're gonna learn the system, which again is sort of a benefit, because as they learn it, they might be confused in certain areas, which will help in general quality. Maybe something needs to be refined, and maybe it means to be made just a little bit better. But they're gonna try to learn the system, and then they're going to try to test everything. They're not gonna just test technical things. They're going to test as much as they can, and they're gonna try to break the program at all costs. The tester is motivated slightly differently. They're motivated by qualities with maybe this one over here is deadline or maybe even ego or, you know, skill. They're motivated by trying to create really good programs, but not entirely on the quality they might be. You know well looming deadline and try to push it out well, The tester over here is completely motivated on quality. What they want to do is they want to make sure that there are no bugs, because if you pass a piece of software onto the tester, the tester now holds responsibility. If there are bugs, the developer has developed it. They do the initial Dev. But this guy is import is ready for quality, so he is held responsible for quality. If there's a bug, it comes back to him or her, and therefore they're going to try to break everything. They want to find every single bug in this program, so that when it gets pushed out, there aren't a lot of bugs at all, and they will look a little bit better, and they will be basically doing good at their job. So the tester is very important as well as a developer, and finally, a lot of companies will actually use this. Nowadays, they'll release a beta version or a demo version, and they will release it to the public for a user test. So user test is a lot of times you'll see games do this Maybe, like they have, like, beta weekends or something. They're testing. The servers are testing the gameplay. They're making sure everything's optimize. And the best way to do that is to release it to a 1,000,000 people and see how do people use it? What configuration of hardware on their computer breaks it? What? You know, what are they doing that we didn't anticipate? So that's very important as well. And again, they must learn the system Azad go through, which again, is pretty much a benefit they But they know how they will use the system. So the user is using the system. That's what the whole system was designed for is for a user to use it so they know how that's gonna work. And they're going to just try to use it. They're not gonna try to break it or go really hard on it. They're just gonna try to use it. And if it breaks, then they're gonna issue a bug report. The bad end on this is the user isn't really motivated by reporting a bug, so they're just motivated by using the software. So using the software and if we're creating a for example. Ah, piece of software for a business. Of course, they're probably gonna report the bugs was because they want the best piece of software possible. But if we're creating, like, a marketable software, so you know, a Microsoft Word or a video game or an online application? A lot of times user is not going to report bugs source. They're not going to go to the steps. The, you know, 15 20 minutes it might take to write an actual, really good bug report. And because of this, we're not going to get a lot of bug reports from them. So we're gonna have to do some, like, anonymous data keeping or something else to get information. So even though this is a really good testing vector, it's very hard for us actually get usable information off it. So whenever we're creating our plan, we need to understand all of this. We don't understand the motivations behind every single one. We need to understand where we're going to get the most quality for the most amount of time we spent. And we just need to understand that different testers we're gonna test it differently, and they're going to find bugs differently, and understanding all of this together again will help us create a better test plan. 45. 6-9 Automatic vs Manual Testing: our next area of testing strategies that we want to look at is his idea and this distinction between manual and automatic testing. And what's the importance of either? Why would we use either so manual testing is just that it's manually done. So if I, for example, need to test a piece of code, we have this piece of code, and I need to see if it works on different Web browsers. Well, all I do is I literally go, and I opened it up in each Web browser, and I visually check it to see if it looks good. If it does, then I give the check mark on each side, and then I put it into some sort of report and send it off to whoever needs toe have that report, whoever needs sign it or say that, Yep, these things work, and that's manual testing, and you'll see that there's something sort of easy about this in the sense that we don't have to design anything for it. We just do. So we just figure out what needs to be done, and we just immediately do it. So there's no real overhead to this. However, what if we needed to test a server for 15 million server calls at the same time, let's say the server was guaranteed toe work at 15 million server calls. How do we figure out if that 15 million will work or not work? That's going to be pretty hard for us manually to dio. And maybe we'll do something like a beta test where we actually allow real users to use it . That's a smart way of doing it. But an even smarter way of doing it is to automatically test it's, or users don't have to be the test cases and automatically test it. It takes time and it takes effort, and we actually get sort of like this graph going on here. So this is the effort required in the testing phase. So it's sort of like this reverse exponential graph right here, and this is the effort required in the dev phase for testing. So what this means is this is saying that if we don't spend any time at all in the dealt development face, so the red is Dev or ah, let's do the terminology. We've been using the implementation phase and their implementation and then we'll say black . Here is the testing phase. So if we don't spend any time in development at all, you'll notice that there is an extremely high amount of time we're going to spending in the testing phase where if we spend just a little bit of time planning and developing some test cases and actually divine ing the test software because if we do automatic testing, that means we have to actually design more software. And we're goingto test that software as well. Grants come up with design documents. We're gonna have to come up with ways that it's gonna work and architecture and stuff like that. But if we spend that time in the implementation phase and the design phase and everything to get that tow work, that we can reduce the test time by ah whole lot. So this is the testing phase, and the problem is, a lot of companies won't spend the time to develop the software until they get into the testing phase. And this means that as we're developing the software, we don't even think about testing, and then we actually have to go back, break apart the software again, and figure out how to put proper test cases in there. Where if we had just put test cases as we worked, we would have saved a whole lot time a lot of time later on. And what is is usually end up creating. Well, whatever we get to the testing phase and we've already done this, we've already not spend any time doing it. And we're looking at this amount of time to implement proper testing software. Well, what we dio is we skip the testing phase or we do a really small set of manual tests and say, Yup, looks good and we push the software out and that happens more often than not. So this is one of the biggest breakdowns in the software development process is not developing proper testing software throughout the process. If you can see all we need to dio and developed just a little bit of testing as we work and throughout the implementation process, and we can actually save ourselves a whole bunch of time. And of course, this is an exact graph. But if I was looking at this as an exact graph, I would look and say, Well, why don't we look to develop right around here because that's going to give us the minimum amount of effort and will give us the best chance. You know, this graph course wouldn't stop here. Would probably do something like this where it just lows. Over time, we could delete this line right there, but yes, overall, though you can see the point here is that we would look for this idea of what we don't want to spend all of this extra time in implementation. It's not gonna give us a whole lot of benefit later on, but there it is very important to at least spend this amount of time in the implementation phase because it will save us money and it'll increase our quality over time. So the idea of manual vs automatic testing is important here and outlaw off. I'm gonna really drill home. How these connect is that a lot of times the automatic testing is done in the implementation face because we have to design software for it is over designing automatic tests. We need to spend that time up front. It's going to have a lot of upfront costs. So with manual testing, it's quick. It's gonna be straight straight away. We could just jump in and do it. There's no planning required with automatic testing, though. There is a whole bunch of planning beforehand. We have to develop different software with the move through it. We have to verify it and then we can actually use it. And that takes up front cost upfront time. However, in the long run, it saves us time. So understanding the distinction between those an understanding that it's important to basically create software, uh, or create testing software is something that is important when you're creating your strategy. 46. 6-10 Black and White Box Testing: with testing. There's also this idea of black box and white box testing. And so, with this lecture, I'm It's going to be more of a top sort of view of this. This gets very technical really fast whenever you talk about these things, especially with black box testing, because you actually go into sort of mathematical proofs and you have to understand things like state machines and cause effect, graphing and basically mathematical nomenclature and stuff like that. And that's where you sort of like with a computer science degree. You might actually understand some of this stuff or if you're really into Q A, you learn more about this, but I want to just go over a little bit of top down with some maybe some key words if you want to look up additional things and yet just get you exposed to it. So the black box testing what we have is we have inputs on left side, so we put it in, put it goes into a black box. So it's a function that we don't know how it works. All we know is that it's supposed to do something, and then we get an output over here and with black box. It means again that we don't understand the interior of this. And this A lot of times is what testers are is they're gonna come in and they don't understand the nitty gritty of the inside. So there, black box testing. Now there can be white box testers as well. They're just going to spend some time learning the interiors of the code. And that's we're gonna talk about. Over here is white box testing, but with black box testing, we have an input. We have an output. We have put in different input. We get different output and we're just checking to see we have this again, this oracle where we have this input on the left, you know, we have some sort of input, and it's supposed to be giving different output on the right side. And so what we're trying to do is return to see, does it work? If we'd combine different things, is it still working? And so we have things like boundary values, and that's where we try to input high and low ranges. And if these past is assumed, everything else passes. So if we can put you know, a 1,000,000,000 0 into an equation or a 1,000,000,001. We assume that everything between one and a 1,000,000,000 probably works as well. Because what function or what equation wouldn't it work with? That's that very weird test case where numbers in between here wouldn't work. But the edges do work. So we do try that sort of boundary test with this where we try to basically break it by going into corner cases. How large the number can we input? How small the number Comey input And does it still work? Cause effect, graphing. This is where we test different causes to make sure different effects happen. And this gets again very, very complex or basically like creating these graphs of cause and effect values, and you're trying to see what the end effect is. So you're trying different causes which are just the input, and you're trying to see the same similar effects with pair wise Testing is when we have multiple parameters being tested and we're trying to check all conditions here. So we have, you know, ah, form or something. And there's 28 different ways to say yes and no and different values and stuff. And so we're trying to test by putting in those different pairs to see if the output is what we expected. The output and then state Bates based testing is checking input to check state changes and state changes is if we know state machines. We basically it's these machines that the program has these different states, and certain points change basically the state of the machine here. So, for example, ah, lot of times is there tested with zeros and ones. So maybe a zero goes to hear Ah, one goes here, a zero goes to here and then maybe there's a loop on one here and so on. And it's just sort of this big control flow here of different states. So we're trying to do is we're trying to test to make sure that our state machine that we draw is accurate within here. That if we put these inputs and outputs in here, that is going to get us from state one to state to to state three to state four to state 586 or however many states endo being in our program here. So that's the state based testing with white box testing. What we have is we have the ability to see inside of it. We know the control flow, We know the variables, we know all the data within it. And we're actually checking that in this testing. And so with Black Box were testing the general use of the program or testing that if we use it as normal users, it's going to work with white box. We're testing a little bit more technical. We're making sure that there's no memory leaks were making sure that the variables air used right. We're making sure data flow is correct. And with white box testing we do to really main things here is that's the idea of control flow testing and then data flow. Testing and control flow is we set of test cases, which cover all branch conditions in different statements. So if we have this big FL statement or even select Blood said we have, it starts here and we have NFL statement, and then this one has it fell statements, and this goes down here and then it goes like that goes over here and like so it's kind of hard to test all of this. So what we're trying to do is we're gonna create probably an automatic solution that's going to toggle between these and try to test each flow at least once. So it's going to go down. And it's going to try to test and make sure that it goes through each flow at least one time so that everything has been touched once. And then that we know that the expected output is correct on every single flow. That's control flow testing, data flow testing is gonna cover. All variables were designing test cases to cover the different variable death declarations and their uses to make sure that at no point does a variable break. Or, for example, if we develop developed in certain type strict languages where, for example, a variable has to be an integer Ah, lot of times, if we don't touch that variable, then a new air won't pop up until we touch it and something wrong goes wrong. So, for example, at some point, if we're trying to put a string, which again is a computer science term for just like just like text here? So it's just a string of characters together a string. If we try to put a string into their, it might blow the whole program up and the whole thing will crash. Well, if we don't test all the variables and make sure that all of the control flows and all that touches of those variables never breaks it, that we don't know about that bug until someone actually does it. And it crashes a program and gives them bad user experience. So that's what we do with data flow. Testing is we know the interiors. We're gonna check all those little points of data and make sure that they're all working and being set properly. So that is a black box and white box testing again. Sort of. This was a top down view of it just to do you understand some of the terminology If you're more interested in this, definitely look up some more information online and this stuff it gets pretty complicated, but it is very interest 47. 6-11 The problem with testing: So let's go over some of the problems with testing or these air just sort of things to keep in mind when you're testing so that you don't spend undo time or stress on the testing phase. And the 1st 1 is that exhaustive testing is impossible. What this means is that we have this curve right here of time spent and bugs that we might accomplish, and over time this curve gets less and less and less. Meaning that may be 100% is right here, so maybe we can get, you know, 95% of bugs definitely knocked out. But the longer the more bugs we find, the stronger and stronger amount of work and time we have to spend to get those next percentage of bugs gone. And even with this will never know if the program is bug free. It's almost impossible to design a test case for every single possible use case with your program, especially if it's something large. Imagine Windows or Mac OS trying to make sure that it was 100% bug free. It would cost trillions of dollars and years and years and years of time by the time they actually developed one of those that they could consider maybe 99.9% bug free. The technology would have moved on, and the product would be useless. So we have to keep that in mind is that we don't need to make sure that it's 100% bug free . We just need to make sure that it's generally bug free. And this is also something important. Is that this idea that as the number of DIF detected defects increases, so does the probability of more bugs. Imagine if you had to programs both doing the exact same thing. You run the same test cases on both of these programs. So you have program A and you have program be and Program A comes back with 10 bugs, and you might think, Oh, that's a lot. There's something's wrong with Program A. You run the same program or the same test case on B and has 150 bugs. Now, just on these exact same test cases, which one of these do you think might have even more problems later on? And it's probably gonna be be because amount of bugs that we detect gives us the overall quality of the code. And so if we detect more and more bugs, there's the probability that the whole code base is probably not written very well. And there's probably Mawr and more bugs in there. So with this, with the 10 bugs 1st 150 bugs were probably gonna find over the course of testing this, you know, way less bugs than we do with a course of testing this. And again, this is a probability. So this isn't guaranteed. Maybe this ends up having 500. This one stays at 1 50 It's never a guarantee thing, but it's a general sort of notion that we need to think of is if we begin our testing phase on, we start looking at the code, and there is a bug after bug after bug after bug that we might need to start looking at the architecture of the app, and something might be terribly wrong with the code base. And we're gonna be dealing with bugs with this forever. We need to make decisions on what to do about that. So those were just starting to the very important things that understand whenever we're talking about tests they got. This one is, of course, the most important. Exhaustive testing is impossible. We cannot guarantee the program will not have bugs. We just need to try to get as many of them out as possible in the most efficient way possible. Our company is still trying to make money, so we're still trying to release this product on time. Adding eight weeks to the products deadline does not usually result in a favorable outcome for, you know, the employees. So we don't want to add, You know, two months did it to the deaf. Time to test that last 2% of bugs. We don't want to do that. That's probably not going to be the best decision. At some point, we have to make the efficiency call. We have to understand that we want to do good testing, but we don't want to try to guarantee their no bucks. It's just wasted effort 48. Project Overview: Now that you have a good understanding of the processes and the ways to design software, the project is gonna be a sort of fun, open ended project. Were you just going to design some piece of software? So I've given you a prompt down here that you can use or you could create your own. Essentially, all I want you to do in the project is to come up with some sort of requirements and specifications about what you want to build, then try to come with an architecture and design of that project and maybe even look into how you might deploy it and stuff like that. But overall, I just want you to come with the idea and then how you might come up with the requirements and specifications. Be creative with it. Look up different things. Try to figure out the best way of doing it. Try to see if you wanted to add a feature later on what additional requirements specifications would you need. And that's really just the project is just come up with a project, a fake project and see how you might build this piece of software. The only thing I'd advise don't make it too complicated. Like don't tell you want to create the next Facebook or something like that, as that might have a list of requirements, you know, three or four pages long or even longer. So come up with something simple, like like a vending machine. Or like a simple, maybe online store. Or maybe you want to create, you know, Ah, simple iPhone app, stuff like that, so that you can just work with something really simple, coming with some requirements and see how you transition those over into the design and the architecture of the APP.