University Institute of Information Technology,
PMAS-Arid Agriculture University,
Rawalpindi Pakistan
Course code: SE-415
Assignment no: 03
Submitted by: Ali Khursheed (20-Arid-748)
M. Zeeshan Akbar(20-Arid-810)
Class: BSSE 8(A) Morning
Submitted to: Mam Ruqia Bibi
Bachelor of Science in Software Engineering
Software Re-engineering Project for a Flutter Login Page
Step 1: Find a Legacy Code
Let's take a simple legacy Flutter code for a login page as an example. This code
might be outdated in terms of best practices and could be improved.
Legacy Login Page Code:
import 'package:flutter/[Link]';
void main() {
runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
class LoginPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Padding(
padding: [Link](16.0),
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(labelText: 'Username'),
),
TextField(
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Perform login
},
child: Text('Login'),
),
],
),
),
);
}
}
Step 2: Identify Reasons to Restructure
1. State Management: The current code does not manage the state effectively,
which can lead to issues in larger applications.
2. Form Validation: No form validation is implemented.
3. Code Reusability: The code lacks modularity and reusability.
4. Security: Plain text fields for username and password without any form of
validation or encryption.
5. User Experience: No feedback is given to the user upon an unsuccessful login
attempt.
Step 3: Refactor the Legacy Code
We'll refactor the legacy login page code to include state management using a stateful
widget, form validation, and better user experience practices.
Refactored Login Page Code:
import 'package:flutter/[Link]';
void main() {
runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
}
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
bool _isLoading = false;
void _login() {
if (_formKey.currentState!.validate()) {
setState(() {
_isLoading = true;
});
// Simulate a login process
[Link](Duration(seconds: 2), () {
setState(() {
_isLoading = false;
});
// Here you would usually navigate to another screen or show a success message
[Link](context).showSnackBar(SnackBar(content: Text('Login
Successful')));
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Padding(
padding: [Link](16.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _usernameController,
decoration: InputDecoration(labelText: 'Username'),
validator: (value) {
if (value == null || [Link]) {
return 'Please enter your username';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || [Link]) {
return 'Please enter your password';
return null;
},
),
SizedBox(height: 20),
_isLoading
? CircularProgressIndicator()
: ElevatedButton(
onPressed: _login,
child: Text('Login'),
),
],
),
),
),
);
Control Flow Analysis (CFA):
1. Control Flow Graph (CFG): Identify the control flow in the
refactored code, such as the state transitions between login attempt,
validation, and feedback.
2. The main control flow involves:
1. Initializing the form.
2. User input in the username and password fields.
3. Form validation on button press.
4. Displaying loading indicator.
5. Simulated login process.
6. Feedback on successful login.
Data Flow Analysis (DFA):
1. Data Flow Graph (DFG): Track the flow of data through the
program.
2. Key data points:
1. User input in the username and password fields.
2. Validation results from the form validators.
3. The _isLoading boolean to manage the loading state.
Program Slicing:
1. Extract relevant parts of the code that handle the login process.
2. Forward Slicing: Identify how the username and password input
impact subsequent parts of the program (e.g., triggering validation,
showing loading state, displaying feedback).
3. Backward Slicing: Determine which parts of the code impact the login
validation logic.
Step 3: Refactor the Legacy Code
We'll refactor the legacy login page code to include state management using a stateful
widget, form validation, and better user experience practices.
Refactored Login Page Code:
dart
Copy code
import 'package:flutter/[Link]';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LoginPage(),
);
}
}
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _usernameController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
bool _isLoading = false;
void _login() {
if (_formKey.currentState!.validate()) {
setState(() {
_isLoading = true;
});
// Simulate a login process
[Link](Duration(seconds: 2), () {
setState(() {
_isLoading = false;
});
// Here you would usually navigate to another screen or show a success message
[Link](context).showSnackBar(SnackBar(content: Text('Login
Successful')));
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Login'),
),
body: Padding(
padding: [Link](16.0),
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
controller: _usernameController,
decoration: InputDecoration(labelText: 'Username'),
validator: (value) {
if (value == null || [Link]) {
return 'Please enter your username';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validator: (value) {
if (value == null || [Link]) {
return 'Please enter your password';
}
return null;
},
),
SizedBox(height: 20),
_isLoading
? CircularProgressIndicator()
: ElevatedButton(
onPressed: _login,
child: Text('Login'),
),
],
),
),
),
);
}
}
Step 4: Perform Reverse Engineering Techniques
Control Flow Analysis (CFA):
1. Control Flow Graph (CFG): Identify the control flow in the refactored code, such
as the state transitions between login attempt, validation, and feedback.
2. The main control flow involves:
1. Initializing the form.
2. User input in the username and password fields.
3. Form validation on button press.
4. Displaying loading indicator.
5. Simulated login process.
6. Feedback on successful login.
Data Flow Analysis (DFA):
1. Data Flow Graph (DFG): Track the flow of data through the program.
2. Key data points:
1. User input in the username and password fields.
2. Validation results from the form validators.
3. The _isLoading boolean to manage the loading state.
Program Slicing:
1. Extract relevant parts of the code that handle the login process.
2. Forward Slicing: Identify how the username and password input
impact subsequent parts of the program (e.g., triggering validation,
showing loading state, displaying feedback).
3. Backward Slicing: Determine which parts of the code impact the login
validation logic.
Step 5: Draw a Call Graph
The call graph for the refactored code would include the following method calls and
their interactions:
1. MyApp -> LoginPage
2. LoginPage -> _LoginPageState
3. _LoginPageState -> _login
4. _login:
1. Form validation methods.
2. State updates for loading indicator.
3. Feedback via ScaffoldMessenger.
References and Help sources:
1. Flutter Documentation: Utilized official documentation to understand and
implement best practices in Flutter application development.
2. Firebase Authentication: Referenced Firebase documentation for integrating
and handling user authentication in Flutter.
3. State Management in Flutter: Used Flutter community resources and
tutorials to understand state management using Stateful Widgets.
4. Form Validation Techniques: Followed guidelines from Flutter’s official
documentation on form validation.
5. UI/UX Best Practices: Referenced various UX design principles to enhance
the user experience in the login process.
6. Stack Overflow: Consulted community discussions for troubleshooting
common issues encountered during the development process.