Object-Oriented Design Object-Oriented Design The first stage of the two-stage design process is Conceptual design. Conceptual Design : It provide your initial thoughts for how the requirements will be satisfied. Identifying components, their responsibilities and connections. Conceptual design is an early phase of the design process, in which the broad outlines of function and form of something are articulated. It includes the design of interactions, experiences, processes, and strategies. Elicitating Requirements : It involves not only listening to what the client is telling you, but asking questions to clarify what the client has not told you. User Story : --Once a requirement is elicited, it needs to be expressed in some form. One technique for expressing a requirement is called a user story. A user story is simply a requirement, often from the perspective of an end-user, which is stated in natural language. As a ______, I want to ______ so that ______. --Put the user role into the first blank. This may be quite simple for software in which there is generally only one type of user, or a bit more complex in cases where the software may do different things for different people. Either way, this clarifies who wants to use this feature. --In the second blank, put the goal that the user role wants to achieve. This will lead to some feature that you want to implement. --After so that, put the reason why the user role wants this goal. Sometimes this clause is omitted if the benefits are clear and generally known. --After you fill in a user story, you can apply object-oriented thinking to it to discover objects and possibly further requirements! Conceptual Mockups : It is a scale or full-size model of a design, used for teaching, demonstration, design evaluation, promotion, and other purposes. A mockup is a prototype if it provides at least part of the functionality of a system and enables testing of a design. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design CRC Cards : CRC stands for Class, Responsibility, Collaborator. CRC cards are used to record, organize and refine the components in your design CRC cards help you to organize your components into classes, identify the responsibilities and determine how they will collaborate with each other. Example: NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design The second stage of the two-stage design process is Technical design. Hint: This is when you will define the structure of the code and start turning your mockups into classes. Techinical Design : --To describe and refine the solution, so that it is clear enough for developers to implement as working software. ---In a technical design, you start specifying the technical details of each component. This is done by splitting components into smaller and smaller components that are specific enough to be designed in detail. Generally the phrase 'technical design' refers to project activities that take place after the detailed design (or 'developed design' or 'definition') has been completed, but before the construction contract is tendered or construction begins. Many developers have noticed the same thing, and there are generally three categories of objects. Entity Objects Entity objects are the most familiar, because they correspond to some real-world entity in the problem space. If you have an object representing a chair in your software, then this is an entity object. If you have an object representing a building or a customer, these are all entity objects. Generally, these objects will know attributes about themselves. They will also be able to modify themselves, and have some rules for how to do so. When you are identifying objects to include in your software and breaking down those objects into smaller objects, you will initially get entity objects. Boundary Objects : Boundary objects are objects which sit at the boundary between systems. This could be an object that deals with another software system - like an object that obtains information from the Internet. It could also be an object with the responsibility of showing information to the user and getting their input. If you program a user interface - the visual aspect of software - you are probably mostly working with boundary objects. Any object that deals with another system - a user, another software system, the Internet - can be considered a boundary object. Control Objects : Control objects are objects which are responsible for coordination. You will discover control objects when you attempt to break down a large object, and find that it would be useful to have an object that controls the other objects. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Language Evolution : Cobol, Fortran : (Introduced with Global variables only) --1960 Algol68, Pascal : (Introduced Local variables, Abstract data type) --1970 C, Modula-2 : seperate files(Header file), But still Abstract data type cannot extent another. --mid 1970 OOP : abstract data type – easy writes Structure system around abstract data types i.e. Classes Abstract data type can extent another.(Inheritence) --1980 4-Design Principles : 1>Abstraction : Simplifies a concept(Class), which ignores unimportant details. Rule of Least Astonishment: The abstraction captures essential attributes and behavior for concept with no surprises and no definations that fall beyond it’s scope. 2>Encapsulation : --> Act’s as a capusle, containing something inside. Some of which you can access from outside, and some of which you cannot. *Bundle attributes and methods together into self contained objects. *Expose certain data and functions of the object, that can be accessed from other objects. *Restrict access to certain data and functions, only within that object. Def: Encapsulation forms a self-contained object by bundling the data and functions it requires to work, exposes an interface whereby other objects can access and use it, and restricts access to certain inside details. *It helps with data integrity. Certain attributes and methods of a class can be restricted from outside use. *It can secure sensative information. (Can use some values for analysis, but never reveals them) *It helps with software changes. i.e. the accessible interface of a class remains same, while the implementation of attribute and method can change. Black Box Behaviour: *Class that you can not see for details about, how attributes are represented or how methods compute their result. *We provide input and obtain output, by calling the methods. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design 3>Decomposition: *It is taking a whole thing and dividing it up into different parts. *Or, on the flip side taking a bunch of separate parts with different functionalities, and combining them together to form a whole. *Decomposition allows you to further break down problems into pieces that are easier to understand and solve. *A complicated whole thing can be composed out of constituent, separate, simpler parts. *Important issues to understand are how the parts relate to the whole, such as : fixed or dynamic number their lifetimes, and whether there is sharing. 4>Generalization: *It helps us to reduce the amount of redundancy when solving problems. *We can generalize the actions into its own method, and simply pass it through a different set of data through arguments. *Generalization can be achieved by classes through inheritance.(Super/Sub Classes) eg: (Animal SuperClass -----> Dog, Cat SubClasses) *D.R.Y Dont Repeat Yourself. Developers use technical diargrams called UML-Class-Diagrams to express their design: UML-Class-Diagrams : CRC cards are only good for prototyping and simulating higher level designs. To guide implementation, you need a technique that would be more like a blueprint. A UML Class Diagram, or just Class Diagram for short, allows you to represent your design in more detail than CRC cards can but it's still visual. Class Diagrams are much closer to the implementation and can easily be converted to classes in code. Food Class (Abstraction) NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Diff. b/w CRC-Cards and Class-Diagrams: ---> You could certainly use CRC cards for abstracting an object such as a grocery food item but there are simply too many ambiguities that prevent a programmer from translating a CRC card to code. ---> One ambiguity is that a CRC card does not show a separation between properties and operations. They are all listed together. Class Diagrams are very close to implementation, making the translation to Java very easy. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Encapsulation with Class Diagrams: - means private + means public # means protected --> Getters and Setters are used to get & set private sttributes. Its acts like a safe gateway to manupulate private data fields. Getters and Setters can have other bussiness related implementations, hidden from outside world. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Decomposition: Association: Association is some relationship. This means that there is a loose relationship between two objects. These objects may interact with each other for some time. For example, an object of a class may use services/methods provided by object of another class. Aggregation: Aggregation is a “has-a” relationship where a “whole” has “parts” that belong to it. There may be sharing of “parts” among the “wholes” in this relationship. The “has-a” relationship from the “whole” to the “parts” is considered weak. What this means is although “parts” can belong to the “wholes”, they can also exist independently. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Composition: Composition is an exclusive containment of parts, otherwise known as a strong “has-a” relationship. What this means is that the “whole” cannot exist without its “parts”. If loses any of its “parts”, the “whole” ceases to exist. If the “whole” is destroyed, then all of its “parts” are destroyed too. Usually, you can only access the “parts” through its “whole”. Contained “parts” are exclusive to the “whole”. Generalization (Inheritance) The superclasses are the generalized classes, and the subclasses are the specialized classes. In Java, a protected attribute or method can only be accessed by: the encapsulating class itself all subclasses all classes within the same package The inheritance that we have been looking at is called implementation inheritance. For Java, only single implementation inheritance is allowed. Well a superclass can have multiple subclasses. A subclass can only inherit from one superclass. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Generalization(Interfaces): --> An interface only declares method signatures, and no constructors, attributes, or method bodies. --> It specifies the expected behaviors in the method signatures, but does not provide any implementation details. In object oriented languages, polymorphism is when two classes have the same description of a behavior, but the implementations of the behavior may be different. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design There is one other form of inheritance that we haven't looked at called multiple inheritance. This is when a subclass has two or more super classes. While this is possible to do with other object oriented languages, like C++, JAVA doesn't support Multiple Inheritance. This is because inheriting from two or more superclasses can cause Data Ambiguity. When your subclass inherits from two or more superclasses that have attributes with the same name or behaviors with the same method signature, how do you distinguish between them? Since JAVA cannot tell which one you would be referencing, it does not allow for multiple inheritance so that data ambiguity is not an issue. Interfaces do not run into this issue. In JAVA, a class can implement as many interfaces as we want. This is because of the nature of interfaces. Since they are only contracts and do not enforce a specific way to complete these contracts, overlapping method signatures are not a problem. A single implementation for multiple interfaces with overlapping contracts is acceptable. There is no ambiguity here because the Person class only has one definition of a speak method, and it is the same implementation for both interfaces. This is JAVA's approach to avoid the issue that is introduced with multiple inheritance. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Evaluating design complexity: This was observed in a psychology paper by George Miller in which subjects had to recall 1 to 14 random sounds and images. Subjects started to fail at recall when the number reached around 7. The metrics you will use to evaluate design complexity are coupling and cohesion. Coupling focuses on complexity between a module and other modules. Cohesion focuses on complexity within a module. These two ideas will help you to better apply object-oriented design principles and achieve a more manageable system. Coupling: --> If your module is highly reliant on other modules, you would say this module is tightly coupled to others. This is like having puzzle pieces. --> On the other hand, if your module finds it easy to connect to other modules, this module is loosely coupled to others. This is like Lego. You want coupling for your module to be loose or low, not tight. When evaluating the coupling of a module, you need to consider degree, ease, and flexibility. --> Degree is the number of connections between the module and others. With coupling, you want to keep the degree small. --> Ease is how obvious are the connections between the module and others. With coupling, you want the connections to be easy to make without needing to understand the implementations of the other modules. --> Flexibility is how interchangeable the other modules are for this module. With coupling, you want the other modules easily replaceable for something better in the future. Coupling only concerns complexity between a module and other modules, but you also need to consider complexity within the module. That's where you would look at cohesion. Cohesion: --> It represents the clarity of the responsibilities of a module. --> If your module performs one task and nothing else or has a clear purpose, your module has high cohesion. --> On the other hand, if your module tries to encapsulate more than one purpose or has an unclear purpose, your module has low cohesion. You want high cohesion. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Seperation of Concerns: One goal of software design principles is to help us create a system that is flexible, reusable and maintainable. One of these principles is called separation of concerns. A concern is a very general notion, basically it is anything that matters in providing a solution to a problem. Eg: --> There is low cohesion in the SmartPhone class, because we have behaviors that are not related to each other. --> The camera behaviors do not need to be encapsulated with the behaviors of the phone in order for the camera to do its job. --> Furthermore our smartphone components do not offer us any modularity. We cannot access the camera or the phone separately if we were to build another system that required only one or the other. We cannot replace our current camera with a different camera, or replace it with a completely different object, without removing the code for the camera completely in this class. Our SmartPhone class has two concerns: To act as a traditional telephone To be able to use the built-in camera to take pictures. Now that we have identified these two different concerns, we can separate them out into their own more cohesive classes and encapsulate all the details about each into functionally distinct and independent classes. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Now This allows our smartphone to provide the functions of both the camera and the phone, while keeping the functionalities of either one separate and hidden from each other. The camera and phone know nothing about the other but are still composed by this SmartPhone class. Cohesion is high now. The tradeoff is that we have increased coupling in our system. Because the smartphone class needs to know about the camera and phone interfaces and is indirectly dependent on other classes. Note: Our goal is to create flexible reusable, and maintainable code. Separation of concerns creates more cohesive classes using abstraction, encapsulation, decomposition, and generalization. This creates a system that is easier to maintain because each class is organized so that it only contains the code that it needs to do its job. Modularity is increased in turn, which allows developers to reuse and build up individual classes without affecting others. In our smartphone example, it is clear where the boundaries of each class are. However, real-world problems may not be so obvious. Deciding how to abstract, encapsulate, decompose and generalize to address the many concerns for a given problem is at the core of designing modular software. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Information Hiding: --> Information hiding allows models of our system to give others the minimum amount of information needed to use them correctly and hide everything else. --> Information hiding allows a developer to work on a module separately with other developers needing to know the implementation details of this module. They can only use this module through its interface. --> In general things that might change, like implementation details, should be hidden. And things that should not change, like assumptions, are revealed through interfaces. There are four levels of access in Java: public: access from anywhere protected: access to subclasses and in package default: access in package private: access to the class itself only Conceptual Integrity: Conceptual integrity is about creating consistent software. It's making decisions about how your system will be designed and implemented, so that even if multiple people worked on the software, it would seem as if there was only one mind guiding all the work. There are multiple ways to achieve conceptual integrity: 1. Communication 2. Adopting certain agile development practices like daily stand-up meetings and sprint retrospectives, where team members can agree to use certain libraries or methods when addressing certain issues, can help to maintain the consistency of the code. For example, team members can all follow a particular naming convention. 3. Code reviews are systematic examinations of written code. It's similar to peer review in writing. It's often used to find mistakes in the software, but also to keep different developers consistent with each other. 4. Well defined design 5. Unifying concepts to avoid special cases can provide consistency in your software. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Inheritance Issues: Misusing inheritance can lead to poor code. That happens when design principles are used improperly, creating more problems than they are meant to solve. There are a few points to be aware of when implying inheritance: 1. First, you need to ask yourself, am I using inheritance to simply share attributes or behavior without further adding anything special in my subclasses? If the answer is yes, then you're misusing inheritance. 2. The second indication of improper use of generalization is, if you break the Liskov Substitution Principle. The principle states that a subclass can replace a superclass, if and only if, the subclass does not change the functionality of the superclass. Usefull Examples: An example of bad inheritance can be seen in the Java Collections Library. Have you ever used the stack class in Java? A stack is understood as first in and last out data structure. It has a small number of well defined behaviors like peak, pop and push. This is not the case in the Java stack class, because the stack class inherits from the vector class. This means that the stack class is able to return an element at a specified index, retrieve the index of an element and even insert an element into a specific index. These are not behaviors expected from a stack, but because of poor use of inheritance, they are allowed in Java. A smartphone is a good example of where decomposition works better than inheritance. A smartphone has characteristics of a phone and a camera. It does not make sense for us to Inherit from the phone and then add camera methods to the subclass smartphone. We should be using decomposition to extract out the camera responsibilities, and put them in their own class. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Sequence Diagram: A sequence diagram describes how objects in your system interact to complete a specific task. Think of a sequence diagram like a map of conversations between different people, where this map follows all the messages sent from person to person. Eg: Components/Elements: (Give a Title to the sequence diagram) 1. First you use a box to represent role play by an object. The role is typically labeled by the name of the class for the object. 2. Second, you use vertical dotted lines, known as lifelines, to represent an object as time passes by. 3. Actors/Users are drawn as Stick figures. 4. Finally, you use arrows to show messages that are sent from one object to another. If one object sends a message to another object or objects, we denote this by drawing a solid line arrow from the sender to the receiver. To return data and to control back to initiating objects, we would use a dotted line arrow. -->When an object is activated, we denote this on our sequence diagram using small rectangles on the objects lifeline. You activate an object whenever an object sends, receives or it's waiting for a message. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design Like: Change TV Channel If the TV viewer does not know what channel they want, other sequences can occur. NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design State Diagram: ->A state diagram is a technique that you can use to describe how your system behaves and responds. ->State diagrams can describe a single object and illustrate how that object behaves in response to a series of events in your system. ->A state diagram illustrates object behavior by depicting the changing states of an object. ->These states change and respond to different events. ->A state is the way an object exists at a particular point in time. ->The state of an object is determined by the values of its attributes. When an object is in a certain state, it behaves in specific ways or has attributes set to specific values. Using UML state diagrams, you can express the different states of your objects and how the states will change when an event occurs. Activities are actions that are performed when in a certain state, and they're displayed at the bottom. There are three types of activities for each state, entry, exit, and do: ->Entry activities are actions that occur when the state is just entered from another state. ->Exit activities are actions that occur when the state is exited and moves on to another state. ->Do activities are actions that occur once, or multiple times while the object is in a certain state. Vending Machine Example: NAKUL-GOYAL : Email : LinkedIn : Github Object-Oriented Design EXTRA Model Checking: Model checking is a systematic check of your system's state model in all its possible states. Like Testing Basically, you check all the various states of your software and find that there are any errors by simulating different events that would change the states and variables of your software. So you check if the state model of your software contains some flaw. These checks are done using model checking software. Model checking is done after code has been written and before deployment to find any errors in the behavior of the software before it is released. The model description is written during the modelling phase. Model checking is only effective when the model description is complete and well thought out. Any issues in the model description may cause the model checker to misinterpret the system is behaviour. There are three different phases to performing model checking: Modelling Phase: will be provided in whatever programming language your system uses. You also describe the desired properties. During the modeling phase, you can perform some Sanity checks. These are quick checks that should be easy to do because they usually come from very clear and simple logic. It's like testing if a light bulb is working by flipping a switch on and off Running Phase: this is when you run the model checker to see how your model conforms to the desired properties that you've wrote in the modeling phase. Analysis Phase: This is where you check if all the desired properties are satisfied and if any are violated. Violations are called counter examples. Your model checker will provide descriptions of violations in your system so that you can analyze how it got to that state. -----------------------------------------------------x--------------------------------------------------------------- I have created this document while completing Coursera-OOP-Design course. THANK - YOU NAKUL-GOYAL : Email : LinkedIn : Github
Enter the password to open this PDF file:
-
-
-
-
-
-
-
-
-
-
-
-