Professional Documents
Culture Documents
Soft Engg Practice mst2
Soft Engg Practice mst2
Architecture diagramming is the process of creating visual representations of software system components. In a
software system, the term architecture refers to various functions, their implementations, and their interactions with
each other. As software is inherently abstract, architecture diagrams visually illustrate the various data movements
within the system. They also highlight how the software interacts with the environment around it.
Collaboration
Architecture diagrams significantly boost collaboration between developers and designers and create a unified view
of system functionality and potential issues. A shared understanding of a system, application, or website has several
benefits. It supports communication during the design process, helps teams develop effective system software
components, and ensures a project meets its goals.
Risk reduction
Architecture diagrams identify potential system development risks, such as incorrect assumptions, faulty logic, or
inadequate testing. By identifying and addressing risks early in the software development lifecycle, development
teams can make changes earlier and reduce the risk that significant issues appear later.
Efficiency
Architecture diagrams provide a clear view of system components and structure. So, stakeholders can identify
problems accurately and resolve them quickly. Diagrams also make it easier to maintain and scale systems, so
ongoing changes are more efficient.
Scalability
Architecture diagrams allow stakeholders to identify efficient ways to scale a system. For example, a diagram may
show if a system's architecture is centralized or distributed. Since distributed components scale more efficiently,
monolithic components can be updated or replaced in time. Similarly, graphical representations provide insight into
how data is stored and moved. Stakeholders can identify potential bottlenecks and ways to avoid them.
Here are some of the most commonly used software architecture patterns.
Client-server architecture
Client-server architecture is a distributed application structure that separates tasks and workloads between servers
and clients. Servers provide the resource or service, and clients request it.
The client and server are separate programs that communicate over a network. A web browser and web server are
an example of client-server architecture. It’s a commonly used architecture in distributed computing.
Service-oriented architecture
Service-oriented architecture allow for interaction between distributed application components through services.
Services are abstract, loosely coupled, and language-independent. Applications access them through interfaces.
Developers can reuse existing services rather than having to rebuild from scratch. Service-oriented architecture is
widely used in distributed systems, as services can be deployed across multiple servers.
Microservices architecture
Service-oriented architecture has evolved further, so developers use microservices architecture to build, deploy, and
manage individual services. Applications are split into independently deployable services that communicate through
APIs.
Smaller, independent services make it simpler for developers to develop, test, and deploy applications and deliver
improved fault tolerances and rapid scaling. An example of a microservices architecture is a web application
consisting of several independent services, each responsible for specific tasks.
Cloud-centered architecture
Cloud-centered architecture is used to design and build applications for cloud environments. Cloud-centered
architecture is built and delivered with cloud-specific technologies such as containers, microservices, DevOps, and
serverless computing. It prioritizes automated deployment and management so that applications can be scaled up
and down as needed.
Event-driven architecture
Event-driven architecture is software architecture based on the production, detection, and consumption of events.
User interactions, background tasks, and other sources trigger events that further trigger other functionality. The
event-driven architecture allows applications to be more responsive to changes in a software system and its
environment.
Layered architecture
Layered architecture is a software architecture pattern that separates applications into logic-based layers. This type
of architecture is designed to simplify complex applications and systems, as you can split tasks between layers.
Layers are organized from top to bottom:
Layers can also be structured hierarchically, which aids maintenance and scalability.
Squares and circles represent components such as databases, networks, applications, and services
Lines and arrows show the connections and interactions between the system's components
Labels provide additional information about the components and connections
Additionally, the diagram may also use icons or symbols to visually represent the different components. A small
legend at the bottom, similar to the legend on a map, explains icon usage. The way in which the components and
connections are arranged is called a layout.
It visualizes the relationships as well as the organization between the components present in the
system. It helps in forming an executable system. A component is a single unit of the system, which is
replaceable and executable. The implementation details of a component are hidden, and it
necessitates an interface to execute a function. It is like a black box whose behavior is explained by
the provided and required interfaces.
1. Using a meaningful name to ascertain the component for which the diagram is about to be
drawn.
2. Before producing the required tools, a mental layout is to be made.
3. To clarify the important points, notes can be incorporated.
Each iteration is considered as a short time "frame" in the Agile process model, which typically lasts
from one to four weeks. The division of the entire project into smaller parts helps to minimize the
project risk and to reduce the overall project delivery time requirements. Each iteration involves a
team working through a full software development life cycle including planning, requirements
analysis, design, coding, and testing before a working product is demonstrated to the client.
1. Requirements gathering
2. Design the requirements
3. Construction/ iteration
4. Testing/ Quality assurance
5. Deployment
6. Feedback
1. Requirements gathering: In this phase, you must define the requirements. You should explain
business opportunities and plan the time and effort needed to build the project. Based on this
information, you can evaluate technical and economic feasibility.
2. Design the requirements: When you have identified the project, work with stakeholders to define
requirements. You can use the user flow diagram or the high-level UML diagram to show the work of
new features and show how it will apply to your existing system.
3. Construction/ iteration: When the team defines the requirements, the work begins. Designers and
developers start working on their project, which aims to deploy a working product. The product will
undergo various stages of improvement, so it includes simple, minimal functionality.
4. Testing: In this phase, the Quality Assurance team examines the product's performance and looks
for the bug.
5. Deployment: In this phase, the team issues a product for the user's work environment.
6. Feedback: After releasing the product, the last step is feedback. In this, the team receives feedback
about the product and works through the feedback.
Scrum
SCRUM is an agile development process focused primarily on ways to manage tasks in team-based
development conditions.
o Scrum Master: The scrum can set up the master team, arrange the meeting and remove obstacles for
the process
o Product owner: The product owner makes the product backlog, prioritizes the delay and is responsible
for the distribution of functionality on each repetition.
o Scrum Team: The team manages its work and organizes the work to complete the sprint or cycle.
eXtreme Programming(XP)
This type of methodology is used when customers are constantly changing demands or requirements,
or when they are not sure about the system's performance.
Crystal:
There are three concepts of this method-
1. Chartering: Multi activities are involved in this phase such as making a development team, performing
feasibility analysis, developing plans, etc.
2. Cyclic delivery: under this, two more cycles consist, these are:
A. Team updates the release plan.
B. Integrated product delivers to the users.
3. Wrap up: According to the user environment, this phase performs deployment, post-deployment.
1. Time Boxing
2. MoSCoW Rules
3. Prototyping
1. Pre-project
2. Feasibility Study
3. Business Study
4. Functional Model Iteration
5. Design and build Iteration
6. Implementation
7. Post-project
Feature Driven Development(FDD):
This method focuses on "Designing and Building" features. In contrast to other smart methods, FDD
describes the small steps of the work that should be obtained separately per function.
1. Eliminating Waste
2. Amplifying learning
3. Defer commitment (deciding as late as possible)
4. Early delivery
5. Empowering the team
6. Building Integrity
7. Optimize the whole
OCL, known as object constraint language, is a declarative languageTells us what needs to be done, focusing on
outcomes rather than step-by-step instructions. that enhances UML by defining rules and expressions to describe
software system behaviors and properties precisely. It is often used to specify all types of constraints, including
invariants, pre-conditions, and post conditions that must hold true in various stages of software development.
It allows us to precisely define our software system's requirements, constraints, and behaviors.
It helps in the formal verification and validation of our software applications.
It removes unambiguity in our requirements by clarifying and simplifying complex constraints and properties.
It contributes to improved software quality by enforcing accurate and consistent behaviors.
Constraints in OCL
A constraint is a rule or limitation that defines a specific condition that must be met by our software system. We can
describe three types of constraints using OCL:
1. Invariants
2. Pre-conditions
3. Post conditions
1. Invariant
An invariant is a constraint that is supposed to be proven true before and after the execution of an operation. To
represent invariants in OCL language, we write:
context <ClassName>
inv <InvariantName>: <expression>
context: The keyword used to specify the context within which a constraint defined.
<ClassName>: The name of the class to which the constraint applies.
inv: The keyword that represents the invariant.
<InvariantName> (optional): The name of the invariant.
<expression>: The invariant we want to impose on the class.
2. Pre-condition
A pre-condition is a constraint that is supposed to be proven true before an operation. To represent pre-conditions
in OCL language, we write:
context: The keyword used to specify the context within which a constraint is defined.
<ClassName>: The name of the class to which the constraint applies.
<OperationName>: The name of the operation (along with its parameters) which we want to ensure
meets the pre-condition.
pre: The keyword that represents the pre-condition.
<ConditionName> (optional): The name of the pre-condition.
<expression>: The pre-condition we want to impose on the class.
3. Post condition
A post condition is a constraint that is supposed to be proven true after an operation. To represent post conditions
in OCL language, we write:
context: The keyword used to specify the context within which a constraint is defined.
<ClassName>: The name of the class to which the constraint applies.
<OperationName>: The name of the operation (along with its parameters) which we want to ensure
meets the post condition.
post: The keyword that represents the post condition.
<ConditionName> (optional): The name of the post condition.
<expression>: The post condition we want to impose on the class.
Example
Let's discuss an example to understand constraint representation in OCL. Suppose we have a UML diagram with
two classes: Employee and Company.
If we have an invariant that each Employee working in the Company should have an age greater than 22,
we represent this in OCL as:
context Employee
inv: self.name > 22
Here, we are referring to the attribute name of the Employee's class, so we write the Employee class as context.
The keyword self is optional and refers to attributes within the context class.
Note: We cannot write the constraint for attribute or function of classes other than the context class defined.
If we have a pre-condition that the increment parameter of the increaseSalary function should be
greater than 0 before the execution of the function, we represent this in OCL as:
context Employee::increaseSalary(increment: Real)
pre: increment > 0
If we have a post condition that after executing the increaseSalary function, the salary attribute of the
employee should be greater than his previous salary, we represent this in OCL as:
context Employee::increaseSalary(increment: Real)
post: self.salary > self.salary@pre
Limitations of OCL
Let's discuss limitations of using OCL language.
Learning OCL syntax can be challenging if we are unfamiliar with formal languages.
Despite its formal nature, OCL expressions can sometimes still be ambiguous or open to interpretation.
Integrating OCL with existing software development processes and tools can sometimes require workflow
adjustments.
OCL uses textual notation, which might not be as expressive as graphical notations for certain constraints.
Maintaining and updating OCL constraints alongside code changes can become challenging as software
evolves.
Conclusion
OCL serves as a powerful tool in software engineering, removing ambiguity in requirements and making them more
precise. While improving software quality, its formal nature can be challenging for our understanding. Nevertheless,
OCL contributes to building reliable and well-defined software systems.
2. Standard headers for different modules: For better understanding and maintenance of
the code, the header of different modules should follow some standard format and
information. The header format must contain below things that is being used in various
companies:
Name of the module
Date of module creation
Author of the module
Modification history
Synopsis of the module about what the module does
Different functions supported in the module along with their input output parameters
Global variables accessed or modified by the module
4. Indentation: Proper indentation is very important to increase the readability of the code.
For making the code readable, programmers should use White spaces properly. Some of
the spacing conventions are given below:
There must be a space after giving a comma between two function arguments.
Each nested block should be properly indented and spaced.
Proper Indentation should be there at the beginning and at the end of each block in
the program.
All braces should start from a new line and the code following the end of braces also
start from a new line.
5. Error return values and exception handling conventions: All functions that
encountering an error condition should either return a 0 or 1 for simplifying the
debugging. On the other hand, Coding guidelines give some general suggestions
regarding the coding style that to be followed for the betterment of understandability and
readability of the code. Some of the coding guidelines are given below :
6. Avoid using a coding style that is too difficult to understand: Code should be easily
understandable. The complex code makes maintenance and debugging difficult and
expensive.
7. Avoid using an identifier for multiple purposes: Each variable should be given a
descriptive and meaningful name indicating the reason behind using it. This is not
possible if an identifier is used for multiple purposes and thus it can lead to confusion to
the reader. Moreover, it leads to more difficulty during future enhancements.
8. Code should be well documented: The code should be properly commented for
understanding easily. Comments regarding the statements increase the understandability
of the code.
9. Length of functions should not be very large: Lengthy functions are very difficult to
understand. That’s why functions should be small enough to carry out small work and
lengthy functions should be broken into small ones for completing small tasks.
10. Try not to use GOTO statement: GOTO statement makes the program unstructured,
thus it reduces the understandability of the program and also debugging becomes
difficult.
Coming up with a brilliant software solution takes lots of testing and tweaking. Throughout this
process, you’re bound to come across error messages and other development roadblocks. When
you know the different types of software bugs you’re likely to encounter, you’ll also know the
best approaches to fixing them.
Keep reading to learn about common bugs you may have to deal with in the software
development process.
Pro Tip
Track and process software bugs online with Jotform’s free Issue Tracker Template.
1. Functional errors
This is a broad type of error that happens whenever software doesn’t behave as intended. For
example, if the end user clicks the “Save” button, but their entered data isn’t saved, this is a
functional error. After some investigation, a software tester may identify a more specifi c culprit
behind the error and reclassify it as a different type of bug.
2. Syntax errors
A syntax error occurs in the source code of a program and prevents the program from being
properly compiled. This type of error is very common and typically occurs when there are one or
more missing or incorrect characters in the code. For example, a single missing bracket could
cause a syntax error.
Compiling programs typically indicate where a syntax error has occurred so the programmer can
fix it.
3. Logic errors
A logic error represents a mistake in the software flow and causes the software to behave
incorrectly. This type of error can cause the program to produce an incorrect output, or even
hang or crash. Unlike syntax errors, logic errors will not prevent a program from compiling.
A common logic error is the infinite loop. Due to poorly written code, the program repeats a
sequence endlessly until it crashes or halts due to external intervention, such as the user closing a
browser window or turning the power off.
4. Calculation errors
Anytime software returns an incorrect value — whether it’s one the end user sees or one that’s
passed to another program — that’s a calculation error. This could happen for several reasons:
5. Unit-level bugs
David LaVine, founder of RocLogic Marketing and a former engineer, says unit-level software
bugs are the most common. They’re also typically the easiest to fix.
After your software is initially coded, you need to see how it works through unit testing —
taking a small, logical section of code and verifying that it performs as designed. This is where
various forms of state machine bugs, calculation errors, and basic logic bugs are often
uncovered.
“The bugs are relatively easy to isolate when you’re dealing with a small amount of code that’s
within your control,” LaVine says. “They’re also relatively easy to replicate because there aren’t
a lot of complex, asynchronous interactions taking place yet.”
“System-level integration bugs are harder to fix because you’re dealing with more than one piece
of software, so the complexity increases while overall visibility decreases,” LaVine says. “This
class of bug is often caused by things like byte-swapping, message parsing, or memory overflow
issues.”
Versatility which allows for the code to be easily adapted for another application.
Compatibility with different hardware.
It should be free of any bugs or defects that may affect the security or dependability of the other application.
Table of Contents
1. Internal reuse – This is when code written internally by a developer team or business is reused for
other projects.
2. External reuse – This is when some third-party tool or code is licensed and employed in a project. This
can be tricky since costs will be involved, and time will be required to learn and implement the tool.
Additionally, it creates a dependency upon an external tool which may lead to issues further down the line.
Lower Cost: Saving on time also allows the business to save on costs. Additionally, by utilizing pre-existing
code, organizations can reduce expenses associated with app development, avoiding the need to hire more
people and obtain additional resources.
Reduced Development Risks: Often, the code being reused is tried and tested. Since it’s already been to
battle and survived, it’s safe to say that the code will be highly reliable and free from defects. This guarantees a
good user experience since the code is likely to run smoothly and be perfectly functional.
Prevents Code Bloat: Bloated code is considered to be needlessly long, slow, and resource-intensive. To
prevent the formation of undesired functionality or code bloat, it is crucial to reuse efficient and simple code, if it
is available, across applications.
Also Read: How to Accelerate Product Release Velocity
1. Security: It’s important to ensure no internal vulnerabilities exist in the code prior to reuse. It’s generally
safer to reuse internal code in comparison to code from third-party sources.
2. Reliability: Code must be trustworthy in order to be reused. By ensuring availability, fault tolerance,
and recoverability, you can guarantee trustworthy and reliable code.
3. Performance Efficiency: Code reusability is only useful if the code being implemented is efficient.
4. Maintainability: It’s important to ensure that the code being reused is fault-tolerant and easily
maintainable.
Code reuse can greatly optimize the development process of applications and increase productivity in
software development teams. It can help save on costs, and time, reduce development risks, and
prevent code bloat.
Several challenges, such as communication or administrative issues, as well as office politics, can
also hinder the potential of code reuse. However, under the right circumstances, code reuse is well
worth implementing.