SOFTWARE ARCHITECTURE NOTES
Topics:
• Architecture diagram
• Dry
• Kiss
• Yagni
• Singleton Design Pattern
• Factory Design Pattern
• MVC
• Umbrella Activities
• Software Quality Attributes
Definition of Design Pattern:
A design pattern is a reusable solution to a common problem in software design. It is like a blueprint that
helps developers write clean, organized, and efficient code.
The three main types of design patterns are:
Creational Patterns: Deal with object creation mechanisms and optimizing how objects are instantiated.
Key Patterns:
• Singleton – One instance only (e.g., database connection).
• Factory – Creates objects without specifying exact class (e.g., shape factory).
• Builder – Step-by-step object creation (e.g., building a car).
• Prototype – Cloning existing objects.
• Abstract Factory – Factory of factories (e.g., UI themes).
Structural Patterns: Focus on class/object composition (how objects fit together to form larger structures).
Key Patterns:
• Adapter – Converts one interface to another (e.g., charger adapter).
• Bridge – Separates abstraction from implementation.
• Composite – Treats objects and groups the same way (e.g., folder structure).
• Decorator – Adds features without modifying original class (e.g., adding filters to photos).
• Facade – Provides a simple interface for complex code (e.g., car dashboard).
Behavioral Patterns: Define communication between objects and how they distribute responsibilities.
Key Patterns:
• Observer – Notifies multiple objects when a change happens (e.g., notifications).
• Strategy – Selects a behavior at runtime (e.g., different payment methods).
• Command – Encapsulates a request (e.g., undo/redo feature).
• State – Changes behavior based on state (e.g., traffic light).
Why It Matters
• Creational: Avoid hardcoding object creation (flexibility).
• Structural: Keep code modular and scalable.
• Behavioral: Make interactions clean and extensible.
Singleton Design Pattern:
The Singleton Pattern ensures that only one instance of a class exists and provides a global access point to
that instance.
Key Features of Singleton:
• Single Instance – Only one object is created.
• Global Access – The instance can be accessed from anywhere in the program.
• Private Constructor – Prevents direct instantiation of the class.
Factory Design Pattern:
The Factory Pattern is a creational design pattern that provides an interface for creating objects in a
superclass but lets subclasses decide which class to instantiate.
Why use it?
• Avoids direct object creation using new.
• Supports loose coupling (code is more flexible and maintainable).
• Makes code easier to extend when adding new object types.
Real-Life Example – Ordering a Pizza (Imagine a pizza shop. Instead of preparing each pizza manually, we call
a Pizza Factory, which prepares the pizza for us.)
How factory Works?
• Client Code (Main Method) → Asks the PizzaFactory to create a pizza.
• Factory Class → Decides which pizza class to create.
• Pizza Object → The correct pizza is returned and used.
Now, if we add more pizza types, we only modify the Factory, NOT the main code!
Real-World Examples of Factory Pattern
• Database Connections – A factory creates SQL, MySQL, or MongoDB connections.
• Notification System – A factory generates SMS, Email, or Push notifications.
• Car Manufacturing – A factory produces different car models.
Builder Pattern: The Builder Pattern is a creational design pattern that provides a step-by-step approach to
construct complex objects. Instead of using multiple constructors (which can become difficult to manage),
we use method chaining to create objects with different configurations.
When to Use?
• When a class has too many constructor parameters.
• When we need to build an object step-by-step.
• When the same object needs different configurations.
Key Benefits of the Builder Pattern
• Improves Code Readability – No more messy constructors.
• Supports Method Chaining – Makes object creation clean and flexible.
• Encapsulates Object Creation – Hides unnecessary details.
• Allows Default Values – We can set fallback values if not provided.
• Adds Validations – Prevents incorrect configurations.
UMBRELLA ACTIVITIES: Umbrella activities are a series of steps or procedures followed by a software
development team to maintain the progress, quality, changes, and risks of complete development tasks.
The umbrella activities of a software process are:
1. Software project tracking and control.
2. Risk Management.
3. Software Quality Assurance.
4. Software Configuration Management.
5. Work product preparation and production.
6. Reusability management, Measurement.
Software project tracking and control:
• Project plan and predefined schedule.
• Monitor & Control the predefined schedule,
• Required actions should taken to maintain the schedule.
Risk management:
• Risk is an event that may or may not occur.
• If the event occurs, then it causes some unwanted outcome.
• Proper risk management is required
Software Quality Assurance (SQA):
• SQA is the planned and systematic pattern of activities which are required to give a guarantee of
software quality.
• For example:
o Meetings
o Formal Technical Reviews
o Inspection
o Testing
o Process Improvements to produce good quality software.
Software Configuration Management (SCM)
• Change Control
• Version Control
Work product preparation and production
• Activities that are needed to create the documents, forms, lists, logs and user manuals for
developing a software.
Reusability management
• Reuse the methods
• Object oriented approach
• Components of the software are developed for certain application and are useful for developing
other applications.
DRY (Don't Repeat Yourself):
Definition: Avoid duplicating code by using functions, loops, or inheritance.
Why Use DRY?
Less code duplication = Fewer bugs and maintenance issues.
Easier updates = Fix in one place, applied everywhere.
More readable code = Better structure and reusability.
Real-Life Example: Instead of copy-pasting customer data logic everywhere, store it in a reusable function.
Code Example: public int CalculateDiscount (int price)
{ return price * 10 / 100; }
Why is this better?
Problem:
No duplicate code.
The same "Hello" logic is repeated for Alice and If we change greeting logic, we update it in one
Bob. place.
If we need to greet more people, we copy-paste Works for any name, not just Alice or Brian.
more methods (bad practice).
Why is this better?
Problem: Each method repeats the same One method handles all cases.
[Link] logic. Easier to update message formatting.
KISS (Keep It Simple, Stupid): Write simple and easy-to-understand code.
Code Example:
// Complex Code
foreach(var item in list) {
if([Link] > 50) {
[Link](item); } }
//Simple Code
var expensiveItems = [Link](x => [Link] > 50).ToList();
Key Takeaways for KISS
• Keep code short & simple.
• Remove unnecessary logic.
• Use built-in functions where possible.
• Write code that's easy to read and maintain.
YAGNI (You Ain’t Gonna Need It): Don't add features before they are needed.
Real-Life Example: Avoid adding AI features in an app before knowing if users need them.
// Don't write extra methods if they are not required yet!
Key Takeaways for YAGNI
• Only write the code you need right now.
• Avoid adding unnecessary features "just in case."
• Less code = fewer bugs and easier maintenance.
• New features can be added when required.
MVC (Model-View-Controller) Overview
MVC is a design pattern that separates an application into three interconnected components to improve
maintainability, scalability, and flexibility.
1. Model
• Represents data and business logic.
• Handles database operations (fetching, updating, deleting data).
• Notifies the View when data changes (in some implementations).
Example: A Book class with properties like: Title, Author, and ISBN.
2. View
• Responsible for displaying data (UI).
• Receives data from the Model and renders it (e.g., HTML, JSON).
• No business logic—only presentation.
Example: A webpage showing a list of books.
3. Controller
• Acts as an intermediary between Model and View.
• Processes user input (e.g., form submissions, API requests).
• Updates the Model and selects the appropriate View.
Example: A controller that receives a request to "Add Book" and tells the Model to save it.
Advantages of MVC
• Separation of Concerns – Easier maintenance and debugging.
• Reusability – Models and Views can be reused.
• Scalability – Components can be developed independently.
• Testability – Business logic (Model) can be tested separately from UI (View).
Step 1: Set Up Your Environment Step 2: Create a New [Link] Core Web API
Make sure you have the following installed: Project
.NET SDK (latest version recommended) Open Visual Studio.
Visual Studio or VS Code Click on "Create a new project".
Postman or curl (for testing) Select [Link] Core Web API.
Name the project (e.g., MyRestApi), choose
location, and click Next.
Choose the .NET version (e.g., .NET 7 or 8),
uncheck
Enable OpenAPI support if you don’t need Swagger
right now and click Create. [OPTIONAL]
Step 3: Define a Model (e.g., [Link]) Step 4: Create a Contoller
Create a Models folder and add a class [Link]: In the Controllers folder, create a new controller
namespace [Link] [Link]
{ using [Link];
public class Book using [Link];
{ using [Link];
public int Id { get; set; } using [Link];
public string Title { get; set; }
public string Author { get; set; } namespace [Link]
} {
} [ApiController]
[Route("api/[controller]")]
---------------------------------------------------------------- public class BooksController : ControllerBase
{
Step 5: Run and Test the API private static List<Book> books = new
If you're using Visual Studio: Press F5 or Ctrl + F5 to List<Book>
run the project. {
If you're using CLI: dotnet run new Book { Id = 1, Title = "The Hobbit", Author
Use Postman or curl to test: = "J.R.R. Tolkien" },
GET /api/books [HttpGet] new Book { Id = 2, Title = "1984", Author =
GET /api/books/1 [HttpGet("{id}")] "George Orwell" }
POST /api/books [HttpPost] };
PUT /api/books/1 [HttpPut("{id}")] [HttpGet]
DELETE /api/books/1 [HttpDelete("{id}")] public ActionResult<IEnumerable<Book>>
GetBooks() => books;
[HttpGet("{id}")]
public ActionResult<Book> GetBook(int id)
{
var book = [Link](b => [Link] ==
id);
if (book == null)
return NotFound();
return book;
}
[HttpPost]
public ActionResult<Book> CreateBook(Book
book)
{
[Link] = [Link](b => [Link]) + 1;
[Link](book);
return CreatedAtAction(nameof(GetBook),
new { id = [Link] }, book);
}
[HttpPut("{id}")]
public IActionResult UpdateBook(int id, Book
updatedBook)
{
var book = [Link](b => [Link] ==
id);
if (book == null)
return NotFound();
[Link] = [Link];
[Link] = [Link];
return NoContent();
}
[HttpDelete("{id}")]
public IActionResult DeleteBook(int id)
{
var book = [Link](b => [Link] ==
id);
if (book == null)
return NotFound();
[Link](book);
return NoContent();
}
}
}
Quality Attributes:
What is Quality?
• Fit for Purpose: Meets intended use.
• Conformance to Requirements: Follows specifications.
• Quality is Cost/Price: Higher quality often means higher cost; users pay for value.
• Quality is a Standard: Complies with industry best practices.
• Quality is Value for Performance: Balances performance and cost.
• Quality is an Experience: Ensures user satisfaction.
Levels of Requirement
1. Business Requirements
Purpose: Define the high-level objectives and strategic goals of the organization.
Document: Vision and Scope Document.
2. User Requirements
Purpose: Describe what users need to achieve with the system (from an end-user perspective).
Document: Use Cases or User Stories.
3. Functional Requirements
Purpose: Specify the system’s behaviors, features, and functionalities to meet user needs.
Document: Software Requirements Specification (SRS).
4. Software Requirements:
Purpose: Technical details on how the system implements functionalities (e.g., APIs, databases).
Document: SRS (detailed section).
Quality Attributes:
Quality attributes define how well a software system performs under specific conditions. They go beyond just
what a system does (functional requirements) and describe how well it behaves.
1. Responsiveness
• Measures how quickly the system reacts to user input.
• Delays cause frustration and the perception that the system is broken.
• Not equal to performance — it’s about user-perceived delay.
• Operations should complete within 3–5 seconds under normal load.
• Causes of performance issues:
o Code complexity
o Redundancy
o Poor design
o Slow servers
o No load balancing
o Sudden traffic spikes
2. Scalability
• Ability to handle growth in users, data, or functionality.
• A scalable system stays stable under increased load or changes.
• Factors affecting scalability:
o Number of simultaneous users
o Quality of code
o Scaling up (vertical): Better hardware (e.g., CPU, RAM)
o Scaling out (horizontal): Adding more machines
• Scaling up gives better performance, but scaling out adds flexibility.
3. Usability
• Refers to how easily users can interact with the system.
• Key traits:
o Efficient
o Time-saving
o Easy to learn
o Learnable by observation
o Satisfying to use
4. Security
• Protection from attacks and unauthorized access.
• Includes:
o Authentication: Verifying identity
o Authorization: Defining access rights
o Audit Trails: Logging user actions
o Encryption: Converting data to secure format (ciphertext)
5. Accessibility
• Ensuring the software is usable by everyone, including people with disabilities.
• Broadens the system’s reach and inclusivity.
6. Serviceability
• Ease with which the system can be:
o Monitored
o Diagnosed
o Maintained
• Should allow customer support (self-service, remote, email, phone).
• Tools like logs, alerts, and troubleshooting trees are essential.
7. Extensibility
• Ease of adding new features or modifying existing ones in future.
• Supports system evolution and long-term adaptability.
8. Distributability
• Ability to manage and run multiple systems as a unit.
• Supports distributed development and deployment across nodes.
9. Availability
• Amount of system uptime compared to total time.
• Expressed in “nines” of availability:
o 99% (2 nines): ~88 hrs/year downtime
o 99.9% (3 nines): ~9 hrs/year
o 99.99%: ~53 mins/year
o 99.999%: ~5 mins/year
o And so on...
• Includes planned downtime and upgrade time.
10. Maintainability
• Ability to modify the system easily due to new requirements or fixes.
• Best practices:
o Follow coding standards
o Avoid duplication
o Write clean, simple code
o Think of your code as a story
11. Portability
• Reusability across different platforms, browsers, or OS.
• Enables broader adoption and easier migration.
12. Testability
• Measures how easily a system can be tested.
• Related to:
o Code coverage: How much of the code is tested
o Test coverage: How well requirements are tested
• Types of testing:
o Unit, Integration, Functional, Acceptance
• Coverage types:
o Function Coverage
o Statement Coverage
o Feature, Risk, and Requirements Coverage
• Formula: Code Coverage %= (Tested Lines/Total Lines) ×100
Business Qualities
• Time to Market: Speed of delivery.
• Cost vs. Benefit: ROI from quality.
• Targeted Market: User-fit.
• Legacy Integration: Compatibility with older systems.
Quality Attributes: Visibility and Value
1. User Perspective
• Visible to Users:
o Positive: Features (directly experienced).
o Negative: Defects (e.g., crashes, slow performance).
• Invisible to Users (Until Failure):
o Positive: Architecture, refactoring, process automation, non-functional requirements (e.g.,
security, scalability).
o Negative: Technical debt (hidden inefficiencies that surface later).
2. Business Impact
• Success Factors:
o Functional Requirements: What the system does.
o Quality Attributes: How well it does it (e.g., reliability under load).
• Failure Risks:
o Missing quality attributes (e.g., poor scalability) can doom a system just like missing
features.
Architecture Qualities
1. Conceptual Integrity
• Definition: A unified design vision across all system levels.
• Why It Matters: Ensures consistency, reduces complexity, and aligns with business goals.
2. Buildability
• Definition: Feasibility to develop with available resources while accommodating changes.
• Why It Matters: Balances innovation with practical constraints (team skills, timelines).
Why Quality Attributes Are Critical
1. Invisible Foundations:
a. Attributes like security or scalability go unnoticed when working but cause major disruptions
when they fail (e.g., downtime, breaches).
2. Sustainability:
a. Poor non-functional quality leads to technical debt, higher maintenance costs, and user
attrition.
3. User Trust:
a. A system that’s fast, secure, and reliable fosters long-term engagement.