0% found this document useful (0 votes)
101 views16 pages

Oose Unit 2

Uploaded by

Stargrazer campo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
101 views16 pages

Oose Unit 2

Uploaded by

Stargrazer campo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 16

OBJECT ORIENTED SOFTWARE ENGINEERING

UNIT-2

System Development is model building


The concept of system development as model building refers to the process of creating
computer support systems to assist organizations in achieving their goals. Just like architects
create models before constructing buildings, system developers create models to design and
build software systems. This approach helps in understanding the system requirements,
designing its structure, implementing it effectively, and verifying that it meets the desired
specifications.

Key stages in this process include:

● Requirement Model: This is the initial stage where the functional requirements of the
system are captured. It involves understanding what the system needs to do to fulfill its
intended purpose.
● Analysis Model: In this stage, the system's object structure is established to ensure
robustness and adaptability to changes. It involves breaking down the requirements into
manageable components and defining how they interact with each other.
● Design Model: The design model refines the object structure to fit the implementation
environment. It involves making decisions about how the system will be implemented,
including choosing appropriate technologies and architectures.
● Implementation Model: This is where the actual system is built based on the design
model. It involves coding, testing, and integrating various components to create the final
product.
● Test Model: In this stage, the system is verified to ensure that it meets the specified
requirements. Testing helps identify and fix any issues or bugs in the system before it is
deployed.

three key technologies that form the basis of this approach:

● Object-Oriented Programming (OOP): This paradigm allows developers to model


real-world entities as objects with attributes and behaviors, making it easier to manage
complex systems.
● Conceptual Modeling: This involves creating abstract representations of the system's
concepts and relationships, helping developers better understand and communicate the
system's structure and behavior.
● Block Design: This refers to breaking down the system into manageable blocks or
modules, each responsible for specific functionality. This modular approach simplifies
development and maintenance.
Seamless transition between the models and the need for traceability to ensure maintainability
is important. This means that changes made in one model should be reflected in others, and
there should be clear documentation of how each requirement is implemented throughout the
development process.

The goal of system development as model building is to create simple, understandable, and
adaptable models of the system that can effectively capture its requirements and facilitate
communication among stakeholders. These models serve as blueprints for building the actual
system and ensure that it meets the needs of the organization.

SDLC Models
Waterfall Model (Software Engineering) - javatpoint
Spiral Model (Software Engineering) - javatpoint
V-model (Software Engineering) - javatpoint
Incremental Model (Software Engineering) - javatpoint
Iterative Model (Software Engineering) - javatpoint

System development based on user requirements


Understanding user requirements is vital for the success of any systems engineering initiative.
These requirements capture what users expect from the system—defining the intended use and
value of the final product. It’s through a diligent analysis of user requirements that stakeholders
and engineers are aligned, ensuring that the outcome meets the practical needs with optimal
functionality.
A user requirement is a documented need of what a particular user or set of users requires from
a system to achieve an objective. These lay down critical guidelines for the design and
deployment of the system, encapsulating the desired user experience and functionality.
When the system development process is attentive to user requirements, it results in a product
that truly serves its audience. It begins with the identification of a user’s needs, and ends with
the delivery of a system that effectively fulfills those needs, bolstering both satisfaction and
usability.

Gathering User Requirements Simple Steps


Identifying user requirements is essential for developing a system that meets user expectations.
There are several effective techniques for gathering these insights. The following table outlines
some of these techniques along with their respective strengths and applications.

Technique Strengths Recommended Applications

Interviews Direct feedback, personal Early project stages, individual


engagement, in-depth stakeholder input
understanding
Questionnaires Quantifiable data, broad Large user groups, remote
coverage, easy to analyze stakeholders, statistical
analysis

Focus Groups Collaborative discussions, diverse Exploratory phases, product


perspectives, immediate interact concept testing

Observation/Ethnogr Real-world context, uncover User environment studies,


aphy implicit needs, behavioral insights usage pattern analysis

User Stories User-centric, narrative-driven, Agile development, feature


clear requirements specification

Use Cases System interaction detail, Functional requirements,


scenario-based requirements acceptance testing criteria

Prototyping Feedback on tangible product, User interface design, system


iterative design, engage users functionality demonstrations

Workshops Group collaboration, real-time Cross-functional team


clarification, brainstorming alignment, requirements
refinement

Documenting User Requirements Simple Steps


Once user requirements are gathered, it is essential to document them effectively, facilitating
clear communication and a shared understanding among all project stakeholders. The table
below outlines key methods for documenting user requirements, along with their primary
benefits and typical use cases.

Documentation Technique Primary Benefits Typical Use Cases

User Requirements Centralized repository, Formal projects, regulatory


Document (URD) comprehensive reference compliance, stakeholder
point alignment

Requirements Traceability Ensures each requirement is Complex systems, quality


Matrix (RTM) met, tracks progress assurance, change
management

Use Cases Clarifies functional Software design, end-user


requirements through functionality verification
scenarios

User Story Maps Visual representation, user Agile development, MVP


experience focus scoping, feature prioritization
Functional Decomposition Breaks down complex Identification of system
Diagrams processes, shows hierarchy functions, modular development

Business Process Models Illustrates processes, Workflow analysis, system


identifies user interactions integration planning

Concept of Operations Describes system use in Early system concept


(CONOPS) user environment validation, stakeholder
communication

Prototypes/Wireframes Interactive, user feedback User interface and experience


on design design, usability testing

Design Model:
The Design Model is a crucial stage in system development where the abstract representation
of the system, established during the Analysis Model phase, is refined and adapted to fit the
chosen implementation environment. Here are some key aspects of the Design Model:
● Refinement of Object Structure: The primary focus of the Design Model is to refine the
object structure defined in the Analysis Model. This involves specifying the attributes,
methods, and relationships of each object in more detail to ensure that it can be
effectively implemented.
● Mapping to Implementation Environment: Design decisions are made considering the
target implementation environment. This includes selecting appropriate programming
languages, frameworks, and technologies that align with the system's requirements and
constraints.
● Architectural Design: The Design Model also involves defining the overall architecture of
the system, including high-level components, their interactions, and the communication
protocols between them. This ensures that the system is well-organized and scalable.
● Interface Design: Designing user interfaces and APIs (Application Programming
Interfaces) is another critical aspect of the Design Model. This includes specifying how
users will interact with the system and how different components will communicate with
each other.
● Optimization and Trade-offs: Design decisions often involve trade-offs between various
factors such as performance, scalability, maintainability, and cost. The Design Model
aims to optimize these trade-offs to achieve the best possible solution within the given
constraints.

Implementation Model:
The Implementation Model is where the actual development of the system takes place based on
the decisions made during the Design Model phase. Here's what you need to know about the
Implementation Model:
● Coding and Programming: Developers translate the design specifications into executable
code using the chosen programming languages and frameworks. This involves writing
algorithms, implementing data structures, and integrating various components of the
system.
● Component Integration: Different modules and components developed during the
Implementation Model are integrated to form the complete system. This involves testing
individual components as well as the system as a whole to ensure that they work
together seamlessly.
● Database Design and Implementation: If the system involves data storage, the
Implementation Model includes designing and implementing the database schema, as
well as writing queries and scripts for data manipulation and retrieval.
● Testing and Debugging: Throughout the implementation phase, rigorous testing is
conducted to identify and fix defects or bugs in the code. This includes unit testing,
integration testing, and system testing to verify that the system behaves as expected.
● Documentation and Training: Documentation is created to describe the implementation
details, including code documentation, user manuals, and developer guides. Training
materials may also be developed to educate users and developers on how to use and
maintain the system.

Use-Case Model
The Use-case model is defined as a model which is used to show how users interact with the
system in order to solve a problem. As such, the use case model defines the user's objective,
the interactions between the system and the user, and the system's behavior required to meet
these objectives.

Various model elements are contained in use-case model, such as actors, use cases, and the
association between them.

We use a use-case diagram to graphically portray a subset of the model in order to make the
communication simpler. There will regularly be a numerous use-case diagram which is related to
the given model, each demonstrating a subset of the model components related to a specific
purpose. A similar model component might be appearing on a few use-case diagrams; however,
each use-case should be consistent. If, in order to handle the use-case model, tools are used
then this consistency restriction is automated so that any variations to the component of the
model (changing the name, for instance) will be reflected automatically on each use-case
diagram, which shows that component.

Packages may include a use-case model, which is used to organize the model to simplify the
analysis, planning, navigation, communication, development and maintenance.

Various use-case models are textual and the text captured in the use-case specifications, which
are linked with the element of every use-case model. The flow of events of the use case is
described with the help of these specifications.
The use-case model acts as an integrated thread in the development of the entire system. The
use-case model is used like the main specification of the system functional requirements as the
basis for design and analysis, as the basis for user documentation, as the basis of defining test
cases, and as an input to iteration planning.

Problem domain analysis


Problem domain analysis is a critical phase in software engineering that focuses on
understanding the problem space or the domain in which the software solution will operate. This
analysis aims to gain a deep understanding of the problem, its context, requirements,
constraints, and objectives before the actual development of the software begins. Here's a more
detailed explanation:

Understanding the Problem Domain:


● Gathering Requirements: The first step in problem domain analysis is gathering
requirements from stakeholders, users, domain experts, and other relevant sources. This
involves understanding the goals and objectives of the system, as well as the needs and
expectations of the end-users.
● Identifying Stakeholders: It's essential to identify all the stakeholders involved in the
problem domain, including users, customers, administrators, and any other individuals or
groups affected by the software solution.
● Domain Modeling: Domain modeling techniques, such as creating domain models, class
diagrams, and entity-relationship diagrams, are used to represent the key concepts,
entities, relationships, and behaviors within the problem domain.
● Understanding Constraints: Constraints, such as technical limitations, regulatory
requirements, budget constraints, and time constraints, must be identified and taken into
account during the analysis phase.

Domain Modeling - Software Engineering - GeeksforGeeks

Refactoring
A refactoring is a transformation of the source code that improves its readability or modifiability
without changing the behavior of the system. Refactoring aims at improving the design of a
working system by focusing on a specific field or method of a class. To ensure that the
refactoring does not change the behavior of the system, the refactoring is done in small
incremental steps that are interleaved with tests. The existence of a test driver for each class
allows developers to confidently change the code and encourages them to change the interface
of the class as little as possible during the refactoring.

For example, Pull Up Field relocates the email field using the following steps (Figure 10-3):
1. Inspect Player, LeagueOwner, and Advertiser to ensure that the email field is equivalent.
Rename equivalent fields to email if necessary.
2. Create public class User.
3. Set parent of Player, LeagueOwner, and Advertiser to User.
4. Add a protected field email to class User.
5. Remove fields email from Player, LeagueOwner, and Advertiser.
6. Compile and test

Then, we apply the Pull Up Constructor Body refactoring to move the initialization code for email
using the following steps (Figure 10-4):
1. Add the constructor User(Address email) to class User.
2. Assign the field email in the constructor with the value passed in the parameter.
3. Add the call super(email) to the Player class constructor.
4. Compile and test.
5. Repeat steps 1–4 for the classes LeagueOwner and Advertiser
Typically, refactoring applies a series of standardized basic micro-refactorings, each of which is
(usually) a tiny change in a computer program's source code that either preserves the behavior
of the software, or at least does not modify its conformance to functional requirements. Many
development environments provide automated support for performing the mechanical aspects of
these basic refactorings. If done well, code refactoring may help software developers discover
and fix hidden or dormant bugs or vulnerabilities in the system by simplifying the underlying
logic and eliminating unnecessary levels of complexity. If done poorly it may fail the requirement
that external functionality not be changed, introduce new bugs, or both.

By continuously improving the design of code, we make it easier and easier to work with. This is
in sharp contrast to what typically happens: little refactoring and a great deal of attention paid to
expediently adding new features. If you get into the hygienic habit of refactoring continuously,
you'll find that it is easier to extend and maintain code.

Forward Engineering
Forward engineering is applied to a set of model elements and results in a set of corresponding
source code statements, such as a class declaration, a Java expression, or a database schema.
The purpose of forward engineering is to maintain a strong correspondence between the object
design model and the code, and to reduce the number of errors introduced during
implementation, thereby decreasing implementation effort.
For example, Figure 10-5 depicts a particular forward engineering transformation applied to the
classes User and LeagueOwner. First, each UML class is mapped to a Java class. Next the
UML generalization relationship is mapped to an extended statement in the LeagueOwner
class. Finally, each attribute in the UML model is mapped to a private field in the Java classes
and to two public methods for setting and getting the value of the field. Developers can then
refine the result of the transformation with additional behavior, for example, to check that the
new value of maxNumLeagues is a positive integer. Note that, except for the names of the
attributes and methods, the code resulting from this transformation is always the same. This
makes it easier for developers to recognize transformations in the source code, which
encourages them to comply with naming conventions. Moreover, since developers use one
consistent approach for realizing classes, they introduce fewer errors.

Reverse Engineering
Reverse engineering is applied to a set of source code elements and results in a set of model
elements. The purpose of this type of transformation is to recreate the model for an existing
system, either because the model was lost or never created, or because it became out of sync
with the source code. Reverse engineering is essentially an inverse transformation of forward
engineering. Reverse engineering creates a UML class for each class declaration statement,
adds an attribute for each field, and adds an operation for each method. However, because
forward engineering can lose information (e.g., associations are turned into collections of
references), reverse engineering does not necessarily recreate the same model. Although many
CASE tools support reverse engineering, CASE tools provide, at best, an approximation that the
developer can use to rediscover the original model.

Forward Engineering Reverse Engineering

In forward engineering, the In reverse engineering or backward


application are developed with the engineering, the information are collected
given requirements. from the given application.

Forward Engineering is a high Reverse Engineering or backward


proficiency skill. engineering is a low proficiency skill.

While Reverse Engineering or backward


Forward Engineering takes more time
engineering takes less time to develop an
to develop an application.
application.

The nature of forward engineering is The nature of reverse engineering or


Prescriptive. backward engineering is Adaptive.

In forward engineering, production is In reverse engineering, production is


started with given requirements. started by taking the existing products.

The example of forward engineering


An example of backward engineering is
is the construction of electronic kit,
research on Instruments etc.
construction of DC MOTOR , etc.

Forward engineering Starts with Reverse engineering Starts with an


requirements analysis and design, existing software system and works
then proceeds to implementation and backward to understand its structure,
testing. design, and requirements.

Forward engineering is used to create Reverse engineering is Used to modify


new software applications from and improve an existing software
scratch. application.
Forward egineering is process of Reverse engineering is a process of
moving from a high-level abstraction moving from a low-level implementation to
to a detailed implementation. a higher-level abstraction.

Requirements and design specifications


Requires a clear set of requirements
may not be available, making it necessary
and design specifications.
to reconstruct them from the code itself.

Forward engineering is generally Reverse engineering is generally less


more time-consuming and expensive. time-consuming and less expensive.

The final product is completely new The final product is typically a modified or
and independent of any existing improved version of an existing software
software system. system.

Involves a series of steps such as


Involves steps such as code analysis,
requirements gathering, design,
code understanding, design recovery, and
implementation, testing, and
documentation.
deployment.

Forward engineering is commonly Reverse engineering is commonly used in


used in the initial stages of software the maintenance stage of the software
development. development life cycle.

Anti Patterns
An antipattern is just like a pattern, except that instead of a solution, it gives something that
looks superficially like a solution but isn’t one.
Anti-patterns are the opposite of best practice, which is a solution that has been proven to be
effective. They are often used because they seem to work, but the larger context or the
long-term consequences are often not considered. They can occur in software design, project
management, and organizational behavior. We should avoid anti-patterns.

Anti-patterns affects your software badly and it adds “technical debt”- additional work for you
(and surely a headache) as well. Let’s discuss the six most common types of anti-patterns and
their solution in software development.
Spaghetti Code
The spaghetti code anti-pattern occurs when code is poorly structured and difficult to
understand. This type of code lacks modularity, separation of concerns, and readability. It is
difficult to maintain or modify spaghetti code because it is so difficult to understand. Code
reviews and refactoring are good techniques to prevent and remove spaghetti code. We should
split larger blocks of code into smaller reusable chunks. We should keep methods small, and
they should do only one thing.

Golden Hammer
Software development is a field where it’s not important that if a solution or a pattern worked for
a single problem then it will also work for the other problems. If a solution is fit for problem A,
problem B, and problem C then it’s not necessary that it will be fit for problem D.

Imagine a scenario that you’re working on a project, you adapted a new solution, a brand-new
architecture, and this new architecture solved all your past set of issues. Now you tried this new
architecture for another set of the problem….and voilaaaa, it worked for that as well. Now you
become confident and you start trying to make it fit everywhere but…wait, you find that it’s not
working for the problems XYZ. This is what the golden hammer or the silver bullet is.

The golden hammer can generate many problems in your code. The chosen solution may not
be an efficient solution to your problem and your code can also turn into an overly complicated
code.

Pick the right set of tools, languages, frameworks, patterns, or the architecture for a specific
problem. Always have multiple solutions (at least two) for a single problem. Observe the pros
and cons of each one of them and then pick the best one.

Boat Anchor
If you’re in software development then surely you might have predicted something to implement
in the future. What if I need to implement the XYZ feature in the future? What if this case
happens in my code??
The above what if question force you to add some additional lines of code in your program
which isn’t needed right now. This is what boat anchor anti-pattern is in software. This
anti-pattern exists in the code when programmers leave a piece of code in the codebase
thinking that they might need it later.
You write some piece of code which is not mentioned in the current requirement but you’re sure
that you will need that maybe next month or maybe after two months. You don’t delete it. You
think that you will immediately make it work whenever in the future you will be asked to
implement it.
This just creates another anti-pattern in your software. Your colleagues are looking at the code
and trying to understand that what this specific piece of code is doing in the codebase. Surely
it’s just a wastage of time to read and debug that unnecessary lines of code.
In simple words boat, anchor depicts one thing- heavy to carry (obsolete code which has no
use, serves no purpose, does nothing in the code, and adds technical debt).

Dead Code
Dead code is mostly a piece of code in a file that was written a couple of years ago to build
some functionality but now it’s not needed anymore. Your program won’t terminate anywhere if
this function will be removed completely.
It will be risky to completely remove the dead code. You can do monkey testing if you don’t want
to remove the dead code. Comment out this piece of code, turn off the things, and see what
happens in production. You can also take an iterative approach to remove the code piece by
piece from your codebase. Keep checking the functionality in your software to assure that you
haven’t broken anything.

God Object
The God Object anti-pattern happens when a single object or class tries to do too much,
resulting in tight coupling and decreased maintainability. A God Object typically has too many
responsibilities and violates the single responsibility principle of object-oriented programming.
We can split such a God Object into several smaller classes with dedicated responsibilities.
A typical god class/god object takes many responsibilities and a lot of dependencies. God class
controls many other classes. If most of the piece of code needs to access one object then that
object might be a god object.
God classes are hard to unit test, maintain, debug, and document. You might have started
designing your application with no god class, but when the requirements get added and the
team size grows day by day, a single clearly defined class turns into the god classes at some
point.
To solve this issue you need to separate out and modularize your code better. Sometimes
programmers compare this with a very funny example. You’re asking for a banana but you
received a gorilla holding a banana. You got what you wanted but more than what you needed.

Copy and Paste Programming


You can easily find an example of this anti-pattern while doing the code review of junior
developers or an intern. Junior developers or interns lack the development experience, and they
face difficulty in building some features or writing some code from scratch. They try to copy and
paste the code from some resources such as StackOverflow, Github, or from the other blogs or
videos. They copy and paste these codes into their own file without doing any testing or impact
analysis.
This anti-pattern acts like a virus in your software and to fix this issue you need to change the
code everywhere the code was copied. This happens because of the poor understanding of the
fundamentals such as loop structures, functions, and subroutines.
You can avoid this anti-pattern by doing code review frequently and carefully. The code should
be tested properly and also analyze the impact if you implement that in your program. It should
be carefully reviewed and approved by the senior developers in the team. Also, do code
refactoring to abstract each appearance into a single function or a method.

It is essential to recognize and avoid anti-patterns because they can lead to several negative
consequences:
● Inefficient or ineffective solutions to problems
● Increased complexity and maintenance costs
● Decreased code readability and understandability
● Decreased team productivity and morale
By recognizing and avoiding anti-patterns, we can improve our solutions and ensure they are
effective, efficient, and maintainable. This can lead to better outcomes for our projects and a
more positive work environment.

Visitor Patterns
It is a type of behavioral design pattern. It manages algorithms, relationships, and
responsibilities between objects. It is used to perform an operation on a group of similar kinds of
Objects at runtime. It decouples the operations from an object structure. Using visitor patterns,
we can easily add new behaviors to the existing class hierarchy without changing the existing
code. Sometimes, it is also known as a behavioral pattern.

These design patterns provide all about class object communication. These are the patterns
that are specifically concerned with communication between objects.

Therefore, the primary goal of the visitor pattern is to move the operational logic from the
objects to another class. Using visitor patterns, we can achieve the open-close principle.

The visitor pattern actually creates an external class that uses data in other classes. We can
use the pattern when we need to perform operations across a disparate set of objects. It
provides additional functionality to the class without modifying it.

There are the two most important methods that are used in visitor patterns. The accept() method
accepts a visitor. It is provided by the Visitable class. The visit() method is called every time
when we visit an element. It is implemented by the Visitor class.
Example of Visitor Design Pattern
The most common example of visitor pattern is shopping in the supermarket. In the
supermarket, we pick the goods and add them to our cart. When we collect all the necessary
goods to the cart, we go to the bill desk for billing. The cashier checks all the goods picked by
us and tells us the total amount; we have to pay. Here, the cashier acts as a visitor.

Design Components
There are five major components of visitor pattern:
○ Client: It is a class that acts as a consumer of the classes of the design pattern. It has
the authority to access the data structure objects. It also instructs them to accept a
Visitor that performs the appropriate processing.
○ Visitor: It may be an interface or an abstract class. The interface contains the visit
operation for all types of visitable classes.
○ ConcreteVisitor: All the visit methods that are declared in abstract visitor must be
implemented in the ConcreteVisitor class. Each visitor is responsible for different
operations.
○ Visitable: It is also an interface in which we declare the accepted operation. It is an entry
point that enables an object to be visited by the visitor object.
○ ConcreteVisitable: It is a class that implements the Visitable interface or class in which
accept operation is defined. The object of the visitor class is passed through the object
of using the accept operation.

Advantages
○ We can easily add items to the system. The changes are required only in the Visitor
interface. Other existing code will not be affected.
○ If the logic of operation changes, then we need to make changes only in the visitor
implementation.
○ It reduces the maintenance cost.
○ Being relatively clean, easy-to-read code.
○ Type-safety, type errors are caught at compile time.
○ It provides high extensibility.

Disadvantages
○ It is difficult to extend if there are several implementations of the visitor interface.
○ While designing the pattern, emphasis on the return type of the visit() method. Else, we
will have to change the interface and all its implementations.
Interface descriptions

Interface objects

You might also like