- Read Tutorial
- Watch Guide Video
The reason for that is because it's one of the most high-level components. When I'm usually going to build out this type of package diagram it's typically when I'm first thinking about what I'm going to be building.
Now, because of the way that this course is structured, I wanted you to develop a mindset and a mental framework for building out and discovering how you can organize code. You're building this system after looking at the code--which is hopefully a little bit more straightforward than doing it from scratch--but in the future building, this type of diagram is going to be the very first thing that you do even before you have entered a single line of code into your editor.
phone_parser/lib/phone_parser.rb :
require "phone_parser/version" require "phone_parser/country_codes" module PhoneParser def self.parse(number, country_code: '1') number.delete!("^0-9") digit_length_validator(number) CountryCodes.country_code_validator(number, country_code) end def self.digit_length_validator number number.length < 10 ? (raise PhoneLengthError) : (number) end end class PhoneLengthError < StandardError def message 'Phone numbers need to have at least 10 digits' end end
So what we have here is a phone parser. You can see that we have a few modules. We have the phone parser module, and then we bring in the country code module. You don't have to worry about the version; that simply dictates the version of this particular code library.
It's relatively simple what is inside of this. The idea for using this as an example was not to give you an overly complex problem, but instead to give you a really nice case study that you can use for future projects.
Notice I added a frame here and I used the shorter version of package--just 'pkg'--so that anyone looking at this will instantly know that it's a package diagram. Inside of it, we just have two modules which, if you look at the codebase, that's all we have there as well. We have PhoneParser, and then we have CountryCodes.
Now I'm drawing this dotted line with an arrow here because a phone parser has a dependency. It depends on the country code. Now that is one of the most important parts of this entire project is being able to see and to visualize where the dependencies in your system are. Because if I were to build out this type of system--if I were to start with this package diagram and then go and start coding--it would instantly tell me that this phone parser cannot live by itself. It is going to have to have a call to this CountryCodes module.
CountryCodes can live by itself. This is simply a helper library. It's not making any calls to PhoneParser. This could just as easily be taken out and applied in a different application. And it does not need PhoneParser. However, if you look at the PhoneParser code library you'll see that it does require CountryCodes. And that's part of how it performs the country code part of the validation.
The functionality of this particular Ruby gem is not the most important part of the project. The most important part is being able to see how these are organized. We have two modules, so it makes sense that we'd have two packages, and then be able to add a few items so we can show that there is going to be a number, a country code, and some of the other methods that are inside each one of these items. And also maybe show what type of data structure we're working with.
But here I'm much less concerned about adding a lot of detail. This is still very high level. If I were to build this out and come back and start building out the project afterwards--which is actually what I did--this is the same UML diagram I used before I wrote that entire library. Then I can come and have a really nice idea right away on what type of systems I'm going to have to build in to each one of these modules. And like I mentioned, one of the most critical parts of this entire part of the project is being able to outline the dependencies, because the other part of this that's very important is: imagine that we're going to make some significant changes later on. We're going to say that this phone parser library has to be revamped for adding 10 new features. If I do not have a package diagram right here that shows the different validations, then I could potentially be throwing myself into a situation where I might break this connection on accident. So I might pull out the call to CountryCodes, or I may pull out the CountryCode library entirely or something like that.
Now that may seem implausible, and it's mainly because we only have two modules here, but imagine an application that has 20 different modules or 100 modules. It becomes shockingly easy to pull out one type of module, or one type of class, and not realize that it was a dependency and was being called from another module and so if you have a package diagram then you can when you're later on making changes have a little checklist and say that when I'm making changes to this phone parser library I have to be careful because I know that it relies on country codes. So for me personally one of the most important elements of a package diagram is being able to visualize those dependencies.