Examness

Architecture

System Design इंटरव्यू प्रश्न

Scalability, microservices, caching, queues and trade-offs.

38 प्रश्न

  1. 1.

    Improved Fault Tolerance

    शुरुआती

    If a microservice fails, it ideally doesn't bring down the entire system, making the system more resilient.

  2. 2.

    What are the main benefits of using microservices?

    शुरुआती

    Let's look at the main advantages of using microservices:

    Key Benefits

  3. 3.

    Improved Team Dynamics

    शुरुआती

    Thanks to reduced codebase ownership and the interoperability of services, smaller, focused teams can thrive and communicate more efficiently.

  4. 4.

    Flexibility

    शुरुआती

    Decoupling services means one service's issues or updates generally won't affect others, promoting agility.

  5. 5.

    Technology Diversity

    शुरुआती

    Different services can be built using varied languages or frameworks. While this adds some complexity, it allows for best-tool-for-the-job selection.

  6. 6.

    Easier Maintenance

    शुरुआती

    No more unwieldy, monolithic codebases to navigate. With microservices, teams can focus on smaller, specific codebases, thereby enabling more targeted maintenance.

  7. 7.

    Tailored Security Measures

    शुरुआती

    Security policies and mechanisms can be tailored to individual services, potentially reducing the overall attack surface.

  8. 8.

    Scalability

    शुरुआती

    Each microservice can be scaled independently, which is particularly valuable in dynamic, going-viral, or resource-intensive scenarios.

  9. 9.

    Agile Development

    शुरुआती

    Microservices mesh well with Agile, enabling teams to iterate independently, ship updates faster, and adapt to changing requirements more swiftly.

  10. 10.

    When should the Singleton pattern be applied and what are its drawbacks?

    मध्यम

    While the Singleton pattern offers benefits such as a single point of access and delayed instantiation, its drawbacks and potential misapplications are worth considering.

    Key Considerations

    Scope of Singleton Behavior

    The Singleton pattern isn't always the most suitable for enabling unique global access. Classes managed by dependency injection (DI) frameworks, for instance, often provide more adaptable and testable mechanisms for context-driven singletons.

    Drawbacks of the Singleton Pattern

    1. Hidden Dependencies: The use of singletons can introduce implicit and potentially unexpected dependencies. This can make the codebase more challenging to understand and debug.
    1. Violation of the Single Responsibility Principle: Singletons often manage their own lifespan and state, going beyond the scope of their primary responsibilities.
    1. Memory Management Baggage: Systems using singletons need to manage memory manually, which can be tedious and error-prone.
    1. Thread Safety Complexity: Ensuring thread safety in a multithreaded environment can be complex and, if done incorrectly, lead to performance bottlenecks or data inconsistencies.
    1. Testability Concerns: Code featuring singletons can be hard to test in isolation, as they introduce global state.
    1. Encapsulation Limitations: Although singletons encapsulate their state within their class, the structure can lead to tight coupling throughout the codebase.
    1. Potential for Abuse and Overuse: Over-reliance on singleton patterns can lead to a monolithic architecture, making the system less flexible and harder to maintain.

    Best Practices for Singleton Usage

    Considering the potential drawbacks, it's good to adhere to these best practices:

    1. Use Singleton with Caution: Evaluate if other design patterns, such as factory patterns, or frameworks like DI might be a better fit.
    1. Deliver Concise Responsibilities: Let a singleton manage one responsibility or functionality.
    1. Apply Lazy Initialization Judiciously: While delaying creation can save resources, verify that it doesn't introduce state inconsistency.
    1. Ensure Thread Safety When Appropriate: Utilize methods like double-checked locking or initialize-on-demand patterns in multithreaded environments to maintain data integrity.
    1. Focus on Maintaining Global State: If your primary goal is to preserve global state, view the singleton pattern as one of the tools at your disposal.
    1. Use DI for Wider Flexibility: Combine the benefits of DI with the clarity and convenience of singleton where it makes sense.

    Explore all 85 answers here 👉 Devinterview.io - Software Architecture

  11. 11.

    Explain the Publish-Subscribe pattern and its applications

    मध्यम

    Instead, they define the character of the message using classes and descriptions, and subscribers subscribed interested subjects receive those messages.

    Core Components

    • Publisher: The sender of the messages. It doesn't direct messages to specific recipients but instead classifies published messages. Each message has a category or topic that is used to route it to the interested subscribers.
    • Subscriber: Recipient of the messages. It expresses an interest in one or more topics and only receives messages that are classified with these topics.
    • Message Broker/Mediator: An intermediary that takes on the task of forwarding messages from publishers to subscribers. This component dispatches messages based on the topics to which subscribers have subscribed.

    Mechanism

    1. Registration: Subscribers express their interest or topic preferences to the broker. In some systems, publishers may not be aware of any subscribers.
    1. Message Delivery: When a publisher sends a message, they publish it to a specific topic. The message broker, then, finds the relevant subscribers who have subscribed to that topic and forwards the message to them.

    Application Scenarios

    1. Network and Messaging Systems: Pub-Sub is essential for computers and devices to exchange information in distributed systems, like IoT networks, financial systems, and multiplayer games.
    1. User Interface, Model-View-Controller (MVC), and User Interface: Front-end frameworks like React and Angular use a variant known as Flux architecture. 3. Business Logic and Event-Driven Systems: In complex or multilayered systems with myriad dependencies, Pub-Sub provides a clean separation between components or layers.
    1. Serverless Architectures and Microservices: By supporting asynchronous, decoupled communication, Pub-Sub allows for sound architectural designs, improved concurrency, and scalability, and cost-effective resource consumption.
    1. Data Analytics and Monitoring Tools: Tools that collect and analyze data from various sources and then act upon rules or conditions often use the Pub-Sub pattern for efficient data distribution and analysis.
    1. Database Synchronization and Data Distribution: Distributed data systems like Apache Kafka use the Pub-Sub pattern to synchronize data across nodes, ensuring consistency and fault-tolerance.
  12. 12.

    Discuss the concepts of coupling and cohesion

    मध्यम

    Coupling is the level of dependence that modules have on one another. Low coupling is a design goal, indicating that modules are fairly independent.

    In contrast, cohesion reflects the degree to which the elements within a module belong together. High cohesion suggests that all elements in a module are closely related.

    Practical Example: Data Validation Form

    Consider a form where email and phone number are mandatory.

    • Tight Coupling: Data validation for email and phone are directly within the form submit function.
    • Low Cohesion: The form has loose validation responsibilities, such as checking if email is unique.

    This approach can lead to redundant and error-prone code, especially as the form grows more complex. Instead, one could use a ValidateEmail and ValidatePhoneNumber module, enforcing responsibility and independence.

  13. 13.

    Can you describe the API Gateway pattern and its benefits?

    मध्यम

    The API Gateway acts as a single entry point for a client to access various capabilities of microservices.

    Gateway Responsibilities

    • Request Aggregation: Merges multiple service requests into a unified call to optimize client-server interaction.
    • Response Aggregation: Collects and combines responses before returning them, benefiting clients by reducing network traffic.
    • Caching: Stores frequently accessed data to speed up query responses.
    • Authentication and Authorization: Enforces security policies, often using JWT or OAuth 2.0.
    • Rate Limiting: Controls the quantity of requests to safeguard services from being overwhelmed.
    • Load Balancing: Distributes incoming requests evenly across backend servers to ensure performance and high availability.
    • Service Discovery: Provides a mechanism to identify the location and status of available services.

    Key Benefits

    • Reduced Latency: By optimizing network traffic, it minimizes latency for both requests and responses.
    • Improved Fault-Tolerance: Service failures are isolated, preventing cascading issues. It also helps in providing fallback functionality.
    • Enhanced Security: Offers a centralized layer for various security measures, such as end-to-end encryption.
    • Simplified Client Interface: Clients interact with just one gateway, irrespective of the underlying complicated network of services.
    • Protocol Normalization: Allows backend services to use different protocols (like REST and SOAP) while offering a consistent interface to clients.
    • Data Shape Management: Can transform and normalize data to match what clients expect, hiding backend variations.
    • Operational Insights: Monitors and logs activities across services, aiding in debugging and analytics.

    Contextual Use

    The gateway pattern is particularly useful:

    • In systems built on SOA, where it is used to adapt to modern web-friendly protocols.
    • For modern applications built with microservices, especially when multiple services need to be accessed for a single user action.
    • When integrating with third-party services, helping in managing and securing the integration.

    Code Example: Setting Up an API Gateway

    Here is the Python code:

    from flask import Flask, request
    import requests
    
    app = Flask(__name__)
    
    @app.route('/')
    def api_gateway():
        # Example: Aggregating and forwarding requests
        response1 = requests.get('http://service1.com')
        response2 = requests.get('http://service2.com')
    
        # Further processing of responses
    
        return 'Aggregated response'
  14. 14.

    Describe the Model-View-Controller (MVC) architectural pattern

    मध्यम

    Model-View-Controller (MVC) is an architectural pattern known for its clear separation of concerns. It divides software into three main components, promoting maintainability and scalability.

    Visual Representation

    .png'alt=media&token=245cccca-91d6-412e-91ed-4b0838d00046)

    Key Components

    • Model: Represents the data and logic. It sends updates to the View and Controller.
    • View: User interface components that present data from the Model to the user.
    • Controller: Acts as an interface between Model and View. It processes user input and orchestrates the actions to perform based on that input.

    Core Concepts

    • Event-driven Communication: Components communicate through events or other mechanisms rather than directly calling one another.
    • Unidirectional Data Flow: Data primarily moves from the Model to the View.
    • Loose Coupling: Components are designed to be self-contained and interact with each other through well-defined interfaces, promoting reusability.

    Interaction Flow

    1. User Action: Typically begins with a user input through View components like buttons or forms.
    1. Controller Action: The Controller receives the user input, interprets it for the Model, and triggers appropriate Model updates.
    1. Data Update: The Model is responsible for implementing the requested changes and notifying the View.
    1. View Update: Upon receiving notifications from the Model, the View updates its components to reflect the modified Model state.
    1. User Feedback: The updated View might request user input or display appropriate feedback, initiating another cycle if needed.

    Benefits and Limitations

    Advantages

    • Conceptual Simplicity: Offers a clear structure and predictable data flow.
    • Parallel Development: Different teams or developers can work on each component without interfering with others.
    • Reusability: Each component is designed to be independent and reusable, which reduces code duplication.
    • Testability: Easier to test component logic in isolation.
    • Decoupled Maintenance: Changes to one component (like the UI) can be implemented without affecting others.

    Limitations

    • Potential Complexity: Managing the interactions between Model, View, and Controller can become intricate, especially in large applications.
    • Synchronization: It may not always be straightforward to ensure that the View is in sync with the underlying Model.
    • Two-Way Communication: While primarily unidirectional, MVC can support bi-directional data flow, which can lead to additional complexity.
  15. 15.

    What is Domain-Driven Design (DDD) and how is it related to microservices?

    मध्यम

    Domain-Driven Design (DDD) provides a model for designing and structuring microservices around specific business domains. It helps teams reduce complexity and align better with domain experts.

    Context Boundaries

    In DDD, a Bounded Context establishes clear boundaries for a domain model, focusing on a specific domain of knowledge. These boundaries help microservice teams to operate autonomously, evolving their services within a set context.

    Ubiquitous Language

    Ubiquitous Language is a shared vocabulary that unites developers and domain experts. Microservices within a Bounded Context are built around this common language, facilitating clear communication and a deeper domain understanding.

    Strong Consistency and Relational Databases

    Within a Bounded Context, microservices share a consistent data model, often dealing with strong consistency and using relational databases. This cohesion simplifies integrity checks and data relationships.

    Code Example

    1. PaymentService Microservice:

    ``java @Entity public class Payment { @Id private String paymentId; private String orderId; // ... other fields and methods } ``

    1. OrderService Microservice:

    ```java @Entity public class Order { @Id private String orderId; // ... other fields and methods }

    public void updateOrderWithPayment(String orderId, String paymentId) { // Update the order } ```

    1. OrderDetailsService Microservice:

    ``java @Entity public class OrderDetail { @EmbeddedId private OrderDetailId orderDetailId; private String orderId; private String itemId; private int quantity; // ... other fields and methods } ``

  16. 16.

    What is the principle of least knowledge (Law of Demeter) in architecture?

    मध्यम

    The principle of least knowledge (LoD), also known as the law of Demeter, emphasizes reducing the dependencies between modules and classes to make systems more modular, easier to maintain, and less prone to errors.

    Core Tenets

    The Law of Demeter distills the following key principles:

    • Locality of Knowledge: Each module has detailed knowledge about its immediate collaborators.
    • Black Box Design: A module's internal state is considered its private information, and interactions are based on public interfaces.

    Verbal Expressions

    The Law of Demeter has been formulated using several verbal expressions, offering different perspectives on its core tenets:

    "Don't talk to strangers"

    This phrase is an analogue for the principle that objects or methods should have limited access to other entities.

    "Only talk to your immediate friends"

    This expression emphasizes that a module should interact with its closely related modules and avoid extensive collaboration, mitigating the risk of creating tightly coupled systems.

    Code Example: Demeter Principle Violation

    Here is the code:

    public class Owner {
        private Car car;
    
        public Owner() {
            this.car = new Car();
        }
    
        public void startCar() {
            car.start();
        }
    }
    
    public class Car {
        private Engine engine;
    
        public Car() {
            this.engine = new Engine();
        }
    
        public void start() {
            engine.start();
        }
    }
    
    public class Engine {
        public void start() {
            System.out.println("Starting engine");
        }
    }

    In this system, the Owner class knows too much about the Engine class.

    Code Example: Applying the Law of Demeter

    Here is the code:

    public class Owner {
        private Car car;
    
        public Owner() {
            this.car = new Car();
        }
    
        public void startCar() {
            car.startEngine();
        }
    }
    
    public class Car {
        private Engine engine;
    
        public Car() {
            this.engine = new Engine();
        }
    
        public void startEngine() {
            engine.start();
        }
    }
    
    public class Engine {
        public void start() {
            System.out.println("Starting engine");
        }
    }

    In this improved structure, the Owner class directly communicates with the Car class, maintaining a more logical and appropriate communication pattern.

  17. 17.

    Define "modularity" in software architecture

    मध्यम

    Modularity in software architecture refers to the degree to which a software system can be broken down into separate functional or logical modules or components. These modules are often designed to be distinct, yet interrelated, promoting ease of development, flexibility, maintainability, and reusability.

    Core Attributes of Modularity

    • Encapsulation: Modules expose only a well-defined, limited interface, keeping internal functionalities hidden. This reduces complexity and the possibilities of unintended interactions.
    • High Cohesion: Modules contain closely-related functions, promoting focused responsibilities. This characteristic is vital for both the maintenance and reusability of code.
    • Loose Coupling: Modules should be connected in a way that minimizes their interdependence. Reducing the dependencies between modules makes it easier to replace, update, and reconfigure individual components.
    • Abstraction: Modules are self-contained units with defined interfaces, abstracted away from unnecessary internal details.

    Benefits of Modularity

    • Enhanced Maintainability: Simplified testing, debugging, and maintenance procedures.
    • Clear Design Boundaries: Improved team workflows, as individual developers or groups can focus on specific modules without needing to understand the entire system.
    • Reusability: Modules that aren't tightly coupled often lead to more reusable code.
    • Parallel Development: Modularity lends itself well to parallel development, enabling team members to work on different modules simultaneously.
    • Flexibility: Modules can often be replaced, updated, or augmented with new functionality easily.

    Real-World Application

    • Android Applications: Based on a modular architecture, developers can build individual modules known as "feature modules" that represent a specific set of features or functionalities in the app.
    • Cloud Computing: The microservices architectural style is modular, where each microservice is a self-contained unit that can be developed, deployed, and scaled independently.
    • Game Development: Engines such as Unity and Unreal Engine use modular structures made of components and subsystems to manage game objects and systems.
    • Web Development: Frameworks like Angular or React structure applications as modular components, each handling a particular piece of the user interface or corresponding functionality.
  18. 18.

    What is the layered architectural pattern?

    मध्यम

    The Layered Architecture Pattern is characterized by the hierarchical organization of the software components into distinct layers, each serving a specific role and potentially necessitating communication with adjacent layers. It's also known as the N-Tier Architecture or the Multi-Tier Architecture.

    Key Components

    • Layers: The logical groupings of software elements that collaborate to perform specific tasks or operations. There can be any level of separation, with most applications distinguishing between three primary layers: Presentation, Business Logic, and Data.
    • Inter-Layer Communication: Layers communicate with one another in a strictly defined order. Typically, lower layers serve as a foundation and are only aware of themselves and those directly above (direct dependency), while higher layers are cognizant of the layers beneath them, often using defined interfaces (dependencies could be direct or transitive).

    Advantages

    • Modularity: By compartmentalizing functionalities, the architecture enhances manageability and promotes code reusability.
    • Isolation of Concerns: Each layer focuses on a specific aspect of the application, aiding in code simplicity and maintainability.
    • Flexibility in Development and Updating: Since layers are relatively independent, teams can work on different layers concurrently, and modifications are contained within specific areas, reducing the probability of ripple effects.
    • Consistently Defined Structure: The anticipated interactions between the various layers are consistently outlined, offering a robust blueprint for development and maintenance processes.
    • Scalability: The architecture can adapt to scaling demands. For instance, if the business layer is strained, more resources can be allocated to it without necessitating changes in the presentation or data layers.

    Common Use Cases

    • Web Applications: They frequently adopt a 3-Tier architecture, dividing responsibilities across the client-side interface (presentation), server-side processing (business logic), and database management systems (data).
    • Enterprise Solutions: Complex business operations can often benefit from an architecture that rigorously separates UI, logic, and data.
    • Systems with Numerous Users: Scalability is essential for products and services that have many users. A layered architecture helps manage this by compartmentalizing components.

    Drawbacks

    • Potential Overhead: The need for data and control flow to traverse layers might lead to performance implications.
    • Rigidity in Change Management: Modifying one layer might necessitate adjustments in other dependent layers. This domino effect can make the system less flexible.
    • Complexity with Many Layers: While the architecture can include numerous layers, this can lead to increased complexity, making the system challenging to comprehend and maintain.

    Code Example: Basic Three-Layer Architecture

    Layers

    Presentation Layer:

    This layer is responsible for displaying information to users and handling user interactions. In a web application, it might correspond to the View. In a Windows Forms app, it is the form itself.

    public class UserController
    {
        private readonly UserService _userService;
    
        public UserController(UserService userService)
        {
            _userService = userService;
        }
    
        public void DisplayUserInfo(string userId)
        {
            var userInfo = _userService.GetUserInfo(userId);
            // Pass userInfo to the view for display
        }
    }

    Business Logic Layer:

    This layer implements the business rules and processes. It acts as an intermediary between the presentation and data layers.

    public class UserService
    {
        private readonly UserRepository _userRepository;
    
        public UserService(UserRepository userRepository)
        {
            _userRepository = userRepository;
        }
    
        public UserInfo GetUserInfo(string userId)
        {
            // Apply any business rules or logic here before retrieving the user data
            var userInfo = _userRepository.GetUserById(userId);
            return userInfo;
        }
    }

    Data Layer:

    This layer is responsible for data storage and access, such as a database, file system, or web service.

    public class UserRepository
    {
        public UserInfo GetUserById(string userId)
        {
            // Code to interact with the data storage medium to retrieve user information
        }
    }

    Wiring the Layers

    In a real-world application, you might perform dependency injection to wire up the layers. Here is the C# code:

    // In your Main method or application entry point
    var userRepository = new UserRepository();  // A concrete implementation
    var userService = new UserService(userRepository);
    var userController = new UserController(userService);

    In many modern systems, this wiring could be handled by an IoC container.

  19. 19.

    What are the SOLID principles of object-oriented design?

    मध्यम

    SOLID is an acronym that represents the five basic principles of object-oriented programming. These guidelines help to enhance code readability, reusability, and maintainability.

    The SOLID Principles

    1. Single Responsibility Principle (SRP)

    A class should have only one reason to change. In other words, it should have only one responsibility.

    1. Open/Closed Principle (OCP)

    A module (i.e., a function or a class) should be open for extension, but closed for modification.

    1. Liskov Substitution Principle (LSP)

    Derived classes should be substitutable for their base classes, meaning that they should share the same interface and be used interchangeably with objects of the base class.

    1. Interface Segregation Principle (ISP)

    Many client-specific interfaces are better than one general-purpose interface.

    1. Dependency Inversion Principle (DIP)

    High-level modules should not depend on low-level modules. Both should depend on abstractions. Additionally, abstractions should not depend on details; details should depend on abstractions.

    What the SOLID Principles Mean

    • SRP: A class should be responsible for doing one thing and doing it well.
    • OCP: Systems should be designed so that they are open for extension but closed for modification. This generally means that when new functionality is required or specifications change, the existing code should not need to be modified. Instead, the code should be easy to extend so that new functionality can be added.
    • LSP: This principle deals with whether a derived class is a true subtype of the base class. Essentially, it means that derived classes should not change the behavior of the base class.
    • ISP: This principle deals with the idea that classes or modules should not have to depend on interfaces that they don't use. It's better to have multiple small, specific interfaces than one large general one.
    • DIP: A high-level class should not care about the details of its dependencies. This means that interfaces or abstractions should be used instead of concrete implementations.
  20. 20.

    What is a 'Service Mesh'? How does it aid in managing microservices?

    मध्यम

    A Service Mesh is a dedicated infrastructure layer that simplifies network requirements for microservices, making communication more reliable, secure, and efficient. It is designed to reduce the operational burden of communication between microservices.

    Why Service Mesh?

    • Zero Trust: Service Meshes ensure secure communication, without relying on individual services to implement security measures consistently.
    • Service Health Monitoring: Service Meshes automate health checks, reducing the risk of misconfigurations.
    • Traffic Management: They provide tools for controlling traffic, such as load balancing, as well as for A/B testing and canary deployments.
    • Adaptive Routing: In response to dynamic changes in service availability and performance, Service Meshes can redirect traffic to healthier services.

    Elements of Service Mesh

    The Service Mesh architecture comprises two primary components:

    • Data Plane: Controls the actual service-to-service traffic. It's made up of proxy servers, such as Envoy or Linkerd, which sit alongside running services to manage traffic.
    • Control Plane: Manages the configuration and policies that the Data Plane enforces. It includes systems like Istio and Consul.

    Key Capabilities

    • Load Balancing: Service Meshes provide intelligent load balancing, distributing requests based on various criteria, like latency or round-robin.
    • Security Features: They offer a suite of security capabilities, including encryption, authentication, and authorization.
    • Traffic Control: Service Meshes enable fine-grained traffic control, allowing you to manage traffic routing, failover, and versioning.
    • Metrics and Tracing: They collect and provide key operational telemetry, making it easier to monitor the health and performance of your microservices.

    Code Example: Service Mesh Components in Kubernetes

    Here is the YAML configuration:

    For the Control Plane:

    apiVersion: v1
    kind: Pod
    metadata:
      name: control-plane-pod
      labels:
        component: control-plane
    spec:
      containers:
      - name: controller
        image: control-plane-image
        ports:
        - containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: control-plane-service
    spec:
      selector:
        component: control-plane
      ports:
      - protocol: TCP
        port: 80
        targetPort: 8080

    For the Data Plane:

    apiVersion: v1
    kind: Pod
    metadata:
      name: service-1-pod
      labels:
        app: service-1
    spec:
      containers:
      - name: service-1-container
        image: service-1-image
        ports:
        - containerPort: 8080
      - name: proxy
        image: envoyproxy/envoy-alpine
      containers:
      - name: service-2-container
        image: service-2-image
        ports:
        - containerPort: 8080
      - name: proxy
        image: envoyproxy/envoy-alpine

    In this example, Envoy serves as the sidecar proxy (Data Plane) injected alongside service-1 and service-2, and the control-plane-pod and control-plane-service represent the control plane.