Software Re-Engineering Exam Notes
Software Re-Engineering Exam Notes
Exam Notes
Short Questions:
Q3)Name any two software reengineering tools and briefly explain their
function.
• Rational Rose – Rational Rose is a software tool used to design and plan
software systems.
It uses UML (Unified Modeling Language) diagrams to show how the system
works.
It helps developers understand the structure and behavior of the software
clearly.
This tool is very helpful in reengineering because it shows the full design of
the system in a simple way.
• Imagix 4D – Imagix 4D is a tool used to understand and analyze old source
code.
It creates diagrams and reports that show how the code is working.
This helps in finding errors, understanding code logic, and improving the
system.
It is useful in reengineering because it makes old and complex code easier to
read and change.
Restructuring means changing the structure of the code to make it better and easier
to understand, but without changing how it works.
It improves the quality of the code by making it clean and well-organized.
It is useful when the code is messy or hard to read.
• Single Responsibility Principle (SRP) – This principle says that every class
should have only one job or reason to change.
If a class does too many tasks, it becomes confusing and hard to manage.
When a class has only one job, it is easier to understand, test, and fix.
This helps in keeping the code clean and makes future changes simple and
safe.
It improves the maintainability of the software.
• Open/Closed Principle – This principle means that a class should be open
for extension but closed for modification.
We can add new features by writing new code, but we should not change the
existing code.
This helps in preventing new bugs and keeps the old code working properly.
It allows us to grow the software without breaking what already works.
This makes the software easy to maintain and improves long-term stability
When the Single Responsibility Principle (SRP) is violated, it means that one class
is doing many different tasks instead of just one job.
This makes the code very confusing and hard to read or understand.
If we try to change one part of the class, it may break other parts that are not related.
This can lead to new bugs and errors in the system.
Testing also becomes difficult because one class is handling too many things.
It is hard to know where a problem is coming from.
Making updates or improvements takes more time and effort.
So, violating SRP makes the software harder to maintain, less flexible, and less
reliable.
1. Reverse Engineering
2. Code Refactoring
We clean up the old code by removing bad parts and making it more readable.
We don't change what the code does, only how it looks and works internally.
This step makes the system easier to maintain and understand.
Refactoring helps reduce duplicate code, simplifies logic, and improves naming and
structure.
This makes it easier for new developers to work on the system and reduces future
errors.
3. Data Reengineering
Once the system is well understood, we slowly move parts of the system into a
modern programming language (like Java, Python, or C#).
We can use the Strangler Pattern to replace old modules one by one without
stopping the whole system.
This reduces risk and allows testing of each part separately.
It also helps the business keep running while the system is being changed.
New parts can use better tools, libraries, and security features available in modern
languages.
5. Forward Engineering
After everything is understood and planned, we redesign and rebuild the system
using modern tools and languages.
This includes writing new code, creating a modern user interface, and adding new
features.
Forward engineering helps in building the system in a clean and well-organized way.
We can also add automation, error checking, and reporting features that were
missing in the old version.
This makes the new payroll system more powerful and user-friendly.
Justification:
• These steps reduce risk and cost because we improve the system slowly.
• It helps in keeping the business running while making changes.
• It gives a clean, modern system that is easier to update and maintain in the
future.
• Each step improves a specific part of the system without breaking other parts.
• It also helps in training new developers and improving system performance.
1. Reverse Engineering
After we understand the system through reverse engineering, we start improving the
code by refactoring.
Refactoring means cleaning and improving the code without changing what it
does.
We remove redundant code, such as repeated logic that appears in many places.
We create reusable functions or classes so that we don’t have to write the same
code again and again.
We also rename variables and functions to make the code easier to read and
understand.
This helps in reducing errors, improving speed, and making the system easier to test
and maintain.
Example to Illustrate:
Imagine a software that calculates employee salary in many places using the same
formula, but the code is written separately each time.
Explanation:
This line is repeated in many places in the program.
If the formula changes, we must update it everywhere, which is hard and risky.
Explanation:
Now we use a function. The formula is written in one place only.
If anything changes, we update the function only once.
This makes the code clean, simple, and easier to maintain.
First, we use reverse engineering to understand what the procedural code is doing.
Since procedural code is written using simple functions and variables, we study it
to find out how it works.
We note the purpose of each line and write small documentation if needed.
This helps us know how to change it into a better form.
✅ Example:
This is a simple line doing salary calculation directly. The logic is not reusable or
organized.
We moved the logic into a class. Now the code is more reusable, organized, and easy
to update later.
First, we use reverse engineering to understand how the desktop application works.
We study the old code, user interface, data handling, and business logic.
We create documents, diagrams, and models to show what the system does.
This helps us rebuild the same features in the web-based version without missing
anything.
It also helps new developers understand the system clearly.
✅ 3. Data Reengineering
After understanding and cleaning the old system, we use forward engineering to
build the system using web technologies like HTML, CSS, JavaScript, Python, PHP,
etc.
We create a user-friendly web interface, connect it with the new backend, and test
everything step by step.
We also add features like user login, remote access, and mobile support.
✅ 5. Maintainability
By reengineering the code and using clean, modern design, the web system becomes
easier to maintain.
Future changes, bug fixes, or feature updates are easier to do.
It also becomes easy for new developers to understand and work on the system.
✅ 6. Scalability
A web-based system can handle more users and more data than a desktop system.
Reengineering helps in designing the system in a way that it can grow in the future.
We can add more features, connect to other systems, or move to cloud hosting easily.
This makes the system ready for business growth.
✅ Conclusion:
Let’s discuss each issue and how we can fix it to improve maintainability.
✅ 1. High Coupling
Problem:
When classes are too dependent on each other, it is called high coupling.
If one class changes, the other class may also break.
This makes the system hard to update and test.
Example:
A Payment class directly uses the methods of Employee, Tax, and Report classes
all together.
Solution:
✅ 2. Poor Cohesion
Problem:
When a class does too many different tasks, it has poor cohesion.
The class becomes large, confusing, and difficult to maintain.
Example:
A single Employee class that handles personal details, salary calculation, and
printing reports.
Solution:
✅ 3. Misuse of Inheritance
Problem:
Inheritance is used when it is not needed, or used incorrectly.
This creates complex relationships that are hard to understand and manage.
Example:
A Printer class inherits from Employee, which does not make sense because they
are unrelated.
Solution:
• Use inheritance only when classes share common behavior and "is-a"
relationship.
• If two classes do not have a clear connection, use composition instead of
inheritance.
• Follow Liskov Substitution Principle (LSP) to make sure child classes can
replace parent classes safely.
• Use clean naming, proper class structure, and follow design principles like
SOLID.
• Use UML diagrams to plan relationships before coding.
• Keep the code modular, testable, and easy to read.
• Regularly do code reviews and refactoring to improve quality.
✅ Conclusion:
To make object-oriented code maintainable, we should avoid high coupling, fix poor
cohesion, and use inheritance correctly.
By applying best design practices, we can build a system that is easy to understand,
test, and grow in the future.
When a system is developed without using design patterns, it may work at first, but
over time it becomes hard to maintain, update, or understand.
Design patterns are standard solutions to common problems in object-oriented
design.
They help organize code properly, reduce errors, and improve system quality.
1. Unstructured Code:
Without design patterns, the code may become messy, with no clear structure.
It’s hard to know which part does what, and changing one thing may break
others.
2. Repeated Code:
The same logic might be written again and again in different places.
This increases chances of mistakes and makes updates harder.
3. Tight Coupling:
Classes may depend too much on each other.
A change in one class may affect many other classes.
4. No Reusability:
Without good design, we can’t reuse parts of the code in other places.
This leads to more work and increases the size of the system.
1. Factory Pattern
2. Observer Pattern
Problem Solved: When one object changes, others need to update, but code is
tightly connected.
How it helps: This pattern allows objects to subscribe and get updates without tight
connections.
It improves flexibility and makes updates easier.
3. Singleton Pattern
Problem Solved: When we need only one instance of a class, but many are created
by mistake.
How it helps: It controls object creation and ensures only one instance is used.
This is useful in things like logging, database connection, etc.
4. Strategy Pattern
✅ Conclusion:
A system without design patterns becomes hard to manage because the code is not
organized properly.
By using the right object-oriented design patterns, we can make the system more
maintainable, flexible, reusable, and easy to understand.
It also helps future developers to make changes safely and saves time in the long
run.
Q7) You have received several bug reports for a legacy object-oriented module.
Analyze the possible reasons for the frequent failures and propose design-level
changes that could reduce maintenance costs.
When a legacy object-oriented module keeps getting bug reports, it means the
design of the code may have serious problems.
These problems increase failures and make the system hard to maintain.
We need to study the code, find the design issues, and apply better design practices
to reduce future bugs and lower maintenance cost.
✅ Conclusion:
Frequent bugs in a legacy object-oriented module are usually caused by bad design,
tight coupling, poor structure, or outdated code.
By applying design principles like SRP, loose coupling, good cohesion, and
proper error handling, we can reduce the number of bugs.
These improvements will make the system easier to maintain, safer to update,
and cheaper to manage in the long term.
Q8) Analyze the software maintenance challenges that arise due to poor
encapsulation in an object-oriented design. Support your answer with examples
and potential solutions.
Encapsulation is an important concept in object-oriented programming.
It means keeping the internal details of a class hidden and allowing access only
through proper methods (like getters and setters).
When encapsulation is not used properly, it creates many problems during
software maintenance.