📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

Основы архитектуры приложений (декомпозиция). Лекция 1: Основы архитектуры Java приложения. UML

Sergey Nemchinskiy32:15

Transcription

Hello, my dear friends!

On this channel, a long time ago, you could even say that the entire channel started with these lectures. There was a lecture about how to decompose a subject area, generally how to build the architecture of an application.

But the architecture of an application begins primarily with the decomposition of the subject area, meaning breaking down the subject area into parts that we will work with. I think that’s clear, right?

The lecture was very old; in fact, it was probably the very first video I recorded for the channel. So, the recording quality and sound were not great. It was so long ago that I didn’t really know how to explain things well.

Well, I watched it again, and it seemed okay, but we decided to re-record it for you in good quality. This will be a series of lectures on how to start building the architecture of an application.

We will discuss everything: how to decompose the subject area, how to identify specific classes during this decomposition, how to connect them, what typical solutions exist for various situations, and what tools we will use for this.

Today’s first lecture is about the tool we will use, which is the UML language.

My name is Sergey Nemchinsky. I have been programming for a long time and have also worked as an architect in some of my projects. I teach courses on architecture, so I have some understanding of this. I think it will be very useful for you if you are a programmer or planning to become one.

Let’s get started!

[Music]

Transform code into art with my author’s course on design patterns. The course presents information in an understandable way, unlike textbooks, with detailed breakdowns of patterns, webinars with the group, lots of networking, and practice. Register for the course by February 21 and get a 20% discount.

First, a brief introduction about why all this is important.

It’s very simple. Since ancient times, when something was floating above the earth, well, it doesn’t matter, from Adam and Eve, ancient programmers communicated with each other. While communicating, programmers would take a piece of paper, a pen, or maybe a marker and draw on a board.

In any case, they drew something to explain to each other. Two or three programmers would gather, one would explain something to the other, and naturally, they would scribble something because humans are visual beings.

We perceive most information visually, so it’s very helpful to see, at least in some approximate form, what the conversation is about. It’s much easier to remember and discuss.

Everything was good and wonderful. Two programmers gathered, drew something on a piece of paper, some scribbles, and so on, but they understood each other and went their separate ways.

In principle, nothing has changed since then, and in most cases, programmers still gather and continue to draw some nonsense on a piece of paper, and it doesn’t bother anyone.

The main thing is that they both understood what the conversation was about, right?

This situation suited everyone, except for the authors of textbooks, lectures, and others. Because you understand that every author of a programming textbook or training wants to explain to their audience in a way that they understand everything.

If you have to explain your system at the beginning of every book or lecture, your lecture immediately becomes significantly longer, and the book fills up with a lot of additional information.

Most importantly, this is incredibly inconvenient for your readers, viewers, and listeners because they came to you, then went to Vasya Pupkin, who drew completely different symbols with different meanings or the same symbols with different meanings.

In short, you get confused. You switch to another speaker, and there are clouds and triangles pointing in the opposite direction, and you’re like, “Oh God, my brain is exploding trying to remember what each lecturer is explaining.”

In general, everyone got tired of this. I mean, the people who wrote beautiful programming books.

Well, it’s clear that everyone wants some standards. They gathered and came up with a standard.

I want to draw your attention to the fact that UML is not a programming language; it is, in fact, a language for how everything is drawn and interpreted. It’s very simple: Unified Modeling Language.

It’s clear and natural because, seriously, if we are working with some images, it would be good if they were all the same.

It’s worth noting that this language, like everything in our programming world, evolves at an incredible speed.

As of today, there are dozens of types of UML diagrams, and with each new standard, new diagrams are added. But don’t worry; we only need one or two diagrams as programmers.

Okay, the class diagram and the sequence diagram. We will talk about them today.

And believe me, everything I tell you in this first lecture will be enough for you to read and draw these diagrams so that other people who understand UML can read them, and when they draw them, you will also be able to see and understand them.

Honestly, there are many other types of diagrams, but many of these diagrams are not for programmers. For example, some are for business analysts or DevOps.

There are actually more than five diagrams for programmers, but they are used so rarely that I had a situation where I drew an activity diagram that was much better suited for the case, and our American Indian representatives of the client said, “Can you draw a UML diagram?”

I said, “But this is an activity diagram.” They said, “I don’t know, just a sequence, please.”

So keep in mind that knowing more is not always useful, and in this case, it probably is.

So, why do we need UML?

You will use UML when you think about it. It’s very useful and helps you, well, you know, structure your thoughts.

Drawing abstract circles is great, but it’s very difficult to validate what’s drawn. UML is a somewhat standardized thing, and when you look at it or show it to another programmer, they can also assess whether it’s drawn correctly.

That’s the first reason.

The second reason is that you can turn UML into code in any object-oriented language without any problems because, well, it is what it is.

Starting with a UML diagram for your application is very convenient. You start by drawing a diagram of the subject area, from which you then create what is called a class, which will represent the subject area.

You describe its fields and relationships, which is already a good framework for the application from which you can push in both directions.

Then we go to the database, then we go to the front end. That’s the plan, but we’ll talk about that later.

Now let’s talk about the two diagrams we need and how they look.

Let’s start with the class diagram because probably 90% of all UML diagrams you will draw, or maybe even 95%, will be class diagrams.

This is a static diagram that shows how the classes in your application are related to each other, what fields they have, and what methods they have.

It’s all very simple. Let me show you how it looks.

First, I’ll show you on the example of a blank screen. I will just draw it in a human way, and you will see that there’s nothing complicated about it.

What do we have in a class diagram?

In a class diagram, we will have a class.

You will laugh, but there is a class.

A class in a class diagram is represented as a rectangle.

Sorry, there should be a rectangle here. I’m drawing a bit crookedly, but I think you understand me.

So, a rectangle is divided into three sections. In the top section, we will have the class name; in this case, let’s say it’s Class A.

In the second section, we will have the class fields or attributes, as they are called in UML terms, but you can say fields, and no one will be offended.

These are supplemented with access levels. Usually, fields are private.

Private means there’s a minus sign in front of them. Public means there’s a plus sign in front of them.

In the overwhelming majority of programming languages, there are also additional access levels: protected, package, local, and some other options.

But UML is about simplicity. For UML, there are exactly two access levels: private and public.

If you need to specify some tricky access level, just indicate it, and you can sort it out later according to your situation.

UML is about being easily understood.

Yes, there are symbols that show these access levels, and everything can be shown cleverly, and so on, but don’t complicate it.

UML is about the simplest representation.

As my experience shows, if you need to draw something in UML that UML doesn’t allow, think again.

Most likely, you’re overcomplicating it, and you’ll write nonsense in the code.

Don’t do that. Think about how to make it simple. If your diagram is simple, your application will likely be simple too.

And if it’s simple, there will be fewer errors, and you will write it much easier.

Do you understand what I mean?

So, how do fields look?

For example, a field is written as follows: fieldName: type.

I’ll write type int. I think that’s clear, right?

In the third section, we will have functions, methods, or operations in UML terms.

We will have public, which means a plus sign, operation1, with parameters in parentheses. If there are none, it’s empty, and then a colon followed by the return type.

For example, it’s all simple and clear.

This is how a class is described.

You might say that in your programming language, there are many other variants of objects, like interfaces in Java or enums in many other languages.

So, here’s the thing: I highly recommend not to bother with that.

Draw a rectangle everywhere. If you really want to indicate that this specific thing is an interface or an enum, UML has a nice feature where you can indicate that below the class name in angle brackets.

So, you can indicate that it’s an enum.

I didn’t fit it here, but you get the idea.

But as practice shows, you can skip this.

Again, keep it simple and avoid trying to create complexities.

Next, what else do we have in UML in the class diagram?

Let’s switch to a more convenient editor because, let’s be honest, this is inconvenient.

And this is how you will draw on a piece of paper when you show it or on a board when you talk to other programmers.

They’ll be like, “What is this?”

As you can see, my handwriting is not great. I think your handwriting isn’t great either because you’re programmers.

So, let’s use specialized software for this.

There’s actually a ton of specialized software, but I’ll just take a free one because it’s free, simple, and you can use it anytime through a browser or download the app, again for free.

Okay, I’ll set aside unnecessary things, including the tablet, and let’s use the mouse for convenience.

This is how it looks.

Let’s create a new diagram.

It looks a bit scary, but don’t be afraid. We’ll figure out what we need.

We need a class.

Oh, something familiar, right?

With one click, I got a nicely drawn rectangle where everything is in place.

Here, we can easily rename the class.

Let’s call it, for example, Student.

Great! The student will have a field, for example, name.

I’m too lazy to write two fields, so let’s say name, and its type will be string.

That’s logical, right?

Of course, your name will probably not be a string or something like that, but we’ll keep it simple for now.

And look, there are also methods.

Everything is clear and simple.

I don’t even know what else to add.

As you can see, we don’t like the access level here; we want it to be private.

When I show this to students, they regularly ask, “Where are the getters and setters for this field?”

The general idea of UML is that we only draw what is essential.

It’s clear to anyone that if there’s a field with a minus sign, there’s likely a getter and setter.

But if you really want to indicate them, you can put a plus sign on that field, and it will be considered that the field has getters.

But honestly, these are all technical details.

Right now, we are thinking about the system as a whole, how these objects interact with each other, and how they will be nicely laid out.

Got the idea?

So, a method.

I don’t know, let’s just call it a method.

Now, let’s figure out the relationships between objects.

We will have a second object that we will call, I don’t know, let’s keep it simple and call it ClassName.

They will have some interaction.

What does interaction mean?

Look, the simplest interaction is association.

Here in UML, it’s not even highlighted because normal people don’t use it.

A line between two classes indicates a bidirectional relationship.

Or it often means that we just haven’t thought about how these two classes are related.

A line without arrows on both ends is considered a line with two arrows pointing back and forth.

It reads as follows: Class Student and ClassName are somehow related or depend on each other in code.

This probably doesn’t mean anything because, let’s be honest, normal people don’t use cyclic dependencies between two classes.

Class Student depends on ClassName, and ClassName depends on Student.

That’s just bad practice.

But if you have such bad practice in your code and you somehow anticipated it at the architectural level, then this line without ends is how you would represent it.

But such perversions, as you understand, are rare, so we’ll remove it.

It’s still unnecessary; that’s just too much.

So, we’ll delete it.

The most common arrow you will use is a simple arrow.

Let’s make it straight.

This simple arrow reads as follows: Class Student uses or depends on ClassName.

In code, this means that some method of Class Student calls some method of ClassName, possibly a constructor that creates such an object.

It doesn’t matter; it just means it depends on it.

If several methods from Class Student call methods from ClassName, the arrow remains the same.

You don’t care about the number of calls because, in reality, we are only interested in one thing: does Class Student depend on ClassName or not?

What does this mean?

Will it compile if we remove ClassName?

If we remove Class Student, ClassName will compile because it doesn’t depend on Class Student.

But if we remove ClassName, then Student is no longer there, and there’s no one to call.

Got the idea?

So, this arrow indicates dependency.

If you call someone, you depend on them.

The next arrow we are interested in is the aggregation arrow.

Now, let me find it.

Found it!

The aggregation arrow is represented with a diamond shape.

It means that, for example, a student has many of something.

This arrow reads as “has” or “contains.”

For example, a student has several groups.

In code, this usually means that this object has another field.

In code, it typically looks like this: another field that will be a list of groups.

For example, the field will be called groups, and it will be of type List<Group>.

So, in this case, if Class Student has a list of objects of that type, we create such a relationship.

Because many beginners get confused later, I want to clarify that this arrow with a diamond can also be represented like this.

It’s often drawn in documentation.

But I personally get annoyed by this.

This way, the diamond is on the side with one, and the arrow is on the side with many.

You can write it like that, but I honestly don’t see the point in drawing the arrow.

It’s very confusing for me.

I still prefer aggregation in the form it was, without the arrow, with the diamond on the side where the list is, and that’s it.

Most sources also draw it this way, but if you see such an arrow, don’t be surprised; it’s a normal situation.

Now let’s talk about composition.

Composition is also a relationship, meaning “consists of.”

This relationship is no longer about students and groups.

For example, it would be if the group consists of students.

If there are no students, then there is no group.

Or more precisely, a car consists of parts.

If there are no parts, there is no car.

Because, seriously, something has to exist, right?

From a coding perspective, it’s exactly the same list as before.

But usually, in code, it also means that there are special constraints on the class that it cannot be created without at least one child object.

Honestly, I’ve never seen composition in real production code, and you probably won’t use it either.

So, just forget about the existence of this arrow.

But if for some reason you need to explicitly state that it’s not just aggregation but composition, and you want to ensure that it cannot be created without at least one child object, then you can keep an eye on that.

I don’t know; the idea is clear.

Now let’s talk about other types of relationships.

The first relationship we are interested in is generalization.

So, if this is Class Person, we use the generalization arrow.

Let me find it.

Here it is!

This arrow goes from the child to the parent and reads as “generalizes.”

I know that many beginners get confused with this arrow.

It means that Class Student is a subclass of Class Person.

This arrow, even though it has the label “extends,” is often not written.

You can even delete this label because it can be confusing.

This arrow indicates generalization, meaning it goes from the child to the parent.

Class Person is a more general object compared to Class Student.

I know that every time I explain this lecture, beginners ask, “Why is the arrow pointing this way? I would like it to point the other way, from Parent to all its children.”

I say, “No, well, first of all, even in code, in any programming language you write, if you have OOP and inheritance, how do you write it? In the base class, you just write ‘class’ with nothing additional. In the child class, you write ‘class’ followed by a colon and some experiments.”

Yes, there are dependencies on programming languages, but these are the two main options used.

So, this is how the class indicates that it inherits from that class.

That’s why the arrow goes from the inheritor to the parent because, in the inheritor, you specify whose inheritor it is, while the base class doesn’t call anyone, doesn’t depend on anyone.

The arrow goes in the direction of dependency.

Yes, let it be triangular in this case because, well, look, Class Person can compile without Class Student.

It doesn’t care about its descendants.

That sounds a bit off, but sorry.

Class Student cannot exist without Class Person.

So, no other arrows interest us.

As you can see, there’s a very small list of what you need to know in terms of UML.

And agree, it’s quite simple to draw any diagram that comes to mind using these elements.

You might say that in your language, there are templates, generics, enums, and a ton of other goodies like interfaces, and so on.

Yes, UML has special symbols for many of these things.

So, look for them; there’s a special symbol for almost every concept.

But I highly recommend not using them.

If you really want to use some tricky term, just do the following:

For example, write “interface Person.”

No problem!

Or you can move it to the next line; that’s often done too.

No problem!

If you want to say “enum,” just write “enum” here.

What I’ve explained is basically all you need to know about class diagrams.

As you can see, it’s such a simple thing that I’ve explained it in about 20 minutes.

Now let’s move on to the next diagram we are interested in, which is the sequence diagram.

The sequence diagram is also quite simple.

Essentially, if the class diagram shows us the static structure of what our code consists of, like the classes that are related to each other, the sequence diagram shows how everything will work.

Here, we have all the possibilities to say, “This sequence occurs.”

Because, in principle, these two diagrams are enough to show any static and dynamic structure.

You don’t need anything more.

So, how does a sequence diagram look?

It’s even simpler, surprisingly.

I’ll show it to you now.

It consists of these elements: objects.

Yes, the sequence diagram is about how things happen during the execution of your program.

Naturally, you cannot interact with the classes themselves.

Well, there are static sections and so on.

Anyway, we interact with objects.

If this object has a name, it’s written at the top.

For example, let’s say we have an object named A.

This object is of type Student.

And here we have another object, for example, a Professor.

If we need several objects of the same type, we give them different names, and they will call each other.

So, here’s how it goes:

The Student sends a message to the Professor, for example, submitting an assignment.

It’s simple; he sent it to him.

Here, we write the name of the method that the Professor called.

For example, the Professor might call something in his educational system to double-check the assignment with artificial intelligence.

Some educational system will check it.

For example, it returns a value, and the Professor returns the result to the Student.

So, the sequence is clear, right?

The Student sent the assignment to the Professor, the Professor consulted the educational system, and the educational system returned something to him, which he then returned to the Student.

There might be a situation where the Professor decided to consult himself first.

This is how it looks.

Now, about these things: this is called a lifeline.

Many systems actively use it.

In this case, this block shows that the Student is active at this moment, doing something.

You can draw them or not; in modern programming, it doesn’t really reflect anything.

But it’s customary to do so.

If you use many UML drawing systems, they will automatically place these lifelines for you.

Yes, we had an arrow going in the wrong direction.

It should be like this; he turned to himself.

He said to himself, “I’m great!”

I’ll place this activity here because it’s active.

And the system is also active, so I’ll place it here.

This is how it will look.

You can draw these lines quite easily; you can add them or not.

But the function itself is quite simple: one object calls another object, and that object returns something to it.

You can write the return or not; it’s assumed that even if you didn’t indicate this arrow, some return occurred.

So, if we delete these arrows, the diagram is still absolutely simple and understandable.

We will go into more detail with all these elements when I show them in specific examples.

But all the elements are so primitive that you can start using them from today.

It’s all very simple and, in fact, very useful.

Note that all these elements will be used in all literature related to architecture, starting from the simplest GoF patterns, the Gang of Four, where everything is written and drawn in UML.

They explain it all there.

I hope I’ve explained these very simple things more clearly.

You can start using them.

If you have questions or want to clarify something, or if you need additional explanations, I will add those in the next video.

But in the next video, we will look at typical solutions, how they are used, and how we decompose and write programs.

Okay, that’s it!

I love you all.

Subscribe, like, and let me know in the comments how useful you find these videos.

Goodbye, and I can peacefully leave this planet knowing that my music will remain: Alex Van Halen from Van Halen.