<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vinko Buble</title>
    <description>The latest articles on DEV Community by Vinko Buble (@vinko_buble).</description>
    <link>https://dev.to/vinko_buble</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2877508%2Ff61cc160-7e74-41c8-b225-f38950a972d2.jpg</url>
      <title>DEV Community: Vinko Buble</title>
      <link>https://dev.to/vinko_buble</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vinko_buble"/>
    <language>en</language>
    <item>
      <title>Execution Flows Programming Paradigm - Harvesting the Power of Nullary Functions</title>
      <dc:creator>Vinko Buble</dc:creator>
      <pubDate>Mon, 17 Feb 2025 23:52:57 +0000</pubDate>
      <link>https://dev.to/vinko_buble/execution-flows-programming-paradigm-harvesting-the-power-of-nullary-functions-2j4o</link>
      <guid>https://dev.to/vinko_buble/execution-flows-programming-paradigm-harvesting-the-power-of-nullary-functions-2j4o</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Check out the Python open-source project &lt;a href="https://github.com/execution-flows/flow-compose" rel="noopener noreferrer"&gt;Flow Compose&lt;/a&gt;, a tool that facilitates the implementation of the &lt;strong&gt;Execution Flows&lt;/strong&gt; programming paradigm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Function as a Core Construct
&lt;/h2&gt;

&lt;p&gt;All programming languages revolve around functions as fundamental building blocks. We encapsulate code within functions and invoke them at runtime. In this discussion, we focus on one essential characteristic of functions: &lt;strong&gt;input arguments.&lt;/strong&gt; Functions rely on input arguments to access data and operate effectively.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcha8v00yajbm7xa0ark.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvcha8v00yajbm7xa0ark.png" alt="Functions need to pass arguments." width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 1.&lt;/strong&gt; A simplified diagram illustrating how functions operate. Colored boxes represent the function's input arguments.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Function Input Arguments
&lt;/h3&gt;

&lt;p&gt;A caller function must be aware of all required data and pass it to the called function through input arguments.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;object-oriented programming (OOP),&lt;/strong&gt; additional data can be accessed through object member variables, reducing the reliance on function arguments. However, this approach is limited to the member variables of the specific object. Furthermore, adding new member variables to a class or object still requires passing them as arguments during object construction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explosion of Function Variations
&lt;/h3&gt;

&lt;p&gt;As a software system expands its functionality, the number of functions grows exponentially. Variations of functions emerge to accommodate different use cases, leading to an increasingly complex codebase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi020earb8ihy6l5r23h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi020earb8ihy6l5r23h.png" alt="The complexity of the codebase grows exponentially." width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Figure 2.&lt;/strong&gt; The complexity of the codebase grows exponentially, even with continuous code refactoring.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Each layer represents an application layer, such as the API, business logic, domain-specific components, or data transformation. Sub-numbers indicate variations in use cases and branching within these layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Can't Refactoring Help?
&lt;/h3&gt;

&lt;p&gt;The extent of codebase refactoring is irrelevant because refactoring merely &lt;strong&gt;shifts complexity&lt;/strong&gt; from one form to another. It can reduce a small number of massive, branching-heavy functions, but in doing so, it often &lt;strong&gt;explodes into an enormous number of smaller, interdependent functions, forming a complex execution graph&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2&lt;/strong&gt; is actually more representative of a refactored codebase—one where complexity is distributed across a large number of smaller, interconnected functions. However, real-world software architectures are far more intricate than this diagram suggests. These diagrams serve only to illustrate the core idea.  &lt;/p&gt;

&lt;p&gt;For applications with &lt;strong&gt;a small number of features and use cases,&lt;/strong&gt; copying and pasting a few functions is rarely a concern. However, in &lt;strong&gt;enterprise software,&lt;/strong&gt; the sheer scale of features and customizations &lt;strong&gt;drives exponential growth in branching and function variations&lt;/strong&gt;, making complexity unavoidable.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Handling a Code Change
&lt;/h3&gt;

&lt;p&gt;Code changes often require the introduction of a new data element. The most common way to deliver data is through input arguments. As a result, all functions involved in the feature must expand their input arguments to accommodate the change. This effect is known as &lt;strong&gt;“argument drilling.”&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0s3cjyzsa2vgfvsgeg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0s3cjyzsa2vgfvsgeg2.png" alt="Argument drilling" width="800" height="647"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Figure 3.&lt;/strong&gt; &lt;em&gt;"Argument drilling"&lt;/em&gt; – A red box represents a new input argument required by &lt;em&gt;Func 4&lt;/em&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unfortunately, &lt;strong&gt;argument drilling&lt;/strong&gt; has a significant impact, as it requires modifying not only all functions in the chain but also creating new function variations.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6wgy7zwnjmw1yw64rkr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6wgy7zwnjmw1yw64rkr.png" alt="The magnitude of a code change" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 4.&lt;/strong&gt; The magnitude of a “simple” code change in a large system.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"Simple code changes" become complex in large systems because the number of touchpoints &lt;strong&gt;grows exponentially&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution Flows Programming Paradigm
&lt;/h2&gt;

&lt;p&gt;The benefits of the &lt;strong&gt;Execution Flows&lt;/strong&gt; programming paradigm stem from three key characteristics:&lt;/p&gt;

&lt;p&gt;1) &lt;strong&gt;Functions take no arguments&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
2) &lt;strong&gt;Functions are mixins&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
3) &lt;strong&gt;Functions use alias names&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Let’s explore each of these in more detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing Methods and Properties as Nullary Functions
&lt;/h3&gt;

&lt;p&gt;The first significant difference in the &lt;strong&gt;Execution Flows&lt;/strong&gt; programming paradigm is that a function (referred to as a &lt;strong&gt;method&lt;/strong&gt;) can access any data point (referred to as a &lt;strong&gt;property&lt;/strong&gt;) available in the flow context.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffv77rlijjs85a6m5zajq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffv77rlijjs85a6m5zajq.png" alt="Methods have direct access to properties" width="800" height="1277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;_&lt;strong&gt;Figure 5.&lt;/strong&gt; Execution flow provides data properties (&lt;strong&gt;colored boxes&lt;/strong&gt;) to its methods directly from the flow context, eliminating the need to pass them as arguments.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because data properties are directly available to any method, methods rarely require arguments. When they do, these arguments are &lt;strong&gt;local and ephemeral&lt;/strong&gt;, such as an index or the current item in a loop, which is readily available within the method's scope.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Methods and Properties as Mixins
&lt;/h3&gt;

&lt;p&gt;The second key characteristic of methods and properties in the &lt;strong&gt;Execution Flows&lt;/strong&gt; paradigm is that they function as &lt;strong&gt;mixins&lt;/strong&gt;. When needed, a method or property can be added to any flow.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk74l8pw7fevj65c1intz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk74l8pw7fevj65c1intz.png" alt="Methods and properties function as mixins" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 6.&lt;/strong&gt; Methods and properties function as &lt;strong&gt;mixins&lt;/strong&gt; — a single instance can be added to multiple flows.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Methods and Properties Are Referenced Using an Alias Name
&lt;/h3&gt;

&lt;p&gt;The third key aspect of mixins — whether methods or properties — is that they reference other mixins using an &lt;strong&gt;alias name&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;For example, &lt;em&gt;Method 1-1&lt;/em&gt; in &lt;em&gt;Figure 6&lt;/em&gt; calls &lt;em&gt;Method 2&lt;/em&gt;, without directly specifying &lt;em&gt;Method 2-1&lt;/em&gt; or &lt;em&gt;Method 2-2&lt;/em&gt;. Instead, the &lt;strong&gt;Flow&lt;/strong&gt; determines which implementation of &lt;em&gt;Method 2&lt;/em&gt; will be used: either &lt;em&gt;Method 2-1&lt;/em&gt; or &lt;em&gt;Method 2-2&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Because:&lt;br&gt;&lt;br&gt;
1) &lt;strong&gt;Methods take no arguments&lt;/strong&gt;, reducing dependency on explicit data passing.&lt;br&gt;
2) &lt;strong&gt;Methods are mixins&lt;/strong&gt; and can be added to any flow.&lt;br&gt;
3) &lt;strong&gt;Methods use alias names&lt;/strong&gt; to access other mixins instead of direct references.&lt;/p&gt;

&lt;p&gt;As a result, we achieve &lt;strong&gt;multiple orders of magnitude fewer variations&lt;/strong&gt; in function implementations.  &lt;/p&gt;

&lt;p&gt;Now, let’s explore how much this reduces complexity.  &lt;/p&gt;

&lt;h3&gt;
  
  
  The Complexity of a Code Change in the Execution Flows Programming Paradigm Is...
&lt;/h3&gt;

&lt;p&gt;Unlike other programming paradigms, where code changes lead to variations of functions, &lt;strong&gt;code changes in the Execution Flows paradigm&lt;/strong&gt; are highly localized. A change affects only the &lt;strong&gt;method&lt;/strong&gt; that requires modification and involves adding a new &lt;strong&gt;property&lt;/strong&gt; to the execution flow.  &lt;/p&gt;

&lt;p&gt;Adding a property to a flow is a &lt;strong&gt;one-line change&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuhp4q3wlu5dgas75izw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuhp4q3wlu5dgas75izw.png" alt="Adding a change in Execution Flows" width="798" height="1358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 7.&lt;/strong&gt; The red box represents a new data property used by &lt;em&gt;Method 4&lt;/em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To better understand how localized a code change is, let’s examine what it takes to modify multiple flows that are variations of a similar use case.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7a05fghvokb91xcpp5lb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7a05fghvokb91xcpp5lb.png" alt="Adding a change to many Flows" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Figure 8.&lt;/strong&gt; Implementing a change across multiple flows.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The code change is limited to &lt;em&gt;Method 4-1&lt;/em&gt; and involves adding a new &lt;strong&gt;property mixin&lt;/strong&gt; to the flows that use &lt;em&gt;Method 4-1&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;Adding a property mixin to a flow is a &lt;strong&gt;one-line code change&lt;/strong&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By adopting the &lt;strong&gt;Execution Flows&lt;/strong&gt; paradigm, we reduce the &lt;strong&gt;exponential complexity&lt;/strong&gt; of a code change from &lt;strong&gt;O(kⁿ)&lt;/strong&gt; to &lt;strong&gt;constant complexity O(1)&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;For example, the code change shown in &lt;strong&gt;Figure 8&lt;/strong&gt; required modifying only a single &lt;strong&gt;method&lt;/strong&gt; and adding a &lt;strong&gt;property&lt;/strong&gt; to a fixed number of flows.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can check out the Python open-source project &lt;a href="https://github.com/execution-flows/flow-compose" rel="noopener noreferrer"&gt;Flow Compose&lt;/a&gt;, a tool that facilitates the implementation of the &lt;strong&gt;Execution Flows&lt;/strong&gt; programming paradigm.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>executionflows</category>
      <category>flowcompose</category>
    </item>
  </channel>
</rss>
