0% found this document useful (0 votes)
50 views21 pages

Software Re-Engineering Exam Notes

Uploaded by

saaddl333333333
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)
50 views21 pages

Software Re-Engineering Exam Notes

Uploaded by

saaddl333333333
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/ 21

Software Re-engineering

Exam Notes

Short Questions:

Q1) What is the purpose of code refactoring in reengineering?


The purpose of code refactoring in reengineering is to make the code better without
changing what the code does.
It helps make the code clean, simple, and easy to read.
This also makes it easy to find problems and do future updates.
Refactoring removes bad or confusing parts from the old code.
It helps developers work faster and understand the code more easily.

Q2)List three key benefits of applying reverse engineering to legacy systems.

• Reverse engineering helps us understand how an old system works, especially


when there is no proper documentation.
• It helps to find hidden problems, bugs, or mistakes in the old system.
• It makes it easier to improve, update, or rebuild the old system in a better way.
Reverse engineering gives full knowledge of the system’s design and working.
It also saves time and helps in planning future changes clearly.

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.

Q4)Explain the difference between restructuring and re-documentation in


software reengineering.

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.

Re-documentation means creating new or updated documents for the software.


It helps explain how the software works when old documents are missing or
outdated.
It is useful for understanding, maintaining, and updating the system in the future.

Q5)Mention a reengineering strategy to migrate from monolithic to micro


service architecture.
One common reengineering strategy to move from a monolithic system to a
microservice architecture is the Strangler Pattern.
In this method, we do not replace the whole system at once.
Instead, we slowly take out small parts (features or services) from the big monolithic
system and rebuild them as separate microservices.
These new microservices work together with the old system during the change.
Step by step, more parts are moved into microservices until the old system is fully
gone.
This strategy helps in reducing risk, because the system keeps working during the
change.
It also gives time to test each small part properly and fix problems early.
This way, the move to microservices becomes smooth, safe, and easier to handle.
Q6)List two object-oriented design principles that support better
maintainability.

• 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

Q7)How does improper inheritance impact the maintainability of software?


Improper inheritance means using inheritance in the wrong way, like forcing a class
to use code it doesn’t need.
This can make the code confusing, hard to understand, and difficult to update.
If many classes are connected badly through inheritance, a small change in one class
can break others.
It also makes testing and fixing bugs harder because of too many links between
classes.
So, improper inheritance reduces the maintainability and quality of the software.

Q8)What maintenance problem does the violation of the Single Responsibility


Principle (SRP) cause?

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.

Q9) Give an example of a “code smell” in an object-oriented system and explain


its impact.
One common example of a “code smell” in an object-oriented system is a Large
Class.
A large class has too many methods, too many variables, and does too many things.
It tries to handle too many responsibilities, which makes the code hard to read and
understand.
When a class is too big, it becomes difficult to test, change, or fix.
Even a small change in one part can affect other parts of the class.
This increases the chance of bugs and makes the software harder to maintain.
Large classes also break the Single Responsibility Principle, which reduces code
quality.
So, a large class is a bad sign in code and should be split into smaller, focused
classes.
Long Questions:
Q1)You are given a legacy payroll system written in an outdated language.
Apply suitable reengineering techniques to modernize the system. Describe
your approach with justification.

1. Reverse Engineering

First, we study the old system to understand how it works.


We check the source code, data flow, and business rules used in the payroll system.
This is important if there is no documentation available.
We create new documents, diagrams, and models to show the current working of
the system.
This helps the development team understand the system clearly.
We also try to recover hidden knowledge and logic that may have been lost over
time.
Reverse engineering gives us a full understanding of how salaries, taxes, and
employee records are handled.

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

We analyze the old database and improve its design.


We convert old data formats into modern formats, like moving from flat files to a
relational database.
This improves data storage, speed, and security.
We also clean the data, remove duplicates, fix errors, and redesign tables to follow
modern database rules.
Good data design ensures the payroll system is accurate and fast when processing
payments or reports.

4. Migration to Modern Language

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.

Q2) A software product lacks proper documentation and contains a lot of


redundant code. Apply reengineering techniques such as code refactoring and
reverse engineering to improve its maintainability. Illustrate with an example.

To improve the maintainability of a software product that has no proper


documentation and a lot of repeated code, we can use two important reengineering
techniques: Reverse Engineering and Code Refactoring.
These techniques help us understand the system better and clean the code to make
it easier to manage in the future.

1. Reverse Engineering

In reverse engineering, we study the existing system to understand what it does.


Since there is no documentation, we read the source code and try to find out the
purpose of each module or function.
We create flowcharts, UML diagrams, and written documents to describe how
the software works.
This helps developers, testers, and future teams understand the system without
guessing.
Reverse engineering is very helpful when the original developers are not available
or the documents are missing.
It gives a complete view of the software’s logic, data flow, and structure.
2. Code Refactoring

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.

✅ Before Refactoring (Bad Example):

net_salary = (basic_salary + bonus) - (tax + insurance)

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.

✅ After Refactoring (Good Example):

net_salary = calculate_salary(basic_salary, bonus, tax, insurance)

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.

Q3) Select a sample procedural code and apply step-by-step transformation to


convert it into an object-oriented version using appropriate reengineering
techniques.

To convert a software program from procedural code to object-oriented code, we


can use two reengineering techniques: reverse engineering and code refactoring.
These steps help us improve the code and make it easier to update, reuse, and
understand in the future.

✅ Step 1: Reverse Engineering

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.

✅ Step 2: Code Refactoring

Now, we apply code refactoring to improve the code structure.


We remove global variables, repeated logic, and write clean and short code.
Then we use object-oriented style like classes and objects to organize the code better.
This makes the program easier to manage, especially when it grows in size.

✅ Example:

Procedural Code (Old Style):


print(50000 - 5000)

This is a simple line doing salary calculation directly. The logic is not reusable or
organized.

Object-Oriented Code (New Style):


class Salary: pass
# Now we can add methods and reuse it later
Salary().calculate(50000, 5000)

We moved the logic into a class. Now the code is more reusable, organized, and easy
to update later.

We first used reverse engineering to understand the old procedural code.


Then, with the help of code refactoring, we changed it into a clean object-oriented
version.
This new version is easier to maintain, reuse, and upgrade in the future.
It also follows modern programming rules and helps developers work more
efficiently.

Q4) How can software reengineering support the transition of a desktop-based


application to a web-based system? Discuss with reference to maintainability
and scalability.

Software reengineering plays an important role when we want to move a desktop-


based application to a web-based system.
Instead of building the whole system again from the beginning, we can use
reengineering techniques to improve, reuse, and move the existing system into a
modern web environment.
This helps in saving time, reducing cost, and making the system better.
✅ 1. Reverse Engineering

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.

✅ 2. Code Refactoring and Modularization

We clean and improve the old code using refactoring.


We break large blocks of code into small modules or functions.
This makes it easier to move these modules to the web system.
Good modular code is easier to test, reuse, and maintain.
We also remove unnecessary or repeated code.

✅ 3. Data Reengineering

The desktop application may use local files or old databases.


We change and improve the data system to use modern web-based databases (like
MySQL or cloud storage).
We ensure the data is clean, well-organized, and accessible from the internet.
This helps in handling more users and better performance.

✅ 4. Forward Engineering to Web Technologies

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:

Software reengineering helps in a smooth and safe transition from a desktop


application to a web-based system.
By using reverse engineering, code refactoring, data reengineering, and forward
engineering, we make the system more maintainable, scalable, and ready for future
use.
It saves time, improves quality, and brings the old system into the modern world.
Q5) Analyze the given class diagram/code and identify object-oriented design
issues like high coupling, poor cohesion, or misuse of inheritance. Propose
improvements to enhance maintainability.

In object-oriented design, we follow certain rules or principles to make the code


clean, flexible, and easy to maintain.
When these rules are not followed, problems like high coupling, poor cohesion,
and misuse of inheritance can happen.
These problems make the code hard to understand, test, and change.

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:

• Use interfaces or abstract classes to reduce direct dependency.


• Use Dependency Injection to pass required objects.
• Keep classes focused and loosely connected.

✅ 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:

• Apply Single Responsibility Principle (SRP).


• Break the class into smaller classes like EmployeeInfo, SalaryCalculator, and
ReportPrinter.
• Each class should do only one job.

✅ 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.

✅ Final Improvements to Enhance Maintainability:

• 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.

Q6) A system developed without design patterns is becoming increasingly hard


to maintain. Analyze the reasons and suggest how applying appropriate object-
oriented design patterns could resolve the issues.

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.

✅ Reasons Why the System Becomes Hard to Maintain:

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.

✅ How Design Patterns Can Help:

Using object-oriented design patterns can solve many of these problems by


providing tested, proven solutions. Here are some examples:

1. Factory Pattern

Problem Solved: Object creation code is repeated and hard to manage.


How it helps: This pattern provides a way to create objects without writing the code
everywhere.
It reduces duplication and keeps object creation in one place.

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

Problem Solved: Business logic is hardcoded and difficult to change.


How it helps: It allows you to change the behavior (logic) of a class at runtime
without changing the class itself.
Good for things like payment methods or sorting algorithms.

✅ 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.

✅ Possible Reasons for Frequent Failures:

1. Poor Class Design


The class may be doing too many things at once.
This makes it confusing, and one change can affect other parts of the class.
2. High Coupling
The class may be tightly connected to many other classes.
If one class changes, it causes errors in others too.
3. Lack of Cohesion
The methods in a class may not be related to each other.
This makes the class messy and hard to understand or fix.
4. Misuse of Inheritance
Inheritance may be used wrongly, for example, when classes don’t have a
real “is-a” relationship.
This can cause unexpected behavior in child classes.
5. No Error Handling
If the code does not check for errors properly, it may crash often or behave
wrongly.
6. Outdated Code or Libraries
The module may use old code or libraries that are not supported or secure
anymore.

✅ Design-Level Changes to Reduce Maintenance Costs:

1. Apply Single Responsibility Principle (SRP)


Each class should do only one job.
Split large classes into smaller, focused classes.
This makes the code easier to test and fix.
2. Reduce Coupling
Use interfaces or dependency injection so classes are loosely connected.
This way, one class can change without affecting others.
3. Improve Cohesion
Group related methods together and keep unrelated methods in separate
classes.
This makes each class clear and easy to manage.
4. Replace Wrong Inheritance with Composition
If inheritance is misused, replace it with composition.
For example, instead of “class B extends A”, let class B use class A inside it.
This avoids unwanted behavior.
5. Add Proper Error Handling
Use try-except (or try-catch) blocks to handle errors safely.
This makes the system more stable and reduces crashes.
6. Refactor the Code
Clean the code by removing repeated logic, improving names, and organizing
files.
This helps developers understand the system faster.
7. Update to Modern Standards
Replace outdated libraries, functions, or code styles with modern tools.
This increases performance and security.

✅ 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.

✅ Problems when encapsulation is not used properly:

1. Anyone can change data:


If class variables are public, other parts of the program can change them
directly.
This can create errors and make the program crash.
2. No control over wrong data:
Data like marks, age, or price may be set to wrong values (like negative
numbers), which should not happen.
3. Hard to fix bugs:
When many parts of the program change the same data, it becomes hard to
find and fix bugs.
4. No protection:
Important data is not safe because there is no rule or control over who can
use or change it.

✅ Bad Example (No Encapsulation):

student.marks = -50 # Anyone can set wrong value


Explanation:
This code directly changes the marks without any check.
Anyone can set wrong values like -50, which is not allowed.
This makes the program unsafe and hard to maintain.

Good Code (With Encapsulation):


student.set_marks(85) # Value set safely using method
Explanation:
This code uses a method to set marks safely.
The method can check the value before setting it.
So, wrong values like -50 will be rejected.
This protects the data and makes the program easier to fix and manage.

You might also like