<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Architectural Styles on CS446/CS646/ECE452 S26</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/</link><description>Recent content in Architectural Styles on CS446/CS646/ECE452 S26</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/index.xml" rel="self" type="application/rss+xml"/><item><title>Pipe-Filter</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/pipe-filter/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/pipe-filter/</guid><description>&lt;h1 id="pipe-filter"&gt;
 Pipe-Filter
 &lt;a class="anchor" href="#pipe-filter"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Pipe-Filter is suitable for applications that require a defined series of (mostly) independent computations to be performed on a stream of data entries.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example component diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="topology-network.png" alt="Pipe-Filter topology example" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component: &lt;strong&gt;Filters&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;each filter transforms input data entry/entries to output data entry/entries.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;local transformations&lt;/em&gt;: no shared state between filters, and minimal knowledge of upstream/downstream.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;incremental processing&lt;/em&gt;: outputs can begin before all inputs are consumed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connector: &lt;strong&gt;Pipes&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;carry data between filters (streams, files, in-memory queues).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pros-and-cons"&gt;
 Pros and cons
 &lt;a class="anchor" href="#pros-and-cons"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;Maintainability: filters can be replaced or improved locally, as long as their input and output formats are stable.&lt;/li&gt;
&lt;li&gt;Efficiency (throughput): supports concurrency naturally by parallelization and stream processing.&lt;/li&gt;
&lt;li&gt;Observability: performing throughput and deadlock analyses is possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Efficiency (latency): (de)serialization and data copying across pipes can be expensive.
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;variant&lt;/em&gt;: using different data formats for each pipe, improves efficiency but adds complexity.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Complexity: debugging end-to-end behaviors across many stages can be non-trivial.&lt;/li&gt;
&lt;li&gt;Not ideal for interactive systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="variants"&gt;
 Variants
 &lt;a class="anchor" href="#variants"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="pipeline"&gt;
 Pipeline
 &lt;a class="anchor" href="#pipeline"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;This variant requires a linear sequence of filters (i.e., each filter has exactly one input pipe and one output pipe).
An example is the pipe operator &lt;code&gt;|&lt;/code&gt; in Unix shells, e.g., the following component diagram shows the command &lt;code&gt;ls | grep '.pdf' | wc -l&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>Layered</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/layered/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/layered/</guid><description>&lt;h1 id="layered"&gt;
 Layered
 &lt;a class="anchor" href="#layered"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Layered architecture is suitable for applications that can be organized into a hierarchy of layers, where each layer provides services to the layer above and uses services from the layer below.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example component diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="topology-3layer.png" alt="Layered topology example" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component: &lt;strong&gt;Layers&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;each layer groups components at similar abstraction level (e.g., UI, domain/business, data/infrastructure).&lt;/li&gt;
&lt;li&gt;a layer usually only depends on layers below it.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connector: method calls (or RPC) across layer boundaries, typically behind interfaces.&lt;/li&gt;
&lt;li&gt;Configuration: a common constraint is that communication happens only between adjacent layers.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pros-and-cons"&gt;
 Pros and cons
 &lt;a class="anchor" href="#pros-and-cons"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;Maintainability: it is often possible to swap implementations within a layer (e.g., replace storage) if contracts are kept; changes in one layer affects at most two adjacent layers.&lt;/li&gt;
&lt;li&gt;Readability: each layer has a consistent abstraction level, making the system easier to understand.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Efficiency: abstractions in high-level functions can add overhead; performance requirements may force the coupling of high-level functions to their low-level implementations (breaking the encapsulation of the layers).&lt;/li&gt;
&lt;li&gt;Not all systems map cleanly to layered structures.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="variants"&gt;
 Variants
 &lt;a class="anchor" href="#variants"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="allowing-non-adjacent-layer-communication-layer-bypass"&gt;
 Allowing non-adjacent layer communication (layer bypass)
 &lt;a class="anchor" href="#allowing-non-adjacent-layer-communication-layer-bypass"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;This variant relaxes the adjacent-layer constraint: a higher layer may call a lower layer directly (e.g., UI calling the data layer) to reduce overhead or boilerplate. It can improve efficiency and development speed for simple flows, but it tends to erode boundaries over time and makes testing/refactoring harder.&lt;/p&gt;</description></item><item><title>Repository</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/repository/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/repository/</guid><description>&lt;h1 id="repository"&gt;
 Repository
 &lt;a class="anchor" href="#repository"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Repository (a.k.a. data-centered) style is suitable when the central challenge is establishing, augmenting, and maintaining a shared body of information.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example component diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="topology-minimal.png" alt="Repository topology example" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component:
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Repository&lt;/strong&gt;: persistent central data store representing the current system state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools and services&lt;/strong&gt;: independent components that can read and write the repository, monitor changes, and perform concurrent computations.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connector: data CRUD operations and change notifications.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An example of this style is a code editor: many features interact through a shared document buffer.&lt;/p&gt;</description></item><item><title>Implicit Invocation</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/implicit-invocation/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/implicit-invocation/</guid><description>&lt;h1 id="implicit-invocation"&gt;
 Implicit Invocation
 &lt;a class="anchor" href="#implicit-invocation"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Implicit invocation is suitable when components producing events/data do not directly know which other components will consume them.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example component diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="variant-pubsub.png" alt="Publish-subscribe topology" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Publishers&lt;/strong&gt;: emit events/messages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscribers&lt;/strong&gt;: register interest and react when events arrive.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connector: &lt;strong&gt;Events/messages&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;often grouped by topic/channel.&lt;/li&gt;
&lt;li&gt;publishers do not call subscribers directly; the runtime delivery mechanism handles the fan-out to current subscribers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pros-and-cons"&gt;
 Pros and cons
 &lt;a class="anchor" href="#pros-and-cons"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;Maintainability: add/remove subscribers without changing publishers; supports pluggable components at runtime.&lt;/li&gt;
&lt;li&gt;Scalability: asynchronous delivery and buffering can be scaled up to handle spikes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Readability: hidden dependencies between components and unpredictable ordering/timing of execution.&lt;/li&gt;
&lt;li&gt;Debugging/testing: often needs tracing, structured logging, and careful test harnesses to reason about the execution order.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="variants"&gt;
 Variants
 &lt;a class="anchor" href="#variants"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="event-based"&gt;
 Event-based
 &lt;a class="anchor" href="#event-based"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;This variant introduces a shared event bus. Components publish events to the bus and subscribe to events from the bus.
Compared to direct publish-subscribe, the bus makes routing and buffering explicit.&lt;/p&gt;</description></item><item><title>MVVM (MVC, MVP)</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/mvvm/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/mvvm/</guid><description>&lt;h1 id="mvvm"&gt;
 MVVM
 &lt;a class="anchor" href="#mvvm"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;MVVM (Model–View–ViewModel) is a presentation-oriented architectural style commonly used in modern UI applications (including Android).
The primary goal is to separate the UI logic (which usually needs to be real-time interactive), UI state, and business logic.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example package/class diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="topology-mvvm-demo.png" alt="MVVM topology example" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Components
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;View&lt;/strong&gt;: renders UI; listens to user events; reacts to UI state changes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ViewModel&lt;/strong&gt;: holds UI state; redirects user events to business logic; fills data into UI state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt;: business logic, network calls, data access, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connector:
&lt;ul&gt;
&lt;li&gt;control flows from View to ViewModel to Model;&lt;/li&gt;
&lt;li&gt;data flows backwards.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pros-and-cons"&gt;
 Pros and cons
 &lt;a class="anchor" href="#pros-and-cons"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;Maintainability: UI logic and business logic are easier to maintain separately.&lt;/li&gt;
&lt;li&gt;Separation of concerns: UI logic and business logic do not mix together; UI elements can have different (usually shorter) lifetimes than the ViewModel and Model classes.&lt;/li&gt;
&lt;li&gt;Reusability: one ViewModel can be shared by multiple Views when needed.&lt;/li&gt;
&lt;li&gt;Testability: ViewModel and Model can be easily unit-tested without rendering UI.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Overkill for simple state: the extra abstraction may slow down simple projects.&lt;/li&gt;
&lt;li&gt;Debugging: reactive flows and state propagation can be harder to trace without good tooling.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="variants"&gt;
 Variants
 &lt;a class="anchor" href="#variants"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;MVC and MVP are older versions of MVVM that aim for similar goals (separation of concerns) but differ in where UI logic/state lives and how tightly the &amp;ldquo;middle&amp;rdquo; component is coupled to the view.&lt;/p&gt;</description></item><item><title>Server-Client (Microservices, Serverless)</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/server-client/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/server-client/</guid><description>&lt;h1 id="server-client"&gt;
 Server-Client
 &lt;a class="anchor" href="#server-client"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Server-client is suitable for applications that involve distributed data and processing across multiple components over a network.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Basic component diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="topology-minimal.png" alt="Server-client topology example" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clients&lt;/strong&gt;: initiate requests.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Servers&lt;/strong&gt;: respond to requests and provide services/data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Connector:
&lt;ul&gt;
&lt;li&gt;request/response (HTTP, REST, RPC) or message-based communication (queues/streams).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Server-client is widely adopted in various applications:&lt;/p&gt;
&lt;table&gt;&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;img src="examples-db.png" alt="Database viewer / server" /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;p&gt;&lt;img src="examples-file.png" alt="File explorer / server" /&gt;&lt;/p&gt;
&lt;/td&gt;
&lt;/tr&gt;&lt;tr&gt;
&lt;td&gt;
&lt;p&gt;&lt;img src="examples-terminal.png" alt="Terminal window / server" /&gt;&lt;/p&gt;</description></item><item><title>Process-Control</title><link>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/process-control/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://lanortha.github.io/CS446-S26/docs/lectures/architectural-styles/process-control/</guid><description>&lt;h1 id="process-control"&gt;
 Process-Control
 &lt;a class="anchor" href="#process-control"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;Process-control (aka feedback-control) style is suitable when the system’s purpose is to maintain certain properties of a process output near a desired reference value (set point), despite disturbances.&lt;/p&gt;
&lt;h2 id="topology"&gt;
 Topology
 &lt;a class="anchor" href="#topology"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Example component diagram:&lt;/p&gt;
&lt;p&gt;&lt;img src="topology-feedback-loop.png" alt="Feedback control loop topology" /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Component
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Controller&lt;/strong&gt;: computes actions based on the set point and feedback.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Processor&lt;/strong&gt;: the (physical or software) component being controlled; it usually comes with some observers/sensors to collect telemetry data as feedback.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pros-and-cons"&gt;
 Pros and cons
 &lt;a class="anchor" href="#pros-and-cons"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Pros
&lt;ul&gt;
&lt;li&gt;Robustness: can adapt to changing conditions and keep the system within acceptable bounds.&lt;/li&gt;
&lt;li&gt;Autonomy: supports self-correcting behaviors (within designed limits).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cons
&lt;ul&gt;
&lt;li&gt;Cost and complexity: requires monitoring/telemetry, calibration, and control logic.&lt;/li&gt;
&lt;li&gt;Sensitive to latency: delayed or noisy feedback can cause oscillations/instability.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="real-world-examples"&gt;
 Real-world examples
 &lt;a class="anchor" href="#real-world-examples"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;h3 id="autonomous-driving"&gt;
 Autonomous driving
 &lt;a class="anchor" href="#autonomous-driving"&gt;#&lt;/a&gt;
&lt;/h3&gt;
&lt;p&gt;Many components in an autonomous driving system are built around the process-control style.
Consider steering: given a desired steering angle to follow a trajectory (set point), the system (controller) computes the torque command needed to reach that angle and send it to the vehicle&amp;rsquo;s steering actuator (processor); a sensor continuously reports the actual angle (feedback) back to the controller, which can be different than the desired angle because of road conditions, so that the controller can adjust the torque command accordingly.
The same style applies to other components like throttle and braking.&lt;/p&gt;</description></item></channel></rss>