Software Engineeing Notes
Software Engineeing Notes
Hi, I'm Kenneth, I'm a professor from Hong Kong University of Science and Technology. This course
is about software engineering and in the first lecture is going to be just an introduction to software
engineering. These are the learning objectives of this lecture. After this lecture, you appreciate that
developing large software system is a complicated process. You will learn some techniques for
dealing with the complexity of software development. Then finally, you will understand what is
software engineering and why it's important in software development. Software is complexity
developed, because if we are talking about a large software system, it has many lines of code. For
example, for a Boeing 787, it has 14 million lines of code. If you are talking about Windows 7, we
have like 14 million lines of code. Windows 10, we have 15 million lines of code, etc. When we're
talking about this large software system it's not possible for us to implement a system from
bottom-up. That means we implement a system line-by-line function by function. But instead, we
have to plan a lot before we start implementing the system. Software complexity may come from
application domain. The problem itself may be very complicated. The developers, they usually not a
domain experts. For example, if I asked you to build a software system for a hospital to keep track
patients' information. Then you are an expert in programming, but you are not an expert in the
application domain, that means the hospital. Then you may have to learn about the application
domain before you can work on the system. Software complexity may also come from
communication among stakeholders, just because different stakeholders, they may be using different
vocabulary when they communicate. For example, your client may come to you and they ask you to
build a system to store numbers. Then you may have to clarify with your client, whether they want to
store integer, whether they want to store real numbers or floating-point numbers. The stakeholders,
they may have different background knowledge and sometimes human languages are inherently
ambiguous. That's why the complexity may come from communication itself. Also management of
large software development project is going to be complicated. That's why we have to divide the
project into pieces and then we assemble the pieces. We need to coordinate with many different
parts and also many different people. Also coding itself is going to be complicated and creating
useful software is going to be a complicated process. Software complexity may lead to software
quality problems. For example, you may make your software system unreliable. I'm going to show
you a little video about this Ariane 5 rocket. The entire rocket just rolled up because a tiny mistake
into software system, a tiny bug in the software system. We'll talk about this bug when we talk about
testing. [inaudible] A final decision to go was taken. [inaudible] Thirty-seven seconds into the launch,
the on-board computers decided 501 was 90 degrees off course.
Play video starting at :4:28 and follow transcript
4:28
They made an automatic adjustment of the trajectory as the rocket was traveling at the speed of
sound.
Play video starting at :4:51 and follow transcript
4:51
You may also make your system unsafe. For example, the London Ambulance System which fell
twice in 1992 and people died because of the failure in providing ambulance service, and abandon.
For example, people spend five years in developing this London Stock Exchange System. They
eventually they have to abandon the system because it's not reliable. Eventually you may also make
your system inflexible, which is going to be hard to change and also hard to maintain. Also software
complexity may lead to software development problems. For example, your project may be over
schedule, over budget, and also it may not meet user requirements, and development of working
code is lower than expected. That means over-scheduled. Progress is going to be difficult to
measure, and for a large software system, 17 percent of the time they are facing company
threatening. That means people say something bad about your company on, for example, the
internet, and 45 percent of time is going to be over budget, 7 percent of the time is going to be
overtime, and 56 percent of the time is going to deliver less value as expected.
To deal with complexity, the first thing that we have to do is to choose the appropriate design goals at
the very beginning of the project. Let's say if you want to build an online transaction handling system,
then you have to make sure that your system has to be efficient and also reliable. Notice that it's
often impossible to achieve all of them simultaneously, all of them at the same time because of the
time and budget that you have for the project. Notice that some of the design goals, they may be
conflicting with one another. So that's why it's not possible for you to achieve all the design goals at
the same time. To choose the appropriate design goals, you need to clearly understand the client's
design goals at the very beginning of the project. If the client tells you that I want a system to be
efficient and to be reliable, then those have to be the design goals that you choose for the project.
Then you need to prioritize the design goals for a different project and then base the development
around these design goals. Again, you have to choose two or three or four most appropriate design
goals at the beginning of the project. Having clear design goals is going to reduce the complexity of
designing the system because you know exactly what you need for your software system. Eventually
when you design a system, it's going to be much easier. To deal with complexity, another thing that
we can do is to apply modularity and also incremental development, because there is a limit to
human understanding. When we are building a large software system, then we can apply an
approach which is called divide and conquer to divide the large software system into many smaller
pieces. Instead of handling the large software system all at once, we're going to build the smaller
pieces, smaller modules one at a time. The definition of a module is a part of the system that makes
sense to consider separately. Notice that these modules are going to interact with each other
because one module may be using some of the functionalities or some of the operations from the
other modules. So that's why they interact with each other. Another approach to deal with
complexities is to use information hiding. When we try to assess a particular module, we are only
allowed to assess the module or interact with the module via interfaces. By using an interface, we
achieve both abstraction and encapsulation at the same time. What are the definition of abstraction
and encapsulation? Abstraction means we skip details. When we try to use a module, we don't have
to actually understand what's inside a module, that means the source code and the implementation
within the molecule. We only have to understand how to use the interface, that's it. Encapsulation
means if you want to maintain a particular module or when we want to modify a particular module,
then it's going to be just within this module. We don't have to touch the other modules. That's what
we mean by abstraction and encapsulation. The good thing with abstraction is that a module can be
used by only understanding the interface, but not the actual implementation within the module. This
is going to reduce the complexity of understanding the system because you only have to understand
how to use the interface instead of understanding the content. That means the source code and the
implementation within the module. An interface also provides encapsulation. If you want to change a
module, you have to only change that particular module without affecting the rest of the system. This
is going to reduce the complexity of maintaining the system, because when you maintain the system,
when you want to change something, you only have to touch one thing, but not the other things. Now
by applying modularity and also incremental development, that means you chunk the large software
system into smaller pieces and then you handle one small piece at a time, and then also using
interfaces for the modules for the smaller pieces. Then it allows more productivity in team
development, because one team is going to be just responsible for one small thing. It's just because
people, they are focusing on one small thing instead of a large software system. Then eventually, we
may get fewer bugs in system development and also more maintainable software and also more
reusable software, and resulting in more predictable software development. This is going to reduce
the complexity of cost and time estimates for developing the system. Another way to deal with
complexity is to provide training to software engineers. What do engineers do. Engineer they apply
scientific knowledge, for example, mathematics, physics and then develop solution for some
technical problems. Then engineers, they have to design materials, they have to choose the
appropriate materials, structures, and also system while considering some limitations. For example,
the time and budget that you have for the project. What do we have to do as a software engineer?
There are two things that we have to do as a software engineer. One is programming-in-the-small,
that means coding. Another thing is programming-in-the-large, that means software engineering. So
apart from coding, there are many things that you have to do within software engineering. For
example, you have to talk with users in terms of the application, you have to communicate with your
client, and also communicate with your users. Then also translate the vague requirements into
something that's going to be more precise. Then you have to build models of a system at different
levels of abstraction so that when you communicate with your client, when you communicate with
your users, you can use your models to communicate with different stakeholders within your project.
Also you have to use and apply several software development processes, and we're going to talk
about different development processes in one of the upcoming lectures. Also you have to choose the
appropriate design and also make design trade-offs and work as a team. This is going to reduce the
complexity of building the system.
So, what is software engineering anyway? So, I'm going to play back a little video about software
engineering.
Play video starting at ::7 and follow transcript
0:07
>> My name is Chris County Corban. I worked at Apple on IOS. What is software engineering.
We've got four pictures of things here. We have a world of Warcraft. We have Call of Duty 4,
airplane, and we have the New York stock exchange. But what do they all have in common? So
hopefully it will be too much of a reach to think that all of them have a code in common and a lot of it.
Just for a little bit of a frame of reference. Boeing 747 has more lines of code than it does parts
including nuts and bolts. I was really blown away by when I heard this. How much lines of code?
Specifically, a Boeing 747 has 4 million lines of code in it. And most games that you play today have
about 6 million lines of code. And just for reference. So, these are really huge software systems that
really can't be thought of as one line or one class at a time. The software engineer needs to think
about the design of different levels, from one line of code all the way up to the entire system. So,
let's think about scheduling that for just a moment. If I can write one source line of code per minute,
there's 60 minutes in an hour and there's 40 hours an average work week. That gives me 2400
source lines of code per week per software engineer. We take that, we multiply that by the usual 50
work weeks per year. That means every software engineer can crank out 120,000 source lines of
code per year. Pulling that all together, I have two million lines of code estimated in a project. With
the amount of code I can crank out from each engineer, I need the very least 17 software engineers
to get this on the software shelves for the holiday season. You get a feeling that these things need to
be planned out a lot. And also that you have to work in teams. Then, also writing one line of code per
minute on average believe it or not is actually pretty hot shot in the software industry. And actually it
really is, mainly because so much of your job as a software engineer is so much more than coding.
Let's talk about one company may have heard about amazon.com. It's one website. It's relatively
large and pretty complex. Software team was going to go to one small software upgrade pretty easy.
But the upgrade didn't go out so hot and it caused a 90 minute outage. So, is that priceless? Not
exactly. Estimated to cost amazon was $2.8 million dollars in lost. That's not just revenue that they
they lost from customers, where they could have come back later and bought this product later. Now,
this is actually $2.8 million Amazon lost because the website was down. The customer needed
something then, and they lost that $2.8 million. So, somebody got fired. The system wasn't safety
critical but it is financial critical. So, this team needed a better understanding of the process for
developing a critical system. And how to bring an upgrade online without taking down the system. In
this case, Amazon would have benefited from a better defined software development process. As a
software engineer, you have to answer a lot of questions. One question, is how much code you have
to write. But there are a lot of other questions that remain to. How can I help the customer? What's
required to solve the customer's problem? How will the user interact with the system? What
operating system, language, hardware is going to be used? What is the overall software system
structure and how do different components interact with each other? How do I organize my team?
So, we're all effective. And can we finish the game and time to have it on shelves for holiday
shopping? The real common trend here, is that you have to talk to a lot of people to make this
happen. You have to interact with customers who are asking for the system, people who will use the
system, domain experts, banking, avionics, security, medical scientists, engineers from other
engineering disciplines. And even most closely with other engineers on the project. Another big
underlying theme here is communication. Software engineering is a very social activity. You don't sit
in a cube and write code in a corner, you're always working with people and it's a very people driven
field. But that doesn't mean that software engineers don't get their hands dirty writing programs,
using the latest technologies and techniques we live and breathe that as well. And also, it's important
to note that it's not just project management and communication. But it's also not about coding
either. By now you might be seeing that software engineering doesn't exactly equal CS. Both majors
try to solve real world problems using code, but how they go about that is very different. So, for
example, if a bridge falls down, is a scientist or engineer. Well, not so much the scientists, more the
engineer. Scientists build things to learn something new. And engineers learned things to design and
build quality products. Scientists want to achieve scientific breakthroughs. Engineers want to avoid
engineering failures. Computer scientists want to understand the algorithm, and the foundations of
computing theory. Whereas software engineers want to learn and design the principles of best
practices for building quality software system. And lastly, computer scientists want to know the basic
technology works and how to improve it. While software engineers, want to know the characteristics
of technology so they can design the most appropriate technology into their software system. >> So,
what is software engineering? If you take a look at Wikipedia or some references online, you're
going to get different definitions. So, notice that software engineering is a disciplined development
method. So, that means we try to develop something in a disciplined way instead of like your
programming assignment, right? You simply open up the source code and then type in something,
it's that hard. Okay, Iit's not disciplined. Okay. So, that's why software engineering and we are talking
about something disciplined, okay. And then it requires some built in quality. So, we try to achieve
some quality in the final product.
And try to solve some real user problem, okay. In some application domain. And then it requires a
team effort because you have to work in a team. And finally it's going to be multi-version. Okay, it's
not one off. Okay, unlike again, unlike your programming assignment is one off. Okay, in software
engineering or in a large software project, it's not going to be just one off. So, that's why we need
software configuration management to keep track different versions of the software that we have
developed.
So, software engineering involves a modeling activity. So, we have to capture all the use of
requirements and then we have to build a model. And there are two models that we have to build.
One, is what we call the requirements model. We try to capture all the requirements from our
users or from our client. Okay, then we have to build a solution model which is the actual model
that we're going to use for implementation.
Okay. And then we have to match the requirement model with the solution model. And it's a
problem solving activity. We try to look for the most appropriate solution in the presence of
change. And that's why it's not algorithmic, it's systematic. And it's a low range acquisition
activity. Notice that this lollipop acquisition activity is not a linear process. You learn while you're
developing the project. And sometimes you may have to unlearn because you have learned
something wrong, okay. And in the worst case, you may even have to need to start over again
because you are totally wrong. Then you have to start again, okay. And it's a rationale
management activity because our assumptions and solutions may change from time to time
because of bugs or technology. And we may need to revisit decisions from time to time. And
that's why it's important that we document all the things within the project. Because it's important
to remember why we make the decisions or why we make this choice. And we can remember all
the decisions and all the choices that we have made in the project, within the documentation that
we have in the project. So, that's why it's important that we document everything within the
project.
So, these are what we have covered in this lecture to deal with the software development
complexity. We have to choose the most appropriate design goals, usually two or three of them at
the very beginning of the project. And then we try to utilize modularity and also incremental
development techniques. That means we try to chunk the large software systems into many smaller
pieces and then we try to handle a small piece at a time. And also we have to use effective software
engineering techniques. From a technical point of view, there are two things that we have to do
within a software engineering project. First thing, is software engineering. That means we have to
build models, we have to document the system, and keep all the requirements and all the solutions
that we have come up with within the project. And this is what we mean by programming in the large.
And also, another thing that we have to do is of course coding. Okay, building the system and this is
what we mean by programming in the small, coding. And notice that, while coding is an important
software development activity. Software engineering is also essential because it's going to help
reduce the complexity of the project. And eventually helps achieve higher quality and also more
maintainable software systems. And that's all I want to cover in this lecture.
Lecture 2
Modeling Software systems using UML
Hey. This is the second lecture of the course. In the second lecture, I will talk about how we can use
UML to build a model to capture all the data requirements within an application domain. In particular,
I will talk about how we can draw a class diagram to capture or to keep track of important objects
that we have within this software system. These are all the learning objectives of this lecture. After
this lecture, you will understand what is UML and how the UML can be used to model software
systems. You will also appreciate that the UML is a modeling language, a language that we can use
to build a model to represent a system but not a software development methodology. Finally, you will
understand the basic components that we can use to draw a class diagram. For example, classes,
associations, and generalization. These are all the topics that we're going to cover in this lecture.
First, I'm going to give an overview about UML. Then we going to talk about different components
that we can use in drawing class diagram. For example, classes, associations, association classes,
generalization, etc. Also, how we can apply additional constraints on top of the class diagram. First,
we will start with the overview of UML. What is UML? UML is a general-purpose visual modeling
language for systems. That means we try to draw a diagram to represent a system that we're going
to build. It incorporates the best practices in OO modeling techniques because we are talking about
trying to capture a set of important objects within the software system. It's software development
methodology or process neutral because it's not a software development methodology. Is an
industry-standard OO modeling languages for modeling systems. Is very suitable for OO because in
UML we're trying to capture a set of important objects within the model. If we are talking about a set
of objects, then it's going to be very suitable for OO [inaudible]. But it also can be used for non-OO
systems.
Play video starting at :2:16 and follow transcript2:16
The basic idea of UML is that we try to represent the system using a collection of important objects
that exist within the software system. This is the structure of UML. Within an UML, we have different
building blocks, we have different building blocks that we can use for drawing the model. For
example, the important things that we have within the model, different relationships, and different
diagrams that we can use to model the system. Also, we have some common mechanisms. For
example, we can provide additional texture descriptions within the model. Also, we can include
additional adornments, for example, you try to draw some additional things or additional adornments
within the diagram. Also, some common divisions, some extra definition that you can provide to force
you to think about a world in a certain way. Also, extensibility mechanisms for you to extend the
model. We can build a model from different perspectives. For example, from the use-case view,
logical view, implementation view, process view, or deployment view. In this lecture, I'm going to talk
about the building blocks that we can use for drawing class diagram. Within UML, there are different
diagrams that we can draw. In this lecture, we will talk about class diagram. In some of the upcoming
lectures, we will talk about use-case diagram and also State Machine Diagram. Within class
diagram, we are trying to capture all the data requirements within a software system. So we try to
capture all the data requirements in a form of a collection of objects and their relationships. If we are
talking about the use-case diagram, we try to capture all the functionalities provided by the system.
Finally, if we are talking about the State Machine Diagram, we are talking about trying to capture all
the possible states that we can have within an update. These are the three diagrams that we're
going to cover within this course, the class diagram, use-case diagram, and also State Machine
Diagram. Why do we build models? Let's study this example, which is pretty interesting. This may be
how the customer explained about a project. Then this may be how the project leader understand it.
This may be how the analyst decided it. This may be how the programmer implemented it. Then how
the business consultant described it, and how the project was documented. No documentation at all.
What operations installed. How the customer was billed. How he was supported, and what the
customer really needs or maybe it's going to be just something simple. What's the problem here?
The problem here is actually communication. Just because different stakeholders, they may have
different ideas in their mind. That's why at the very beginning of the project, we need to build a
model so that when we communicate, we can communicate using the model. To make sure that all
the stakeholders, they're going to have the same idea in their mind by just take a look at the model.
Why do we build models? Let me just talk about another example. For example, let's say when we
build an airplane. Why do we want to build the model of an airplane before we actually build a
plane? Because you know that the plane itself is going to be very complicated. So that's why we're
going to skip some of the complicated details within the plane and then we're going to build a simpler
model. This is what we call abstraction. We try to skip details and we build a model which is going to
be simpler. But still somehow from the model you can visualize all the details within the plane. Then
we can use the plane, that model, the model of the plane, to communicate with different
stakeholders within the project. That's why we need a model. Because we need a model to
communicate with different people that we have within the project. The models that we're going to
build is going to describe reality. For example, the model of the airplane is going to somehow
describe the actual airplane. But here we'll talk about abstraction, we try to skip details within the
model of the plane. We try to show the essential details that we need for communication, and we try
to filter out the non-essential details maybe just because the airplane itself is going to be can be very
complicated. So we're going to skip some of the complicated things within the airplane in the model.
Play video starting at :6:57 and follow transcript6:57
For software development, this allows us to focus on the big picture, that means, all the important
objects that we have within the software system, and this is what we mean by
programming-in-the-large.
Play video starting at :7:12 and follow transcript7:12
By focusing on the big picture, it allows us to better deal with the complexity of software
development because the software itself, source code implementation services can be very
complicated. That's why instead of talking about a source code, we build a model to capture all
important objects that we have within the software system. This is going to help us deal with the
complexity within a software project. The result of a model is that we get better understand all the
requirements within the product, putting their design, and also more maintainable software systems
because we understand the software system better through a model.
Play video starting at :7:56 and follow transcript7:56
Why object-oriented modeling? Just because it's natural to represent things using objects. For
example in the application domain, we have organizations, we have people, and then we have cars.
Then people, they work for different organizations and also they own different cars. Then I just have
natural to map all these things within indeed application domain as different objects that we have in
the model. Within the model, we have organization, we have person, and we have car, and then we
connect them together using relationships. For example, person they work for organization, and
person they work for,
Play video starting at :8:42 and follow transcript8:42
and we connect them together using associations. For example person they works for organization
and person they own different cars. It's natural to represent things using the application domain
using objects, and it's going to reduce the gap between the application domain and also the model.
This is natural to map things as different objects, and also better represent how people think about
reality. That's why in this lecture, we're going to talk about how we can use a class diagram to
capture a collection of important objects that we have within the application domain. If we are talking
about OO modeling, there are different models that we can build. We can build a model to capture all
the requirements within the software system. In this model, we simply try to identify all the important
objects, all the important things, or all the important objects, or all the important concept that we
want to keep track within the software system. Then we also can come up with a solution model. So
somehow we go through analysis and design and then we build a solution model. That model is
going to be the model that we're going to use for implementation. That means, when we implement,
this are the objects that we're going to implement within the software system and also
implementation level. Eventually we're going to implement the solution model and turn the solution
model into a set of source code or a set of code objects. The same OO concepts can be used at all
levels. In this course, we are going to focus on two models. One is the requirement model, to
capture all the data requirements, all the important objects that we need within a software system.
Also how we design, how we actually design the solution model that we're going to use for
implementation. In this lecture, we focus on requirement model. Again, just keep in mind that if we
are talking about the requirement model, it has nothing to do with implementation. So just given the
application domain. We try to capture all important objects within the application domain, that's it. It
has nothing to do with implementation. If we are talking about implementation, we are talking about
the solution model. Solution model is the one that we use for implementation, but not requirement
model. Requirement model is going to be simple. We know that this are things that exist within the
activation domain. We try to capture all this things within a requirement model. The requirement
model is going to help us understand all requirements, all the things that we need within the software
system.
So now let's talk about how to draw a class diagram using classes, association, association classes
and generalization, etcetera, etcetera. So now let's first talk about class. Okay, now let's say we want
to build a software system for a bank and we know that within a bank we have different bank
accounts. Okay, then this may be different instances of the accounts that we have within the bank.
For example, we have Fred's account, Sam's account, Eva's etcetera, etcetera. Okay, and these are
all the properties within each individual account. For example, for Fred's account, we keep track the
account number on the balance. And then we have some operation to check the balance to deposit
money into the account, to withdraw money from the account or to pay interest into a particular
account etcetera, etcetera. Okay, now, instead of referring to this different accounts right? Within the
application domain, again, right. Because we have so many accounts, that's why we're going to do
classification, okay. We're going to group all these accounts together as a single class called
account. Okay then, within the model, whenever we refer to the accounts, right? We simply say that
we have account, okay within the software system. Okay, so here we are doing classification. Okay,
we try to classify all these instances as a single class. Okay, I can't. Okay, so for each class you
have to specify the class name, the actual builds and also the operations that we can perform within
the class.
So a class is going to describe a collection of objects that have common semantics, attributes,
operations, and relationships. For example, now we can see that this accounts right? They all have
the same attributes. They all have the same operations. So that's why we classify them together as a
single class called account. Okay, and that's why we say that a class is a classifier. And a particular
object is going to be an instance and we try to classify all these instances together as a single class.
And a class is a factory for creating objects. So we can use a class right to create different accounts
within the application domain. The bank, okay. And a good Class should capture one and only one
abstraction. Okay, so that means a good class should capture only one important thing within the
affection domain.
So a good class should capture one and only one abstraction. So that means a good class should
only capture one important thing within the application domain, okay. You should not mix up like
multiple things together and put it as a very general class within the software system, no, okay.
And a class should be named and using appropriate vocabulary of the application domain. Okay, so
that's going to be meaningful and also traceable. And also your your diagram is going to be easy to
read because you're using meaningful vocabularies.
Okay, and within a class you have to define all the actual bills that we have within the object, within
the class. Okay, so you have to provide names. Okay to built the type reasonability, initial value,
multiplicity. Whether we can have like multiple values within that bill, changeability etcetera, etcetera.
And notice that name and type they are required for UMLmodeling. For reasonability, initial value,
multiplicity and changeability. You may skip them in your UML model but name and type they are
mandatory just like this, right. Akane is going to be an integer. And then among, we're talking about
money.
So another thing that we need to specify within a class is what we call operation, okay. Operation
describe a function or transformation that may apply to or by objects within the class. Okay, so we're
talking about some operations that we can perform within the class. Okay, so for each operation we
have to specify the operations, signature, the name, property, name, result, type, etcetera, etcetera.
For modeling all this should be specified. Okay, for example, the name of the operation is going to be
a deposit, okay. And then the parameter that we need to input into this operation is going to be
amount, okay. And then we also need to specify what's going to be returned by this particular
operation, okay. And also we need to specify the visibility of the operations within the class. For
example, whether it's probably private protected or package. Okay, If it's appropriate then that
means that operation is going to be available to all the other objects within the system, okay? If it's
private then that means it's going to be just within that particular object, okay. If it's protected then
that means it's going to be within the object and also all these subtypes, okay. When we talk about
inheritance right, you will know what is like super tight and sometimes okay. Then if it's protected,
that means it's going to be available to the object itself and also all the subtypes, okay. Or within a
popular package, okay.
So an operation, instance is called a method because there are many different possible ways to
implement the same operation. So a particular implementation, a particular instance of an operation.
A particular implementation of that operation is what we call a method, okay. In general, we just say
we have an operation but a particular implementation is going to be called a method. And we say
that an operation can have several methods because there are different possible ways to implement
the same operation. So that's why here we say that there may be multiple or several methods for
implementing the same operation.
So why do we use classes to model systems again, just because kind of natural to represent a
system using classes and objects, okay. Especially for OO system. Okay, so now by representing
the system as a collection of object. Okay, it's going to have an outcome.
And again, choosing the appropriate classes is an important design decision, okay. It's going to help
promote modularity within the development. So that means there are different ways to come up with
the classes, okay. We don't have a single correct way to come up with the classes for modeling the
system. So modularity means we try to chunk a large software system into smaller pieces and then
we're going to handle the smaller pieces one at a time, okay? So if the piece right is too general, too
large, then we lose the advantage of modularity when we build a system.
Another thing that I'm going to talk about for class diagram is what we call association. Notice that
objects or classes within our class diagram, they don't exist alone. Somehow they are connected
with some other objects, within the class diagram. For example, Fred may hold an account, or Sung
may hold an account and then this account may be associated with a bank BEA. Then another guy
maybe Fred he's going to have this account and this account is going to be from HSBC, etc. Notice
that within the system we need to keep track all these links, between the instances that we have
within the system. For example, Fred is going to have this account and this account is from HSBC
and eventually we have to keep track many links within the system. Instead of trying to represent all
of this links within the class diagram, we can perform again classification. We can classify all this
links together and say that we only have this association holds between account and customer. Then
we are going to classify all these links together and say that we have this association is with
between account and bank. Again, here we are doing classification because we have so many links
within the system between the instances that we can have within the classes. That's why we need to
classify these links together and we perform extraction where we skip some details. We're going to
simply say that customer, they holds accounts and then accounts they are with different banks. This
is what we call a class diagram. We have classes in associations between the classes. In
association describe a collection of links. This is what we have mentioned in the previous slide. We
try to perform classification and then classify all the instances off the links as in association.
Conceptually, association they are inherently bidirectional. That means they are somehow
associated with a customer and that customer they may hold different accounts. So they are
bidirectional.
Play video starting at :2:37 and follow transcript
2:37
That means, for example, account is going to be hold by customer and then customer they hold
different accounts. Is going to be bidirectional. Again, in some cases we may show navigability of
association with an arrowhead. It means one object may depend on another object. But if we are
talking about
Play video starting at :3:5 and follow transcript
3:05
the requirement model we may simply use association without arrowhead. Because in most cases
the associations they are going to be bidirectional in a requirement model. In a solution model, we
may use arrowhead, because one class that we implement made depend on another class. But
when we are talking about a requirement model, usually in most cases it's going to be bidirectional.
Play video starting at :3:38 and follow transcript
3:38
Can we have two associations between the same pair of classes? Yes, as long as those two
associations, they have different meanings. For example, one of the association means the people
that attended, the people that are actually the student of a university. Then the other one is like the
people that works for the university. As long as these two associations they have two different
meanings, then we can have two associations between the same pair of classes. Also we can have
unary association. For example, some people they may married two other people and then some
people they may manage, they may be managers of some other people. This is what we call unary
association. Instances within a class, is going to associate with some other instances within the
same class.
Play video starting at :4:39 and follow transcript
4:39
Notice that the collection of class in association names, they must be unique. When you try to come
up with names for the classes in associations, make sure that the names they are unique. These are
the different types of associations that we can have within the class diagram. Can be unary. That
means the class is going to be associated with the same class. Finally here, we have an association
between two classes or, it's going to be ternary, that means we have an association between
multiple classes. In this course, most of the associations they're going to be unary or binary
associations. Notice that higher degree associations, they are extremely rare. Unless really
necessary, you don't include high degree associations into your diagram because higher degree
associations, they are more difficult to understand, they are more difficult to read. If you include
many high degree or ternary associations in your diagram, it's going to make your diagram more
difficult to read and then when you try to use your model to communicate with different stakeholders
within your project, that model is going to be difficult to read. That model is going to be more difficult
to understand by the artistic orders. In most cases, we would simply use unary or binary
associations. In practice, the majority of associations is going to be binary.
Play video starting at :6:19 and follow transcript
6:19
Within an association, you also need to specify what we call multiplicities. Multiplicity specify a
restriction on the number of optics in a class that may be related to an optic in another class. This is
how we specify multiplicity, for example, at a given bank, how many accounts can it have? Now if we
say that a bank can have multiple accounts, then we simply use zero dot dot asterisk. Asterisk
means any. This is the lower bound, zero up to any number of accounts, that means it can have
many accounts. This is how we specify multiplicity, and notice that this is the lower bound zero and
the upper bound is any, up to infinity. Then given an account, how many banks can it be with? For
example, an account must be with exactly one bank. From the application domain, you know that an
account must be from one bank. Then you pull my demo multiplicity here and say that an account
can be associated with one dot dot one, lower bound is one, upper bound is one, that means exactly
one bank. Multiplicity is an application domain constraints, that means you have to get this
information from the application domain, the domain expert, some people from the application
domain will out you, a bank can have many accounts and then an account can be associated with
exactly one bank only. Then some information that you can get from the application domain. This is
how we specify multiplicities within a class diagram. For example, when we specify C1 can be
associated with how many C2, we're going to specify it here. When we specify, for example, C2 can
be associated with how many C1, then we specify the multiplicity here, SA dot dot b. When the lower
bound is zero, then we say there's going to be optional participation. That means C1 may or may not
be associated with any C2 because the lower bound is zero. But if it's mandatory, that means the
lower bound is bigger than zero, then that means C1 has to be somehow associated with some C2,
and we say that the participation is mandatory, etc. Then we also have to specify what we call it the
maximum cardinality. There are some special cardinalities that we can use to simplify the class
diagram. For example, if the minimum cardinality is one and the maximum cardinality is one. For
example, one dot dot one. Then we can replace it with simply a one. That means exactly one. If the
lower bound is zero and the upper bound is an asterisk, then we can simply replace it with an
asterisk. That means any. A bank can have any number of accounts. So this are the two special
cardinalities that we can use to simplify the class diagram. Now let's try out this little example about
multiplicities. So let's say from the application domain, you know that a student must enroll into at
least one course and can enroll into at most five courses in a semester. Then you may say that a
student can be associated with one up to five courses. Then again from the application domain you
know that a course must have at least 10 students and cannot have more than 45 students. Then
you may say that course can be associated with 10..45 students. Now, let's think about it. Does it
make sense to you? What's wrong with it? Think about it.
Play video starting at :10:33 and follow transcript
10:33
Now, let's say before the add drop, in a course, do we have 10 up to 45 students, no. Before the add
drop, do student enroll into any courses? No. So that's why. We have to relax. Notice that once we
specify this constraints within the class diagram, we have to always follow this constraints. Then we
specify it in the class diagram all the time. Now, let's say before the add drop, you allow a student to
enroll into no courses. Also you allow a course to have no students just before the add drop. Then
somehow you have to relax the constraints and just say that. A student may enroll into zero up to
five courses and then a course may have zero up to 45 students. Then some of you may say then
from the model, how do I know that after the add drop, a students should enroll into at least one
course and also a course should have at least 10 students. Notice that, in UML we allow a
dominance. Now, you can draw a little note here say that, after the add drop, we should have at least
10 students in a course and then here you should say that a student should enroll into at least one
course after the add drop. If we are talking about the multiplicity, then we have to follow all the time,
we have to relax the requirements and we have to make it like a student can enroll into zero up to
five courses and it cost me zero up to 45 students just because before the add drop we may have no
student in the course and student may enroll into no courses before the add drop. For unary
association, we also have to specify what we call role name. Usually the role name is going to be
obvious for binary association. Because if we say a person they work for a company, then once I
write the role should be employee and the other side the role should be employer. Just because it's
obvious for binary association to role name is going to be obvious for binary association so we may
skip them for binary association. Unary association, we have to provide the role names on the two
sides just to make sure that we know that one side is going to be the boss and the other side is
going to be the worker. Why? Because eventually when you store the data within your system,
instead of simply saying that we have a link, for example between John and Frank and then between
Sarah and Bill, we also need to provide a label or the role name, saying that, John is the boss and
Frank is actually the worker for the boss. We've done this labels, we've done the role names, we
only have to link then we cannot determine who is actually the boss, who is actually the worker.
That's why for unary association is always required to provide the role names under the class
diagram. But for binary associations or tannery associations, we may skip them.
Play video starting at :14:6 and follow transcript
14:06
Then the last type of association that I'm going to cover in this lecture is what we call aggregation or
composition. Composition we use a whole adornment. Then if you are using a hollow adornment,
then the multiplicity on this side is going to be zero up to one. That means a disk may be associated
with zero computer or one computer, if it's a hollow adornment. When we are using a hollow
adornment, we have a special meaning. It means that it's going to be part of something, for example
the disk is going to be part of a computer. When we have the meaning part of, we're going to use
adornment. If it's hollow, then that means the multiplicity that we have on this side, on the computer
side is going to be 0..1 that means a disk. It's going to be associated with zero up to one computer.
When it's zero, when the lower part is zero, that means the participation is going to be optional. That
means the disk can exist alone without a computer, that's what we mean by optional participation.
But let's say if we are using a filled diamond, then the multiplicity becomes one dot, dot one. A room
is going to be associated with exactly one building. That means the participation is going to be
mandatory. That means the room has to somehow associated with a building. The room cannot exist
alone without a building. That's the difference between a hollow diamond and a filled diamond.
Whole diamond means part of, filled diamonds also mean part of but hollow diamond means the
participation is going to be optional and filled diamond means the participation is going to be
mandatory. That means the existence of room depends on building. When participation is optional,
that means existing of, for example, hard disk does not depends on computer. We use application or
composition only when we want to specify the meaning part of. When something is really part of
something, we use aggregation or composition. When the participation is optional, we say that we
have aggregation, we use whole diamond. When the participation is going to be mandatory, we use
a filled diamond, that means composition.
Play video starting at :17:12 and follow transcript
17:12
Some of you may ask, how do I know whether we're going to use a whole diamond or filled
diamond? One way to think about it is going to be this way, think about when you destroy a
computer, do you destroy all the hard disk? Let's say, if you destroy all the computers, you also
destroy all the hard disk, then you have to make it filled diamond because the existence of hard disk
depends on computer. But let's say, when you destroy a computer, you may keep all the hard disk,
you may still keep all the hard disk, then you have to make it hollow because existence of hard disk
does not depend on a computer. In this case, we have to make it filled. Just because when we
destroy the building, it's natural that we're going to destroy all the rooms within the building. That's
why we have to make it filled to denote that the participation is going to be mandatory. Just because
when we destroy the building, we can also destroy all the rooms within the building. That means the
participation of room is going to be mandatory. That's another way to think about whether we have to
use hollow diamond or filled diamond when we are talking about aggregation or composition. But be
very careful when you're using aggregation or composition, don't replace every single has or have
associations with aggregations or compositions. Let me give you an example, Kenneth has a bank
account. But bank account use not part of me, it's not something that is inside my body. Then you
should not make it part of Kenneth. You should not use aggregation or composition between person
and account because account is not part of the customer. That's why you have to be very careful.
The decision to use aggregation is a matter of judgment and is also a design decision. It's not wrong
to use association rather than aggregation in your project or in your assignment. If you're using
aggregation, you provide more meanings in your diagram because whenever we see a diamond, we
know that something is going to be part of something. You provide more semantics in your diagram.
But it's not wrong to simply use an association between two things to replace aggregation or
composition. That's why it's important that you think twice before you use aggregation or composition
in a class diagram. Think about whether something is really part of something before you use a
diamond within your class diagram. That's all I want to cover in this lecture.
Association-Class
Hi. In this lecture, we will talk about some additional components that you can use for drawing UML
class diagram. Now let's start with an example.
Play video starting at ::12 and follow transcript
0:12
Let's say we want to build a system to keep track of student and random information and we have a
set of students, and we have a set of courses and we keep track which student enrolled into which
course. For example, Macro enrolled into COMP 3111, COMP 3021, and also COMP 3311. Now let's
say if we wanted to also keep track an attribute like grade, then where should we store the grade?
There are different options that we can use.
Play video starting at ::46 and follow transcript
0:46
The first option is that, we may store grade as an attribute under student. For example, for a student,
we stored a grade for COMP 1212 and also for COMP 2012. Is this okay? No, this is not okay
because we don't know exactly how many attributes that we need for a particular student, so this is
not okay. This is the problem, we don't know how many grade attributes that we need for each
student. Option number 2 is that can we use a multi-valued attribute for grade? For example, under
student, we have an attribute called grade which is an array. Then we can store multiple grades
under student. Is this okay? No, this is also not okay because we don't know which grade maps to
which course. Now understood that we just have a set of grades, but we don't know exactly which
grade maps to which course. This option, option number 2 is also not okay. Then let's talk about the
next option which is using an associate class. This is another component that we can use for
drawing UML class diagram. Whenever the association has properties, then we can model the
properties of an association using attributes under the association. For example, when students
enroll into a course, then we tried to keep track the grade, and we keep track a grade under the
association. This is the situation, for example, Macro enrolled into COMP 3111 and then he gets an
A plus. Then we start this attribute under the link between Macro and COMP 3111. As another
example, let's say Jason takes COMP 3111 and then he gets an A. Then again we start the grade A
under this link, then think about it, is this option okay?
Play video starting at :3:2 and follow transcript
3:02
I would say no. Why? Let me give you an example. Now let's say we're using this model we have
students and then students enroll into different courses. We try to keep track older grades using an
association class enrolls in and then we try to keep track the attribute grade using this association
class. Then under student, we may have many students. For example, we may have Kenneth, we
may have Gibson, we may have Desmond and also we may have Dave. They are all students within
the university. Then we have different causes for example, we have COMP 1001, we have COMP
3111, we have COMP 3311 etc. Now let's say we have this situation. Let's say Kenneth enrolls into
COMP 3111 in the previous semester, then he failed. We try to sort the grade fail using association
class. Then now let's say he takes COMP 3111 again in the semester and now this time he gets an A
plus. Now using this model, can we store this information, yes or no? No. Now let's say we have a
pair of instances, let's say Kenneth and COMP 3111 being connected using an association, using a
link. Then notice that this is what you have to keep in mind. Notice that once a pair of instances they
are related, they are related. We cannot relate the same pair of instances using two different links so
now we can only keep one of the two links, but not both of them. Maybe we can simply keep track
the most recent link, which is Kenneth enrolls into COMP 3111 again in the semester and then he
gets an A plus. This is what we can keep track using this particular model and this is the restriction
of this model. Again, keep in mind once they're related, they're related. We cannot relate the same
pair of instances using more than one link. This is not allowed and then we have to remove one of
the two links.
Play video starting at :5:51 and follow transcript
5:51
If you want to keep track all the historical information, for example, Kenneth enrolled into COMP
3111 in the previous semester and then he failed, and then he takes it again in this semester and he
gets an A plus. This information, you cannot store it using this particular model, so now how do we
fix the problem? Because using this model, it's not allowed to have a student to enroll into the same
cause multiple times through the association class enrolls in. Then we may have to use a more
complicated model, which is this one. Now, students, they are not enrolled into different courses they
are enrolled into different offerings of the course. What do we mean by offering? Now let me try to
draw the example so we may have different students and we have also a set of courses. Then we
relay students and courses to get our using offering. Now student, they are not ticking courses they
are taking a particular offering of a course and then we try to keep track of grade of a particular
offering. In case students takes and enrolls into different offerings. What do I mean by offering?
Kenneth, we may have like set of students, like Kenneth, Gibson and then Dave and then maybe
Desmond. Then we have a set of courses, maybe COMP 3111, and also COMP 3311 etc. Under a
course, we can have different offerings in different semesters. That means we may have COMP
3111 for 2019 and also COMP 3111 in spring 2020. They are different offerings of COMP 3111. Now
using this model it's possible that Kenneth enrolled into COMP 3111 for 2019 and then he gets an F.
Then he enrolls into COMP 3111 in spring 2020 again, and then he gets an A plus. Now we have
relating students and courses together through offerings and by using this model, we can keep track
of all historical information. For example, Kenneth enrolls into COMP 3111 in 2019 and he gets an F.
Kenneth also enrolls into COMP 3111 in spring 2020 and then finally he gets an A plus. Now using
this more complicated model, we can actually keep track of all the historic information and we allows
students to enroll into the same course multiple times through different offerings in different
semesters.
Generalization
The next component that I am going to cover in this lecture is what we call it generalization or
inheritance. The definition of generalization is a relationship between classes of the same kind. We
may have a class, and then we may specialize a class into different sub classes which are of the
same kind. Now, let me show you an example because it's easier to explain what is generalization
using an example. Now this is an example. Let's say we're trying to build a software system for a
bank. Then within application domain we have different accounts. From the attributes, we have
different types of accounts. For example, some of the accounts they are check accounts, and then
some of the accounts they are savings accounts. Then some of the attributes lets say service charge
is going to apply to only check accounts, then interest rate is going to applies only to savings
accounts. Then the operation pay interests, it will only applies to savings accounts, etc. Then instead
of saying that we only have account, we can specialize account into two types. One is what we call
check account, and then another one is what we call saving account. This is what we call doing
specialization top down. From account, we can see that there is an attribute called the discriminator.
Account type is the discriminator. To discriminate account into two different types, savings account or
check account. Then we can do it top down, starting from account we specialize into two types of
accounts, check account and savings account. We perform this specialization using a triangle. A
triangle means we have generalization. We try to specialize accounts into two types, check account
and savings accounts. Under a check account we have the additional attribute called service charge.
Then under saving account we have the additional attribute called interest rate, and we have the
additional operation called pay interest.
Play video starting at :2:30 and follow transcript
2:30
We can also do it bottom up. For example, we can see that we have two classes. They are pretty
similar to each other. For example, account and credit card. You can see that the attributes they are
similar, and the operations they are similar. Then we can see that they are similar objects that we
have or similar things that we have within the class diagram. Then we can perform generalization.
Then we generalize account and credit card as a more general class, call account. Under accounts
we have two different types of account, one is bank account and then another one is credit card
account. This is how we perform generalization or inheritance bottom up, because we see that we
have two very similar objects within class diagram. Then somehow we can perform generalization
and then create a more general class called account. Then account specialize into bank account and
credit card account, and this is what we call inheritance. The good thing of inheritance instead, we
can extract the common attributes, relationships, and also operations, and put them into super class.
In our example, we say that bank account and credit card accounts, they share common attributes
like account number and amount, and also they share the common operation balance. Then we can
put all this things in the super class, and they will be shared by the sub classes. For bank account,
we have account number, amount, balance, the operation deposit and withdraw, and for credit card
account we have two attributes, account number, amount and also balance the operation balance
and also this additional operations for credit card. This attributes and operations, they are shared by
the sub classes. This is the good thing of inheritance. You can define all attributes and operations
and also the relationships just once, and then they will be shared by all the sub classes.
Play video starting at :5: and follow transcript
5:00
By putting the attributes or by defining the attributes and operations in just one place. Again, we
reduce redundancy of description and promote reusability of descriptions and also simplify
modification of descriptions. Because if we want to somehow modify the things that we have in the
supertype, we just modify the supertype or superclass. Or if we want to modify a particular type or a
particular subtype of class, then we just simply modify that particular subclass. We don't have to
touch the other things. This is going to help simplify modification of descriptions. This is another
example of inheritance. We can define additional properties under the subclasses. For example,
checking account we have service charge, saving account we have some additional properties. Now
let's say we define another withdraw operation under the subtype. We can see that we also have the
withdraw operation under the supertype. Then notice that if we define another withdraw operation
here under this subtype, it's going to override the withdraw operation that we have defined in the
supertype. That means if an account is a checking account, then it's going to use the operation
under the subtype to perform withdraw rather than using this operation under the supertype. That's
what we mean by overriding. Overriding means, if we define the same operation again in the
subtype, we going to use the operation defined in the subtype. In this example we define withdraw
again in the subtype, then we're going to use withdraw operation under the subtype instead of using
the withdrawal operation under the supertype. This is what we mean by overriding the method of a
superclass operation. This is what we mean by single inheritance and then we can have multi-level
of inheritance. For example, let's say we have another type of account which is checking and saving
together. Then we can simply apply another level of inheritance and then we say that we have a
checking saving account.
Play video starting at :7:24 and follow transcript
7:24
Notice that discussion of multiple inheritances is beyond the scope of this course. In your project or
in your exercises, you may use multiple level of inheritance. But try to avoid having more than three
or four levels of inheritance. Because if you have more and more levels of inheritance, its going to
make your class diagram more difficult to read and more difficult to understand.
Play video starting at :7:57 and follow transcript
7:57
Also make sure that all the other stakeholders they can easily understand your model. Try to limit the
level of inheritance to only two or up to three levels. Don't use four or five or even six levels of
inheritance. It's going to make your diagram very difficult to read. Now, what if we have this special
situation. Let's say PG students they can enroll into zero up to three courses. Then UG students they
can enroll into one up to five courses. Then again, instead of saying PG students they enroll into
some courses, and UG students they enroll into some courses, we can simply say students they
enroll into some courses. But now we have to relax the requirement because PG students they're
going to enroll into zero up to three courses, UG students they're going to enroll into one up to five
courses. Again, then we have to relax and then say that students they enroll into zero up to five
courses. Then some of you may say, we missed the information about like PG student it's going to
be zero up to three courses and UG students it's going to be one up to five courses. Notice that
again, in the class diagram you can always put a note beside and say that, for example, PG student
it's going to be zero up to three courses and then UG students it's going to be one up to five courses.
You can always provide additional information using a note. In generalization we can have what we
call abstract class. We define abstract class using Italic. You can see that this account here is in
Italic. That means this class is an abstract class. The definition of abstract class is that an abstract
class is a class that has no direct instances. That means we don't store any instances here under
accounts. All the instances they are either checking accounts or savings accounts. We don't have
any instances stored under this class account. That's what we mean by abstract class. Abstract
class, we use it for modeling purpose. From this class diagram, we know that check accounts and
saving accounts is under an abstract class called account rates, so they are all accounts. You can
get some additional meaning from this abstract class, but we don't store any instances under this
class called account. We have all instances under checking or saving but not account. Another thing
that we need to define for generalization is the disjoint coverage. The coverage can be either
overlapping or disjoint. What do we mean by overlapping? In this example we can see that players,
they can be either playing tennis or soccer. We make it overlapping. That means some of the players
they are playing tennis and soccer at the same time. This green part. Some players, they may be
playing tennis and soccer at the same time. Then if that's the case, then we have to put the
constraint here saying that this generalization constraint is overlapping. Sometimes it may be
disjoint. That means it's not overlapping. We have accounts and then we have different types of
class, personal and business, and they are disjoint. That means we don't have an account with just
both personal and business. It's going to be disjoint. It's either personal or business but not both of
them at the same time. Another constraint that we can specify for generalization is what we call
completeness coverage. It can be either complete or incomplete. Now let's say under university we
can have UG student or PG student. These are the only two types of students that we have within a
university. Then we can simply say that within the university, we only have UG and PG students and
they are complete. We do not have another type of student. We only have UG and PG students.
That's it. If we make it incomplete, for example, trees can be either this type, that type, or the other
type, if we make it incomplete, then that means we may have some trees which are not of these
three types. All of these three types. Then we're going to use the coverage constraint incomplete.
For example, for players, we may specialize into tennis and soccer. Then some of the players, they
may be both tennis and soccer players at the same time. Then we make it overlapping. We make it
incomplete because in this diagram, there may be some other types of sports that we have not
specified in the diagram. We may even have, I do know swimming and also some other types of
sport. Then we have to make it an incomplete. For trees, it's going to be disjoint and incomplete. For
courses, it's going to be overlapping and complete because we only have either UG courses or PG
courses, so that's why it's complete. It's overlapping because some of the courses they may be for
both UG and PG students. For university students, we have two types; UG or PG. It's going to be
disjoint. It's going to be either UG or PG. We only have these two types of students under the
application domain, so it's going to be complete. Based on what we call the coverage types, we have
to specify the constraints for generalizations. Now let's study another example. Let's say we're trying
to pay tuition fee within the university and there are different types of methods; cash, credit card, or
debit card. Then for payment, say it going to be overlapping, completes, disjoint, complete,
overlapping, incomplete, or disjoint, incomplete. I will say it's going to be overlapping because you
can pay part of your tuition fee using cash and then another part of your tuition fee using credit card.
It's possible. I will say it's going to be overlapping. Is it complete? I will say no, because there are
some other ways that you can pay your tuition fee. For example, you can use Internet banking to pay
your tuition fee. It's not limited to cash, credit card, and debit card only. That's why for this example, I
will say the coverage constraint is going to be overlapping and is going to be incomplete.
Then there are also some rules for you to eliminate irrelevant association. If some of the
associations they are irrelevant to the domain model, you eliminate them. If some of the associations
they are actually operations, again you can eliminate them. There are some ternary association, you
may consider decomposing them into multiple binary associations. Because as I've said before, we
try to avoid using ternary associations, because it's going to make your diagram more difficult to
read. Then if some of the associations, they are derived association, so for example, you can use
this path. A to C, C to B, to go from A to B or you can directly go from A to B. If you can get the same
inflammation using this path A, C, B, and also this path A, B, then you can eliminate one of the two
halves. But you have to be for a careful before you remove a path in your class diagram. Now let's
study an example from our exercise. Now let's say we have this class diagram. In this class diagram,
we try to keep track all transactions for different accounts and the account state belongs to different
customers. Now we can see that we have a cycle in this diagram. Can we remove one of length less
say, makes in the class diagram. Now let's study the example in more details. Let's say this is
actually the information being stored under dissolver system. Transaction T1 is actually a transfer
between A1 and A2 from customers C1 and C2. Now let's say we only have the associations is
against and also holds. Can we tell which customer initiated this transaction? Whether the
transaction is actually initiated by C1 or C2. Can we tell? No, because using the information being
stored under our system, we can actually tell this transaction is actually initiated by C1 or C2. That's
why you also need the association Makes to tell us exactly who may or who started this transaction.
Now with this association, now we can tell for example, T1 is actually initiated by customer C1 using
additional link from the association Makes. So in this very special case, we cannot remove the
redundant path just because the two paths, they have two different meanings. One of their path
means transaction is against which accounts and the accounts there from which customer. The other
path, means who actually initiated the transaction. That's why we have to keep both the two paths,
because they have two different meanings. In a gang of some of the associations state describe
implementation constructs. You may eliminate them. For attributes. You double-check read over
those attributes, they are closely related to a class or an object within your class diagram. Because a
class should be simple and coherent. If the attributes day on not related to a class, then you may
eliminate them. If some of the attributes they should be classes, then you make them classes. If
some of the attributes they should be in an association class, then you should create an association
class and put those attributes within that association class. If there's some ID that you can use to
identify an instance of an object, you eliminate all the IDs because IDs are object identifier's, they
should not be included in the domain model. As an example, in the first exercise, we have IDs as
attributes and we have to remove all of them.
Play video starting at :4:17 and follow transcript
4:17
Because they are not the real properties of the objects, they are simply artificial numbers. To make
sure to our class diagram is going to be simple and also easy to read, we only keep the necessary
attributes and ignore all the IDs. Then finally, for each class we have to specify all the attributes, and
then for each attribute we have to specify the name, type, and also multiplicity all of the activity. For
each association we have to provide a name for the association. If is unitary association, we also
have to provide row names and also maybe multiplicity and also association class if needed. That's
all I wanted to cover in this lecture.