tag:blogger.com,1999:blog-2743572045591506662024-03-05T07:06:22.725-08:00Inversion of Coupling ControlInversion of Coupling ControlDaniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-274357204559150666.post-21930523485921094272021-01-05T19:09:00.010-08:002021-01-06T01:33:12.108-08:00Performance Improvements for TechEmpower Round 20<p>OfficeFloor is turning it's attention to improving performance now that it's underlying concepts have been defined.</p><p>OfficeFloor primarily is <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a> to avoid the <a href="https://sagenschneider.blogspot.com/2019/08/what-is-oo-matrix.html" target="_blank">OO Matrix</a>. This <a href="https://sagenschneider.blogspot.com/2020/11/officefloor-going-beyond-dependency.html" target="_blank">goes beyond dependency injection</a> to include <a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">function/continuation injection</a> and <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">thread injection</a>. In our writings, we've come to understand the <a href="https://sagenschneider.blogspot.com/2020/01/monad-with-iocc-provides-processthread.html" target="_blank">fundamental model</a>.</p><p>However, while some frameworks claim functionality is more important than performance, we at OfficeFloor believe that's just incomplete solutions leaking cumbersome work arounds. Take for example, aspect oriented programming in Spring, where the implementation is layers of reflective calls that hamper performance. In OfficeFloor, everything is executed in discrete functions, or more correctly <a href="https://sagenschneider.blogspot.com/2019/11/first-class-procedure-type-system-for.html" target="_blank">first class procedures</a>. This results in the application being a list of functions executed one after another. An aspect is just a function inserted into the list. Therefore, the cost of an aspect in OfficeFloor incurs no additional overhead costs. But yes, we admit, there is overheads managing the execution of the list of functions.</p><p>So now that the inversion of coupling control solution is understood, the focus has been to look at optimisations. And what better way to look at improving performance than competing against other frameworks. Hence, we very much appreciate the work by the <a href="https://www.techempower.com/benchmarks/" target="_blank">TechEmpower Benchmarks</a>.</p><p>However, truth be told, OfficeFloor's focus has been both on improving optimisations and increasing third party integrations to inject into OfficeFloor applications. So from round 19 to round 20 of the TechEmpower Benchmarks, OfficeFloor has added ability for asynchronous programming. This has opened the door to using technologies such as <a href="https://officefloor.net/tutorials/ReactorHttpServer/index.html" target="_blank">Reactor</a> and in particular <a href="https://r2dbc.io/" target="_blank">R2DBC</a> for asynchronous database interaction.</p><p>Asynchronous frameworks seem to dominate the top of the TechEmpower Benchmarks. Now with Project Loom claiming negligible threading overheads this may change in future years. However, we doubt a model of "negligible threading contention" will out perform the no threading contention of the single threaded asynchronous frameworks. But this is just conjecture without real numbers to back it up. So let's focus on the real numbers of round 20.</p><p>The most interesting inclusions by OfficeFloor for round 20 are:</p><p></p><ul style="text-align: left;"><li>officefloor-raw using R2DBC to provide implementations for the database tests</li><li>officefloor-async providing R2DBC solution</li><li>officefloor-raw using thread affinity to increase throughput</li><li>ByteBuffer pooling improvements</li><li>using parallel GC rather than Java's default garbage collection</li></ul><div><br /></div><h1 style="text-align: left;">OfficeFloor Raw using R2DBC</h1><div>The officefloor-raw entry is different to the other OfficeFloor entries, as it's focus is purely on the HTTP server implementation. It does not include the OfficeFloor inversion of coupling control framework. It just provides a custom test implementation using OfficeFloor's HTTP server component. Hence, why it is classed as a platform rather than framework in the tests. This, however, allows seeing the performance overheads of OfficeFloor's inversion of coupling control framework.</div><div><br /></div><div>Given we are looking to see the overheads, we provided officefloor-raw implementations using R2DBC for the database tests. As officefloor-raw does not incur the inversion of control overheads, it is by nature going to be a lot faster than the rest of the OfficeFloor entries. However, the closer we can get the other entries to officefloor-raw, the more we reduce OfficeFloor's inversion of coupling control overheads.</div><div><br /></div><div>Though looking at the Java competitors above OfficeFloor, we will also consider supporting Vertx's <a href="https://github.com/eclipse-vertx/vertx-sql-client" target="_blank">PgClient</a> for Round 21.</div><div><br /></div><h1 style="text-align: left;">OfficeFloor Async</h1><div>As mentioned, the major change from round 19 to round 20 for OfficeFloor, is the support of asynchronous programming. The officefloor-async entry is using this functionality with R2DBC.</div><div><br /></div><div>Now OfficeFloor is a <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">multi-threaded framework</a>. The asynchronous functionality, therefore, has thread synchronising overheads that single threaded asynchronous frameworks do not suffer. Well the developer suffers in a more complex programming model. However, the performance of single threaded asynchronous frameworks is optimal due to little contention.</div><div><br /></div><div>Hence, the officefloor-async entry shines in the update test. The update test is heavily database dependent and requires reduction of contention between connections. Therefore, pipelining database queries over lower number of connections will decrease the number of parallel updates. This subsequently reduces the contention in the database and improves overall throughput.</div><div><br /></div><div>The officefloor-async entry out performs the other OfficeFloor framework entries in the update test because the database contention is significantly more important than the threading contention for throughput.</div><div><br /></div><h1 style="text-align: left;">Thread Affinity</h1><div>OfficeFloor supports <a href="https://officefloor.net/tutorials/ThreadAffinityHttpServer/" target="_blank">Thread Affinity</a> in it's inversion of coupling control framework to pin servicing of requests to a single CPU. This ensures optimal use of CPU caches, as moving threads between CPUs causes overheads in migrating data to the other CPU caches. By using thread affinity, the operating system's thread scheduler is informed to only schedule the thread to run on a particular CPU.</div><div><br /></div><div>For round 20, we have used thread affinity for the officefloor-raw entry to pin each socket listener thread to a particular CPU. This effectively allows running as 32 separate servers in Citrine, rather than one big congested server grabbing at the work. As contention is always overhead, using thread affinity to run isolated without contention (ok bus aside) has provided increased throughput.</div><div><br /></div><h1 style="text-align: left;">ByteBuffer Pooling</h1><div>The ByteBuffers to read and write from the socket have seen improvements in their pooling. Creating and destroying direct ByteBuffers is expensive, hence it is much better to pool them for improved performance. Furthermore, as direct ByteBuffers are separate memory to the heap, they allow OfficeFloor to effectively manage memory (rather than relying on the "dark magic" of garbage collection).</div><div><br /></div><div>OfficeFloor has two levels of pooling the ByteBuffers:</div><div><ul style="text-align: left;"><li>single core pool</li><li>thread local pool</li></ul><div><br /></div><div>The single core pool is the shared pool of ByteBuffers all threads can draw from. Previously, access to this pool was via synchronized methods. This has been enhanced to use ConcurrentLinkedDeque to reduce thread synchronising overheads. This has provided improved throughput to access the core pool.</div><div><br /></div><div>The thread local pools are an individual pool per thread. As the pool is specific for the thread, there is no thread contention in obtaining/returning ByteBuffers from/to the pool. This further improves performance of threads heavily involved in reading/writing to the sockets. However, can cause out of memory if many threads are involved in reading/writing from sockets (which can be the case particularly for writing responses by request servicing threads).</div></div><div><br /></div><div>Improvements have also been made in the thread local pooling to keep memory down and allow better distribution of ByteBuffers. This is achieved by only allowing the socket listener threads to pool ByteBuffers on their threads. As the majority of ByteBuffer interaction is undertaken by a constant set of socket listener threads, this means they can pool a significantly higher number of ByteBuffers for improved performance. It does mean servicing threads do need to use the core pool for the response ByteBuffers. However, as servicing threads spend time doing other work, there is less chance of contention in accessing the core pool. Therefore, with the improved core pool access, less contention for core pool and the socket listener threads now able have higher pool sizes, it overall provides greater throughput.</div><div><br /></div><h1 style="text-align: left;">Parallel GC</h1><div>While Java is optimising garbage collection for large heaps, focus of OfficeFloor is on reducing garbage. Creating lots of objects incurs more GC, which is overhead taking away from performance. Hence, in reducing object creation there is little need for large heaps. Therefore, while OfficeFloor has moved from Java 11 (round 19) to Java 15 (round 20), we have fallen back to Parallel GC for improved throughput due small heap size.</div><div><br /></div><div>Note we did not notice any significant difference in Java 15 avoiding biases locking by default. However, this was not extensively tested, as we had to do this locally (we did not have enough continuous runs before round 20 is being published to properly check this - so went with Java 15's claim indicating it should be negligible impact).</div><div><br /></div><div>Learning from this is that for Java 15 consider using the Parallel GC if your heap sizes don't grow large.</div><p></p><p><br /></p><h1 style="text-align: left;">Future Work For Round 21</h1><p>For round 21 we will be looking at flattening of the call stack within OfficeFloor. Work is already underway on <a href="https://github.com/officefloor/OfficeFloor/pull/812" target="_blank">this</a>. This will reduce the number of methods called to execute each function in the list. Ideally, bringing OfficeFloor entries closer to officefloor-raw.</p><p><br /></p>Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-34196242854759721842020-11-14T23:20:00.004-08:002020-11-14T23:23:41.222-08:00OfficeFloor: going beyond Dependency Injection<p><span style="background-color: white; color: #222635; font-family: Cambria, serif; font-size: 19px;">This was a submission to DZone's Computer Science Fare: <a href="https://dzone.com/articles/officefloor-going-beyond-dependency-injection">https://dzone.com/articles/officefloor-going-beyond-dependency-injection</a></span></p><p><span style="background-color: white; color: #222635; font-family: Cambria, serif; font-size: 19px;"><b> <br /></b></span>So why another Dependency Injection (DI) framework? Because Dependency Injection is only part of the <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of (Coupling) Control</a> problem. OfficeFloor provides the complete injection solution.
<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="720" src="https://www.youtube.com/embed/2BMkRDrvK58" width="100%"></iframe>
</p><p style="text-align: left;"><br /></p><h1 style="text-align: left;">Dependency Injection Problem<br /></h1><p style="text-align: left;">Dependency Injection on it's own can actually promote lower cohesion and higher coupling. Why, because Dependency Injection provides undisciplined short cuts to get references to objects. I need a repository to retrieve some data, I just inject it. I need some logic to work out some result, I just inject it. Overtime with on going improvements to systems, everything starts to reference everything else. Changing the interface of one thing becomes difficult, as so many things just pull it in (higher coupling). Furthermore, because it is so easy to "just inject" dependencies, convenience starts polluting single purpose logic of classes (lower cohesion).</p><p style="text-align: left;">Now, in disciplined development, we use principles such as SOLID to attempt to reduce this problem. However, we are continually fighting Lehman's laws of two general concerns:</p><p style="text-align: left;"></p><ol style="text-align: left;"><li>systems need to continually add new functionality to stay relevant</li><li>new functionality increases complexity reducing ability to change the system</li></ol><p></p><p style="text-align: left;">Too often deadlines, budgets, even just bad days, we just keep enhancing classes without paying much attention to the second problem. This all builds up and eventually we either:</p><p style="text-align: left;"></p><ul style="text-align: left;"><li>require an expensive rewrite of the system (typically not feasible by the business)</li><li>live with degraded ability to add new features (potentially becoming the death of the system as it can no longer stay competitive)</li></ul><p></p><p style="text-align: left;">Furthermore, Dependency Injection just looks at the <a href="https://sagenschneider.blogspot.com/2019/05/local-microservices-object-orientation.html" target="_blank">static structural concerns</a> of how objects reference each other. We have not added into the mix threading or how we can compose methods together (effectively gaining benefits of functional composition). We find this problem so systematic in DI only systems, that it has actually pulled the <a href="https://sagenschneider.blogspot.com/2019/08/what-is-oo-matrix.html" target="_blank">OO Matrix</a> veil over our eyes.</p><p style="text-align: left;"><br /></p><h1 style="text-align: left;">Going beyond Dependency Injection</h1><div>This is where <a href="http://officefloor.net" target="_blank">OfficeFloor</a> is taking things beyond Dependency Injection.</div><div><br /></div><div>OfficeFloor injects dependencies not only into objects but also as arguments into methods. This means we do not have to structurally link all objects together for the method to traverse these structures. The method just adds a new parameter for a new dependency. The result is we avoid high coupling because objects no longer require structural references to all other objects.<br /></div><div><br /></div><div>However, this only addresses the low coupling, as we also want higher cohesion. Well, OfficeFloor not only injects objects into methods, it also injects other methods into methods. This effectively provides function composition, a concept OfficeFloor has termed <a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">Continuation Injection</a> (or easier to remember Function Injection). The result is higher cohesion of methods. Methods can focus on single purposes and be composed together to achieve more complex functionality. </div><div><br /></div><div>Note that due to OfficeFloor's containerising of the execution of methods, OfficeFloor can also <a href="https://sagenschneider.blogspot.com/2020/01/compose-cats-reactor-zio-effects.html" target="_blank">containerise Monads</a> to be composed in with methods. This <a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">allows blending Object Orientation with Functional Programming</a> in the same application. We are still exploring this aspect, but the composibility provided by OfficeFloor keeps methods focused on single purposes resulting in significantly higher cohesion. </div><div><br /></div><div><h1 style="text-align: left;">Going even further</h1></div><div>Now we could have stopped there, as we are gaining significant benefits over Dependency Injection. However, this only lets you build more maintainable systems. We also want to build highly performant systems too.<br /></div><div><br /></div><div>Now multi-threading is hard. Frameworks usually opt for a single model of threading (thread-per-request / asynchronous single threaded). Attempting to blend threading models requires senior developer skill sets. Furthermore, these blended solutions can run into tricky problems as further incremental functionality is added by other less skilled developers.</div><div><br /></div><div>OfficeFloor, allows assigning execution of the individual methods to particular thread pools (what it terms <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">Thread Injection</a>). This allows blending various threading models (even thread affinity patterns) to achieve the right mix of performance and ease of development. OfficeFloor even allows for different execution profiles based on different hardware. This provides <a href="https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite" target="_blank">highly performant applications</a>.</div><div> </div><div><h1 style="text-align: left;">Elephant in the room </h1></div><div>Regardless of all these injection patterns, the real elephant in the room for applications is growing complexity. To really address the second general Lehman issue of complexity, we need to be able to see the problem. </div><div> </div><div>Lines of code one after another requires us to mentally visualise the complexity in the code. As we practice small incremental changes, complexity becomes hidden in the scroll blindness of the vast lines of code. Yes, we modularise and use principles. However, deadlines and budgets focus us on that small new feature and not the growing complexity elephant in your system.</div><div><br /></div><div>Furthermore, this level of complexity becomes hard to explain to non-technical individuals who generally hold the purse strings or set priorities. As code is already too complex, I find we start drawing diagrams to communicate the problem. We then use these diagrams to justify "refactoring" efforts to simplify the code, with promises that we will be able to add new features faster after this. What's even more "fun" is trying to provide estimates on the effort of the refactoring. When opening the Pandora's box of tackling the complexity, I find in DI only systems, the uncovered herd of complexity elephants just trample over those estimates.</div><div><br /></div><div>However, by the time you find the need to draw diagrams to start to communicate the complexity problem, it is all too late. Complexity has already become a problem. The slow creep of new functionality has added complexity to the point technical debt may become interest only payments. Basically, complexity is showing the signs the system is creaking to it's demise.</div><div><br /></div><div>This late discovery of complexity goes against modern software practices. We want early feedback on this complexity risk so that it can be addressed before it becomes a problem.</div><div><br /></div><div>OfficeFloor's configuration of <a href="https://sagenschneider.blogspot.com/2019/12/first-class-module-type-system-for.html" target="_blank">wiring the methods together is graphical</a>. This graphical configuration visually demonstrates the complexity of the application. The more spaghetti the diagram looks, the more need to spend effort simplifying the system. As this is visual from the start of the project and always up to date (as is the actual configuration of the system), complexity is easily seen. This means complexity can be addressed before it starts becoming a problem.</div><div><br /></div><div>So our motivation behind OfficeFloor is to provide the necessary improvements over Dependency Injection to ease the building of systems, ease the maintaining of systems, and avoiding the complexity increasing so that developers keep their hair when trying to wrangle in that new bit of functionality.</div><div><br /></div><h1 style="text-align: left;">Inversion of Coupling Control</h1><div>So you might ask, why aren't Dependency Injection frameworks adopting Function Injection / Thread Injection for a complete Inversion of Coupling Control solution?</div><div><br /></div><div>Because Function Injection and Thread Injection are <a href="https://sagenschneider.blogspot.com/2020/01/monad-with-iocc-provides-processthread.html" target="_blank">significantly harder to implement</a> than just injecting objects into each other.</div><div><br /></div><div>To achieve method injection, we needed to <a href="https://sagenschneider.blogspot.com/2019/06/local-microservices-first-class.html" target="_blank">containerise the execution of each method</a>. The container:</div><div><ol style="text-align: left;"><li> Ensures all dependencies are available for the method</li><li> Delegates the execution of the method to the appropriate thread pool</li><li> Handles all exceptions coming from the method</li></ol></div><div>Now, this is only the start of the problem. Once we containerised the method, we needed to type the method. To compose the methods together, we needed to know what dependencies on other methods and objects the method requires. The result is a <a href="https://sagenschneider.blogspot.com/2019/11/first-class-procedure-type-system-for.html">typing system for methods</a> that allows them to be visually represented in the graphical configuration. This then lets the wiring of the methods be graphically undertaken.</div><div><br /></div><div>The model driven design issues of using graphical configuration also needs to be avoided. This is achieved by the graphical configuration being modularised similar to class source files. They are:</div><div><ul style="text-align: left;"><li>modularised into separate files</li><li>each modular file is then typed, so can be included like typed methods in other modules </li><li>within each module there is a flat structure (this avoids hierarchies that cause source code merge issues - merge is just like flat lines of code)</li><li>the flat structure is sorted on save, so editing graphical configurations results in the same stored XML (avoiding duplications due to source code merging different line orderings) </li><li>contain no generated identifiers causing merge differences between developers</li></ul>Finally the backing XML to the graphical configuration is easily readable for those rare occasions of having to resolve merge conflicts.</div><div><br /></div><div>Performance requirements dictated that we could not keep swapping threads for each method executed. Hence, if the next method was to be executed by the same thread pool, the current thread would continue on to execute that method. This meant that thread context switches only occurred when required and not for every method execution. This allows OfficeFloor to act as both asynchronous single threaded (no context switch) and thread-per-request (when using thread pools for method execution). However, as threading can be tailored to specific methods, there are various custom threading models available to improve performance of your application (even including thread affinity).</div><div><br /></div><div>Building this flexibility in threading allows the containerised methods to be executed by any thread. Hence, memory synchronisation issues became important. To avoid significant locking and memory synchronising between threads, the internals of OfficeFloor is written mostly via immutable structures. This allows significantly reduced locking when executing the methods within the containers.</div><div><br /></div><div>Furthermore, as methods are not statically linked like objects, there is need for fast look up of dependencies. OfficeFloor provides a compiler that transforms the modular configuration into a graph to represent the entire application. This graph is checked for type correctness so that invalid application configurations is detected at compile time. Once deemed valid, the graph is compiled down into the execution engine that uses array index lookup of all dependencies for performance (avoiding hash map look ups by strings). </div><div><br /></div><h1 style="text-align: left;">Show me the working code</h1><div>The following provides working code demonstrations of OfficeFloor:</div><div><ul style="text-align: left;"><li>Subscription Application (<a href="https://github.com/officefloor/Subscription" target="_blank">source code</a> with application available at <a href="https://officefloor.appspot.com">https://officefloor.appspot.com</a>) <br /></li><li><a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">Weaving OO with Functional Programming</a> (<a href="https://github.com/officefloor/OoFunctionImperativeReactive" target="_blank">source code</a>)</li><li><a href="https://sagenschneider.blogspot.com/2020/01/compose-cats-reactor-zio-effects.html">Composing Monads</a> (<a href="https://github.com/officefloor/ComposeEffectsDemo" target="_blank">source code</a>)</li><li>Plus the <a href="http://officefloor.net/tutorials" target="_blank">tutorials</a><br /></li></ul><p> </p><h1 style="text-align: left;">Conclusion</h1><p>So next time you look to build an application, consider <a href="http://officefloor.net" target="_blank">OfficeFloor</a>. With the enhancements of Function Injection and Thread Injection over Dependency Injection, OfficeFloor encourages significantly lower coupling and higher cohesion in your applications. This avoids complexity from creeping up and can keep you adding new features long after a DI only system become frozen from complexity. See the <a href="http://officefloor.net/tutorials" target="_blank">tutorials</a> to get going with OfficeFloor.</p><p><br /></p></div>Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-25048306878393086542020-03-28T18:30:00.000-07:002020-03-28T18:30:09.804-07:00Migrating Spring Application to OfficeFloorThis series of articles looks at migrating Spring applications to OfficeFloor.<br />
<br />
<h2>
Why?</h2>
So the first question comes up. <br />
<br />
Why migrate Spring applications to <a href="http://officefloor.net/" target="_blank">OfficeFloor</a>? <br />
<br />
Spring provides dependency injection to create a graph of objects. Spring, however, provides little management over threading and attempts to model behaviour through object composition. This is where OfficeFloor in it's <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html">Inversion of Coupling Control</a> provides injection management of threading and functional behaviour.<br />
<br />
Now this is not to say Spring is inferior. Spring's focus has come from and stays with mainstream Object Orientation. OfficeFloor has merely taken these Object Orientation concepts and extended them with <a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">Functional Programming composition concepts</a> and <a href="https://sagenschneider.blogspot.com/2020/01/monad-with-iocc-provides-processthread.html" target="_blank">Process/Threading concepts</a>.<br />
<br />
Now if you are happy with mainstream Object Orientation then by all means stick with Spring. Spring is a great Object Oriented framework that deserves its success.<br />
<br />
However, if you want to avoid writing your own threading or would like more seamless support for functional programming, then please read on.<br />
<br />
<h2>
Let's not replace Spring</h2>
It would be unreasonable to port a Spring application in its entirety. Spring has been under active development since the turn of the millennium. Ok, at the time of writing this article that is just under two decades. For some industries that could be considered a short time. However, in the IT industry, where there are new JavaScript frameworks popping up every day, this longevity is testament to Spring's success.<br />
<br />
For me, Spring's success has been because it got something fundamentally right. Now we could argue academically about Object Oriented composition vs Functional Programming composition. We could argue about libraries vs frameworks. We could even argue about Java vs new languages like Kotlin. But what I see in these arguments is focus on finding simpler and easier ways to write software. And for me, Spring (and more specifically Spring Boot) did that by getting rid of the repetitive plumbing code. This is so we could get on with writing the important functionality of our applications.<br />
<br />
To enable focus on removing repetitive plumbing code there are a few things required:<br />
<ol>
<li>Extensible framework</li>
<li>Plugins written for supporting the various infrastructure / existing solutions</li>
<li>Open platform for community addition / management of plugins</li>
</ol>
Spring by wiring objects together enables this extensibility. New functionality can be included by wiring in the objects to support that functionality <br />
<br />
Plugins then extend the framework to cover including various infrastructure and existing solutions. The plugins avoid us re-inventing the wheel so our focus can be on achieving the functionality of our application.<br />
<br />
The final aspect is supporting the IT ecosystem. There are so many competing technologies and even platforms with the various cloud providers. A single group or company attempting to support this would be overwhelmed. Therefore, Spring has developed a strong open source community to write and maintain all the plugins. Even <a href="https://www.vmware.com/company/news/releases/2009/springsource.html" target="_blank">VMWare's acquisition of Spring</a> mentions this open source community.<br />
<br />
Therefore, it is unreasonable to rewrite Spring into something new. There is too much of an ecosystem to replicate.<br />
<br />
<h2>
Integrating Spring</h2>
So rewriting everything Spring into OfficeFloor is not a feasible direction.<br />
<br />
Rewriting is also a violation of the first point - an extensible framework.<br />
<br />
OfficeFloor must subsequently be extensible to plugin Spring. OfficeFloor supports extension via Object Orientation, Functional Programming and Threading. Therefore, if OfficeFloor is not extensible via Object Oriented Spring, then OfficeFloor fails at being extensible.<br />
<br />
OfficeFloor supports plugging in Spring via a <span style="font-family: "Courier New", Courier, monospace;">SupplierSource</span>. This extension point of OfficeFloor allows for third party dependency injection frameworks to make their dependencies available for injection in OfficeFloor applications.<br />
<br />
Now OfficeFloor's website provides <a href="http://officefloor.net/tutorials" target="_blank">detailed tutorials</a> on various aspects. OfficeFloor likes to adhere to the DRY (don't repeat yourself) principle, so this article series will direct you to the relevant tutorials for detailed aspects of Spring to OfficeFloor migration. Therefore, please see the <a href="http://officefloor.net/tutorials/SpringHttpServer/" target="_blank">Spring tutorial</a> for how to plugin Spring dependencies into OfficeFloor.<br />
<br />
The result of plugging Spring into OfficeFloor is that OfficeFloor gets a library of pre-written objects. Spring focuses on wiring together a graph of objects. OfficeFloor does not interfere with this, as Spring does this exceptionally well. What OfficeFloor does is allow reference to the various objects in the Spring graph for injection into its own application. This effectively allows OfficeFloor to be extended with Spring managed objects.<br />
<br />
<h2>
Going beyond Objects</h2>
The rest of this article serious will look at how to migrate our Object Oriented Spring applications into OfficeFloor to start using OfficeFloor's Functional Programming and Threading extensions. While objects link data with functionality (methods), objects still provide little in terms of threading. This article series will show how to further simplify our Spring applications with these Functional Programming and Threading extensions/plugins by migrating to OfficeFloor.Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-59257670373201418562020-02-11T01:02:00.002-08:002020-02-11T01:02:52.523-08:00DDD Perth 2019 PresentationThe <a href="https://dddperth.com/agenda/2019" target="_blank">DDD Perth 2019</a> presentation of <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a> has been published. Enjoy!<br />
<br />
<br />
<style>
.video-wrapper {position: relative; padding-bottom: 56.25%; padding-top: 25px;}
.video-wrapper iframe {position: absolute; top: 0; left: 0; width: 100%; height: 100%;}
</style>
<div class="video-wrapper">
<iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" height="720" src="https://www.youtube.com/embed/2BMkRDrvK58" width="1280"></iframe>
</div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-14011944853547316842020-01-25T18:21:00.000-08:002020-01-25T18:21:07.324-08:00Monad with IoCC provides Process/Thread modelThis is the final article in the series on looking at Inversion of Coupling Control (IoCC) composition. The previous articles covered:<br />
<br />
<ul>
<li><a href="https://sagenschneider.blogspot.com/2019/11/first-class-procedure-type-system-for.html" target="_blank">First-Class Procedure type system</a></li>
<li><a href="https://sagenschneider.blogspot.com/2019/12/first-class-module-type-system-for.html" target="_blank">First-Class Module</a></li>
<li><a href="https://sagenschneider.blogspot.com/2020/01/compose-cats-reactor-zio-effects.html" target="_blank">Code examples</a></li>
</ul>
<br />
This article looks at providing a mathematical model to explain the composition.<br />
<br />
Just a little disclaimer that I'm not a mathematics boffin. I've a degree in computer science but it did not cover much functional programming. Much of this is through my self taught understanding of functional programming and mathematics. Therefore, I'm happy to take feedback from more capable mathematicians on better ways to express the model. However, I'm hoping this article reasonably conveys the underlying model for composition with Inversion of Coupling Control.<br />
<br />
From Category Theory, we have the associative law:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> f(x) . g(x) = f.g(x)</span><br />
<br />
With this we can introduce dependencies:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;"> f(x)(d1) . g(x)(d2) = f.g(x)(d1, d2)</span><br />
<br />
where:<br />
d is a set of dependencies<br />
<br />
This makes the program very rigid, as changing d1 to d3 has significant impact for use of f(x)(d1 now d3). For example, switching from database connection to REST end point.<br />
<br />
<a href="https://zio.dev/" target="_blank">ZIO</a> attempts to reduce the rigidity by the following:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace;">f(x)(d1) . g(x)(d2) = f.g(x)(D)</span><br />
<br />
where:<br />
D = d1 + d2<br />
Or, in other words:<br />
D extends d1 with d2<br />
<div>
<br /></div>
<div>
Now, we can create lots of morphisms and at execution of resulting ZIO, provide a hom(D), which is the set of all required dependencies.</div>
<div>
<br /></div>
<div>
So, this model works. It is certainly enabling injection of dependencies in functional programs.</div>
<div>
<br /></div>
<div>
Now, I'd like to take another tact to the problem.</div>
<div>
<br /></div>
<div>
The <a href="https://www.microsoft.com/en-us/research/wp-content/uploads/1993/01/imperative.pdf" target="_blank">Imperative Functional Programming</a> paper could not see how to remove the continuation type (z) from the signature. The authors did conclude Monads and CPS very similar, but due to the extra continuation type on the signature and the author's intuition, the IO Monad was the direction forward.</div>
<div>
<br /></div>
<div>
Now I certainly am not taking the tact to replace IO Monad with CPS. I'm looking to create a complementary model. A model where continuations decouple the IO Monads.</div>
<div>
<br /></div>
<div>
So introducing dependencies to the IO Monad, we get:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> IO[x](d)</span></div>
<div>
<br /></div>
<div>
<div>
where:</div>
<div>
d is the set of dependencies required</div>
</div>
<div>
<br /></div>
<div>
This then follows, that joining two IO together we get:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> IO[x](d1, d2)</span></div>
<div>
<br /></div>
<div>
So, maybe let's keep the IO Monad's separate and join them via CPS. This changes the signature to:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> IO[x](d)(z)</span></div>
<div>
<br /></div>
<div>
<div>
where:</div>
<div>
z = Either[Throwable,x] -> ()</div>
</div>
<div>
<br /></div>
<div>
The pesky z that the Imperative Functional Programming paper was talking about.</div>
<div>
<br /></div>
<div>
However, discussed previously is <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Continuation Injection</a>. This effectively hides the z from the signature, making it an injected function. As it's an injected function, the z becomes an indirection to another function. This indirection can be represented as:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> IO[_](d1) -> (Either[Throwable,y] -> IO[y](d2)) -> IO[y](d2)</span></div>
<div>
<br /></div>
<div>
Note: the joined IO need only handle y or any of it's super types. Hence, the relationship indicates the passed type. This makes it easy to inject in another IO for handling the continuation.</div>
<div>
<br /></div>
<div>
Now to start isolating the IO Monads from each other, we are going to start with <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">Thread Injection</a>.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> d -> Executor</span></div>
<div>
<br /></div>
<div>
This represents Thread Injection choosing the appropriate Executor from the dependencies. Therefore, we can then introduce a Thread Injection Monad to choose the Executor.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> F[_](d)(Executor) -> (d -> Executor) -> TI[F[_](d)] </span></div>
<div>
<br /></div>
<div>
<div>
where</div>
<div>
TI is the Thread Injection Monad that contains the dependency to Executor mapping to enable executing the IO Monad with the appropriate Executor.</div>
</div>
<div>
<br /></div>
<div>
This then has the above continuation between IO Monads relationship become.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[IO[_](d1)] -> (Either[Throwable,y] -> IO[y](d2)(Executor)) -> TI[IO[y](d2)]</span></div>
<div>
<br /></div>
<div>
Now the IO Monads can be executed by the appropriate Executor via the TI Monad.</div>
<div>
<br /></div>
<div>
Further to this, we can model dependency injection with:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> F[_](d) -> (F[_](d) -> F[_]) -> DI[F[_]]</span></div>
<div>
<br /></div>
<div>
<div>
where</div>
<div>
DI is the Dependency Injection Monad that supplies dependencies to the function.</div>
</div>
<div>
<br /></div>
<div>
Note that DI Monad will also manage the life-cycle of the dependencies. Discussion of how this is managed will be a topic for another article.</div>
<div>
<br /></div>
<div>
So the above IO Monad continuation relationship becomes:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[IO[_]]] -> (Either[Throwable,y] -> IO[y](d)(Executor)) -> TI[DI[IO[y]]]</span></div>
<div>
<br /></div>
<div>
<div>
where:</div>
<div>
DI propagates the same instances of dependencies across the continuation</div>
</div>
<div>
<br /></div>
<div>
Now, with Continuation Injection we are not limited to injecting in only one continuation. We can inject in many:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[IO[_]]] -> (Either[Throwable,y] -> IO[y](d)(Executor)) -> TI[DI[IO[y]]]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> -> (Either[Throwable,w] -> IO[w](d)(Executor)) -> TI[DI[IO[w]]]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span></div>
</div>
<div>
<br /></div>
<div>
Note: I'm guessing this can be represented on a single line (possible as set of continuations from a particular IO) but I'll leave that to a boffin more mathematical than me.</div>
<div>
<br /></div>
<div>
This means we can remove the Either and have the (possibly many) exceptions handled by separate continuations to get:</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[IO[_]]] -> (y -> IO[y](d)(Executor)) -> TI[DI[IO[y]]]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> -> (ex -> IO[ex](d)(Executor)) -> TI[DI[IO[ex]]]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> ...</span></div>
</div>
<div>
<br /></div>
<div>
This demonstrates that an IO may now actually have more than one output. By having the ability to inject multiple continuations, the IO is capable of multiple outputs.</div>
<div>
<br /></div>
<div>
It is also execution safe. <a href="http://officefloor.net/" target="_blank">OfficeFloor</a> (Inversion of Coupling Control) ensures the handling of one continuation completes before the next continuation begins executing. This ensures only one IO is ever being executed at one time.</div>
<div>
<br /></div>
<div>
Further to this we can qualify DI. Originally we had d1, d2 that was hidden by DI. We can qualify the scope of DI as follows:</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> DI[P,T,_]</span></div>
<div>
<br /></div>
<div>
<div>
where:</div>
<div>
P is the set of process dependency instances</div>
<div>
T is the set of thread dependency instances</div>
</div>
<div>
<br /></div>
<div>
This allows for the following.</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Same thread = DI[P,T,_] -> (_ -> _) -> DI[P,T,_]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Spawned thread = DI[P,T,_] -> (_ -> _) -> DI[P,S,_]</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> New process = DI[P,T,_] -> (_ -> _) -> DI[Q,S,_]</span></div>
</div>
<div>
<br /></div>
<div>
In other words,</div>
<div>
<div>
<ul>
<li>spawning a thread is creating a new set of thread dependencies instances</li>
<li>interprocess communication is a different set of process dependency instances</li>
</ul>
</div>
</div>
<div>
Further to this:</div>
<div>
<div>
<ul>
<li>the set of T may only be the same if the set of P is same</li>
<li>context (eg transactions) apply only to dependencies in T</li>
</ul>
</div>
</div>
<div>
The resulting IO Monad relationship for a same thread continuation becomes.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[P,T,IO[_]]] -> (y -> IO[y](d)(Executor)) -> TI[DI[P,T,IO[y]]]</span></div>
<div>
<br /></div>
<div>
while a spawned thread continuation relationship is modelled as follows.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[P,T,IO[_]]] -> (y -> IO[y](d)(Executor)) -> TI[DI[P,S,IO[y]]]</span></div>
<div>
<br /></div>
<div>
What this essentially allows is multi-threading concurrency. Any continuation may spawn a new thread by starting a new set of thread dependencies. Furthermore, OfficeFloor will asynchronously process the continuation returning control immediately. This has the effect of spawning a thread.</div>
<div>
<br /></div>
<div>
The same goes for spawning a new process.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[P,T,IO[_]]] -> (y -> IO[y](d)(Executor)) -> TI[DI[Q,S,IO[y]]]</span></div>
<div>
<br /></div>
<div>
Therefore, with OfficeFloor, processes and threading are a configuration not a programming problem. Developers are no longer required to code thread safety into their possible imperative code within the IO. As the seldom used process dependencies are coded thread safe, this relationship introduces the ability for mutability within the IO that is thread safe. The isolation of dependencies prevents memory corruption (assuming dependencies respect not sharing static state).</div>
<div>
<br /></div>
<div>
OfficeFloor (Inversion of Coupling Control) is in this sense possibly the dark side. Functional programming strives for purity of functions being the light. Given OfficeFloor can handle:</div>
<div>
<div>
<ul>
<li>multiple outputs from IOs including exceptions as continuations</li>
<li>mutability within the IOs that is thread safe</li>
</ul>
</div>
</div>
<div>
OfficeFloor enables modeling the darker impurities (or maybe I just watch too much StarWars).</div>
<div>
<br /></div>
<div>
What we now have is a possible "inversion" of the function:</div>
<div>
<div>
<ul>
<li>Function: strives to be pure, may have multiple inputs and only a single output. </li>
<li>IoCC: allows impurities, has a single input and may have multiple outputs.</li>
</ul>
<div>
I personally like to think of functions like parts of a machine. They are highly coupled engine cogs providing always predictable output.</div>
</div>
</div>
<div>
<br /></div>
<div>
I then like to think of IoCC like signals. This is a more organic structure of loosely coupled events triggering other loosely coupled events. The result is a mostly predictable output. This is more similar to human decisioning outputs.</div>
<div>
<br /></div>
<div>
Regardless, we now have a typed model that can be represented as a directed graph of interactions. The IO Monads are the nodes with the various continuations edges between them. An edge in the graph is qualified as follows.</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> TI[DI[IO]] == y,p,t ==> TI[DI[IO]]</span></div>
<div>
<br /></div>
<div>
<div>
where:</div>
<div>
y indicates the data type provided to the continuation</div>
<div>
p indicates if a new process is spawned (represented as 0 for no and 1 for yes)</div>
<div>
t indicates if a new thread is spawned (again represented as 0 for no and 1 for yes)</div>
</div>
<div>
<br /></div>
<div>
The result is the following example graph.</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYKsWoP61u6-7VY1pL6Lc1D2-l-xbqszU9MZbfQpJyJXffDr1SZ2saJN0CMZb6FZsTjVv0H23F2R16D6al0AagfYEsHURSDr664U92tAJ_bY-fiQ2mCOXLy-_bRKF_pXT-JB8XctnujA/s1600/DirectedGraph.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="398" data-original-width="559" height="227" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiYKsWoP61u6-7VY1pL6Lc1D2-l-xbqszU9MZbfQpJyJXffDr1SZ2saJN0CMZb6FZsTjVv0H23F2R16D6al0AagfYEsHURSDr664U92tAJ_bY-fiQ2mCOXLy-_bRKF_pXT-JB8XctnujA/s320/DirectedGraph.png" width="320" /></a></div>
<div>
which, is essentially the OfficeFloor Continuation Injection configuration.</div>
<div>
<br /></div>
<h2>
Summary</h2>
<div>
All of the above is already implemented in <a href="http://officefloor.net/" target="_blank">OfficeFloor</a>.</div>
<div>
<br /></div>
<div>
The previous articles demonstrated the <a href="https://sagenschneider.blogspot.com/2019/11/first-class-procedure-type-system-for.html" target="_blank">type system of Inversion of Coupling Control</a> to enable composition. The type system also enabled <a href="https://sagenschneider.blogspot.com/2019/12/first-class-module-type-system-for.html" target="_blank">encapsulation in First-Class Modules</a> for easy assembly and comprehension of OfficeFloor applications. This was then demonstrated with a <a href="https://sagenschneider.blogspot.com/2020/01/compose-cats-reactor-zio-effects.html" target="_blank">simple example application</a>.</div>
<div>
<br /></div>
<div>
What this article has attempted to cover is the core underlying model. It has looked at how injected continuations can be used to join together IO instances. Further, it looked at the dependencies and how they can be used to model processes and threads.</div>
<div>
<br /></div>
<h2>
Future Work</h2>
<div>
At the moment, we're focused on making building non-distributed applications a pleasure with OfficeFloor. This runs on the premise that if you are not enjoying building smaller applications with a toolset, why would you want to build larger more complex applications with that toolset.</div>
<div>
<br /></div>
<div>
However, we are nearing the completion of the bulk of this work.</div>
<div>
<br /></div>
<div>
We will be looking to simplify building distributed applications soon.</div>
<div>
<br /></div>
<div>
This will be achieved by looking at algorithms to examine the directed graph of continuations to decide on best places to separate the IOs into different containers. What the algorithms will take into account are the above relationships. In particular:</div>
<div>
<div>
<ul>
<li>the directed graph of continuations</li>
<li>isolating sub graphs by the process (and possibly thread) dependency rules</li>
<li>identifying which sub graphs to isolate to another container by incorporating run time metrics of the IOs</li>
</ul>
<div>
Note that we can model interprocess communication as:</div>
</div>
</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Async (e.g. queue) = DI[P,T,_] -> (message -> _) -> DI[Q,S,_] -> ()</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> Sync (e.g. REST) = D[P,T,_] -> (request -> _) -> D[Q,S,_] -> (response -> _) -> D[P,T,_]</span></div>
</div>
<div>
<br /></div>
<div>
This can provide type safe modeling of distributing the IOs within the directed continuation graph.</div>
<div>
<br /></div>
<div>
Note that we may have to mark dependency instances that carry non-replicatable state between IO Monads. In other words, a database connection (not in transactional context) can be replicated by obtaining another database connection from the pool. However, a dependency that stores some value in it from one IO Monad that is used by the next IO Monad is non-replicable.</div>
<div>
<br /></div>
<div>
In practice, this has only been variable dependencies to further remove the parameter coupling between IO Monads (see <a href="http://officefloor.net/tutorials/" target="_blank">OfficeFloor tutorials</a>).</div>
<div>
<br /></div>
<div>
However, we are also finding in practice that it is relatively intuitive to find sub graphs to isolate to their own containers. Endeavours in this work will likely look at automation of dynamically isolating sub graphs to containers as load changes (effectively having selective elastic scale of functions not arbitrarily bounded microservices).</div>
<div>
<br /></div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-3672526462510750242020-01-14T11:30:00.001-08:002020-01-25T18:57:21.229-08:00compose Cats, Reactor, ZIO, ... EffectsThis is the third in a series of articles looking at the type system for Inversion of Coupling Control to provide composition.<br />
<br />
The previous articles covered:<br />
<ul>
<li><a href="https://sagenschneider.blogspot.com/2019/11/first-class-procedure-type-system-for.html" target="_blank">First-Class Procedure type system</a></li>
<li><a href="https://sagenschneider.blogspot.com/2019/12/first-class-module-type-system-for.html" target="_blank">First-Class Module</a></li>
</ul>
This article will look at taking the theory into practice. It will use the concepts to build an application composing Effects from various Effect libraries.<br />
<br />
Note that the Effects used is kept deliberately simple to focus on the composition of the effects. This is mainly because this article is not to compare libraries. This article is to compose them. We show how using Inversion of Coupling Control they can be seamlessly composed together in a simple application. Also, order of discussing the libraries is nothing more than alphabetical.<br />
<br />
To keep matters simple the effect will be retrieving a message from the database.<br />
<br />
<h2>
Cats</h2>
Let's begin with <a href="https://typelevel.org/cats-effect/" target="_blank">Cats Effect</a>.<br />
<br />
<pre><code class="language-scala"> def cats(request: ServerRequest)(implicit repository: MessageRepository): IO[ServerResponse] =
for {
message <- catsGetMessage(request.getId)
response = new ServerResponse(s"${message.getContent} via Cats")
} yield response
def catsGetMessage(id: Int)(implicit repository: MessageRepository): IO[Message] =
IO.apply(repository findById id orElseThrow)
</code></pre>
<br />
The <span style="font-family: "courier new" , "courier" , monospace;">catsGetMessage</span> function wraps the repository retrieving message effect within an <span style="font-family: "courier new" , "courier" , monospace;">IO</span>. This can then be used to service the request to provide a response (as per the <span style="font-family: "courier new" , "courier" , monospace;">cats</span> function).<br />
<br />
The use of implicit may be overkill for the single <span style="font-family: "courier new" , "courier" , monospace;">repository</span> dependency. However, it shows how dependency injection can remove dependency clutter from the servicing logic. This is especially useful when the number of dependencies grows.<br />
<br />
<h2>
Reactor</h2>
<a href="https://projectreactor.io/" target="_blank">Reactor</a> has the following servicing logic.
<br />
<pre><code class="language-scala"> def reactor(request: ServerRequest)(implicit repository: MessageRepository): Mono[ServerResponse] =
reactorGetMessage(request.getId).map(message => new ServerResponse(s"${message.getContent} via Reactor"))
def reactorGetMessage(id: Int)(implicit repository: MessageRepository): Mono[Message] =
Mono.fromCallable(() => repository.findById(id).orElseThrow())
</code></pre>
<br />
Again, there is a <span style="font-family: "courier new" , "courier" , monospace;">reactorGetMessage</span> function wrapping the retrieving message effect into a <span style="font-family: "courier new" , "courier" , monospace;">Mono</span>. This is then used to service the request.
<br />
<br />
<h2>
ZIO</h2>
For <a href="https://zio.dev/" target="_blank">ZIO</a> the logic is slightly different, as ZIO provides it's own dependency injection.<br />
<br />
<pre><code class="language-scala"> def zio(request: ServerRequest, repository: MessageRepository): ZIO[Any, Throwable, ServerResponse] = {
// Service logic
val response = for {
message <- zioGetMessage(request.getId)
response = new ServerResponse(s"${message.getContent} via ZIO")
} yield response
// Provide dependencies
response.provide(new InjectMessageRepository {
override val messageRepository = repository
})
}
def zioGetMessage(id: Int): ZIO[InjectMessageRepository, Throwable, Message] =
ZIO.accessM(env => ZIO.effect(env.messageRepository.findById(id).orElseThrow()))
trait InjectMessageRepository {
val messageRepository: MessageRepository
}
</code></pre>
<br />
The <span style="font-family: "courier new" , "courier" , monospace;">zioGetMessage</span> again wraps the retrieve database message effect within a <span style="font-family: "courier new" , "courier" , monospace;">ZIO</span>. However, it extracts the injected trait to retrieve the repository.
<br />
<br />
<h2>
Encapsulating into a Module</h2>
The above functions (<span style="font-family: "courier new" , "courier" , monospace;">cats</span>, <span style="font-family: "courier new" , "courier" , monospace;">reactor</span>, <span style="font-family: "courier new" , "courier" , monospace;">zio</span>) are configured as First-Class Procedures into the following Module.
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipJH3CyW-xzvqMSkFoP93yRUrJIi7nOeVz1ZKw5VdK7nBjFp1rson8Snz-30HmVJ3OaLb6sfyi51blw6JJtBXUDUf8fWpfuVg5alq7J89-kX5U9Eur1XEmdEKpuMedUkVrzMet565jig/s1600/SynchronousModule.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="407" data-original-width="635" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEipJH3CyW-xzvqMSkFoP93yRUrJIi7nOeVz1ZKw5VdK7nBjFp1rson8Snz-30HmVJ3OaLb6sfyi51blw6JJtBXUDUf8fWpfuVg5alq7J89-kX5U9Eur1XEmdEKpuMedUkVrzMet565jig/s320/SynchronousModule.png" width="320" /></a></div>
This module has an output being the <span style="font-family: "courier new" , "courier" , monospace;">Response</span> with inputs <span style="font-family: "courier new" , "courier" , monospace;">Cats</span>, <span style="font-family: "courier new" , "courier" , monospace;">Reactor</span>, <span style="font-family: "courier new" , "courier" , monospace;">ZIO</span> and <span style="font-family: "courier new" , "courier" , monospace;">Imperative</span>.
<br />
<br />
As First-Class Procedures are lazily evaluated they can also wrap imperative code containing effects. The <span style="font-family: "courier new" , "courier" , monospace;">imperative</span> function is the following.
<br />
<br />
<pre><code class="language-scala"> def imperative(request: ServerRequest, repository: MessageRepository): ServerResponse = {
val message = repository.findById(request.getId).orElseThrow()
new ServerResponse(s"${message.getContent} via Imperative")
}
</code></pre>
<br />
<h2>
Using the Module</h2>
The following configuration uses the module to service REST requests. It is configured as the <span style="font-family: "courier new" , "courier" , monospace;">Synchronous</span> module.
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo4KO0B75pHVpRNnvlYqC_N5Np5jLfmKJ1FZ_hGh65pcpxoMQm75X_t7sIJM4zhbZjO5bhPXUJghVX9S2ku1Wr-nko00OvnoPi-CvzgtpX3S-z9bxu_DIEjv78_OdEcG10DHEpuxZBYA/s1600/Server.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="591" data-original-width="858" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgo4KO0B75pHVpRNnvlYqC_N5Np5jLfmKJ1FZ_hGh65pcpxoMQm75X_t7sIJM4zhbZjO5bhPXUJghVX9S2ku1Wr-nko00OvnoPi-CvzgtpX3S-z9bxu_DIEjv78_OdEcG10DHEpuxZBYA/s320/Server.png" width="320" /></a></div>
This demonstrates how easy it is to configure the module into servicing requests.<br />
<br />
What is further interesting is the <span style="font-family: "courier new" , "courier" , monospace;">Asynchronous</span> module has the same interface of inputs/outputs as the <span style="font-family: "courier new" , "courier" , monospace;">Synchronous</span> module. Now, this could quite possibly be the above module re-used (just badly named). However, it is not. The <span style="font-family: "courier new" , "courier" , monospace;">Asynchronous</span> module undertakes the same logic, but just asynchronously (<a href="https://github.com/officefloor/ComposeEffectsDemo/blob/master/src/main/scala/net/officefloor/demo/AsynchronousLogic.scala" target="_blank">code available in demo project</a>).<br />
<br />
What is important for modules is the contractual interface of inputs and outputs. We could quite happily swap the <span style="font-family: "courier new" , "courier" , monospace;">Synchronous</span> / <span style="font-family: "courier new" , "courier" , monospace;">Asynchronous</span> modules around in the configuration and the application will still continue to work. This allows the complexity to be encapsulated.<br />
<br />
A more real world example is we could start out with the quicker to write and easier to debug synchronous effects. Then as the application grows in scale, we may decide to swap in an asynchronous module to better handle scale. The amount of refactoring to swap the <span style="font-family: "courier new" , "courier" , monospace;">Synchronous</span> module to the <span style="font-family: "courier new" , "courier" , monospace;">Asynchronous</span> module would be:<br />
<ol>
<li>Drop in new <span style="font-family: "courier new" , "courier" , monospace;">Asynchronous</span> module</li>
<li>Re-wire flows to the <span style="font-family: "courier new" , "courier" , monospace;">Asynchronous</span> module</li>
<li>Delete the <span style="font-family: "courier new" , "courier" , monospace;">Synchronous</span> module</li>
</ol>
As <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a> removes the function coupling, there is no code to change except providing the implementation of the new module.<br />
<br />
With modules able to contain modules, this provides a means to encapsulate complexity of the application for easier comprehension. It also makes importing modules simple. Drop them in and wire them up. And is especially useful when libraries of third party modules are available for composition of ready to use functionality.<br />
<br />
<h2>
Composing Effects</h2>
This demonstrates First-Class Procedures and First-Class Modules of the previous articles in this series.
<br />
<br />
Hey, but this article promised composing effects!
<br />
<br />
Well I could tell you the send is an effect and that composing this after the above effects is that composition. However, that's taking a lot of my word for it.
<br />
<br />
Therefore, the last module in the server configuration is the following.
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKxct8sVyQ9MKbKRFjEcWPoZxyqxB9h_mfxPkmExqfmx0Wm2tcOdAPm-TqVpX4bUqj2UhsvWtcUaewP4OCQxzI4OOrbbUK8K-bQOoF4xPxeJw2ZXBmb7ybpglxgpiYmkjnEV1-gQ3Bbg/s1600/ComposeModule.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="161" data-original-width="1100" height="46" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKxct8sVyQ9MKbKRFjEcWPoZxyqxB9h_mfxPkmExqfmx0Wm2tcOdAPm-TqVpX4bUqj2UhsvWtcUaewP4OCQxzI4OOrbbUK8K-bQOoF4xPxeJw2ZXBmb7ybpglxgpiYmkjnEV1-gQ3Bbg/s320/ComposeModule.png" width="320" /></a></div>
This module composes an effect from each of the libraries. The code for each effect is the following.
<br />
<pre><code class="language-scala"> def seed: String = "Hi"
def cats(@Parameter param: String): IO[String] = IO.pure(s"$param, via Cats")
def reactor(@Parameter param: String): Mono[String] = Mono.just(s"$param, via Reactor")
def zio(@Parameter param: String): ZIO[Any, Nothing, String] = ZIO.succeed(s"$param, via ZIO")
def imperative(@Parameter param: String): String = s"$param, via Imperative"
def response(@Parameter message: String): ServerResponse = new ServerResponse(message)
</code></pre>
<br />
Each effect just takes the input of the previous and appends it's library name. The resulting response is a string containing all the effect library names.
<br />
<br />
<h2>
No adapters</h2>
<div>
Astute readers may be thinking that under the hood of <a href="http://officefloor.net/" target="_blank">OfficeFloor</a> there may be some fabulous adapters between the libraries. Hmmm, can we extract these and make use of them?</div>
<div>
<br /></div>
<div>
Sadly and for that matter quite happily there are no adapters between the libraries. What actually happens is that each First-Class Procedure unsafely executes its effect and retrieves the resulting output. With the output OfficeFloor then invokes the next First-Class Procedure. By doing so, we do not need to adapt the libraries with each other. We can run each effect in isolation and interface them via their typed inputs/outputs.</div>
<div>
<br /></div>
<div>
This makes integration of new effect libraries very simple. Just write a once off adapter to encapsulate the library's effects within a First-Class Procedure. The effect library is then able to integrate with all the other effect libraries. As First-Class Procedures are actually a specialised First-Class Module, this demonstrates the composition capabilities of Inversion of Coupling Control.</div>
<div>
<br /></div>
<h2>
Summary</h2>
<div>
This article has been code and configuration heavy to demonstrate how First-Class Procedures and First-Class Modules compose.</div>
<div>
<br /></div>
<div>
It has demonstrated that the type system of Inversion of Coupling Control makes composition easy (essentially drawing lines).</div>
<div>
<br /></div>
<div>
Now you need not take my word on the code examples in this article. They are extracted from the demonstration project you can clone and run yourself (found at <a href="https://github.com/officefloor/ComposeEffectsDemo">https://github.com/officefloor/ComposeEffectsDemo</a>).</div>
<div>
<br /></div>
<div>
Also, if we've missed your favourite effects library please excuse me. We're happy, if enough interest, to work with you incorporate adapters to provide further demonstration of integrating the beloved effect library. Focus of OfficeFloor is not to be opinionated but rather provide an open platform to integrate software.</div>
<div>
<br /></div>
<div>
The <a href="https://sagenschneider.blogspot.com/2020/01/monad-with-iocc-provides-processthread.html" target="_blank">next article</a> in the series tests my self taught mathematics to attempt to explain the underlying model of why this ease of composition is possible.</div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-29898310715147692212019-12-25T18:27:00.000-08:002020-01-25T18:44:47.853-08:00First-Class ModuleThis is the second in a series looking at the Inversion of Coupling Control type system for composition. This article discusses a more general Module type system than the previous article's First-Class Procedure Type.<br />
<br />
Note: some functional programming languages also attempt to define First-Class Modules. The First-Class Modules defined in this article are created from <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">inverted functions</a>.<br />
<br />
<h2>
First-Class Procedure</h2>
To recap the <a href="https://sagenschneider.blogspot.com/2019/11/first-class-procedure-type-system-for.html" target="_blank">last article</a>, the First-Class Procedure's type is defined as follows. Note that we exclude the dependency type, as dependencies are auto-wired.<br />
<br />
<pre><code class="language-java">FirstClassProcedureType {
Class<?> parameterType;
ContinuationType[] continuations;
}
ContinuationType {
String name;
Class<?> argumentType;
}
</code></pre>
<br />
This defines the First-Class Procedure to have a single input parameter and multiple continuations out for further composition of logic and handling of exceptions.<br />
<br />
<h2>
Module</h2>
Having a single input with multiple outputs is fine for methods, functions, etc wrapped in First-Class Procedures. However, when systems grow we don't want the complexity to make the inputs/outputs suffer similar increased complexity. We want the inputs/outputs to provide an interface to encapsulate the complexity of the Module. Note that without encapsulation, we don't get the ability to modularise the complexity of the application.<br />
<br />
To enable an interface to the Module, let's create the following input / output types:<br />
<br />
<pre><code class="language-java">InputType {
String name;
Class<?> parameterType;
}
OutputType {
String name;
Class<?> argumentType;
}
</code></pre>
<br />
To understand why these types are created, we are going to use the visual configuration of <a href="http://officefloor.net/" target="_blank">Inversion of Coupling Control</a> to better aid understanding what is happening.<br />
<br />
The following Module configuration represents a single input, handled by a First-Class Procedure that sends its result to an output:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfdN5qmchZulUNVbUcuQWXZkt52F-IpeIfz-EsAoU19GY2af0fvpeyQgN6utYY0O5swGPGy7cFrxtJpLjpj5SlyWFjMtigP-QftIDpBtx53EUPGq1W5Pd1Y9TmYFET0bZlmC4h3b3oLA/s1600/ModuleSingleProcedure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="230" data-original-width="560" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhfdN5qmchZulUNVbUcuQWXZkt52F-IpeIfz-EsAoU19GY2af0fvpeyQgN6utYY0O5swGPGy7cFrxtJpLjpj5SlyWFjMtigP-QftIDpBtx53EUPGq1W5Pd1Y9TmYFET0bZlmC4h3b3oLA/s320/ModuleSingleProcedure.png" width="320" /></a></div>
<br />
In the above configuration, the First-Class Procedure is encapsulated in the Module. All that is exposed from the Module is the Inputs and Outputs. The resulting type of the above Module would be the following:<br />
<ul>
<li>Input named "Input" with a parameter passed to the First-Class Procedure</li>
<li>Output named "Output" with the argument provided by the result of the First-Class Procedure execution</li>
</ul>
<div>
This, however, provides little improvement on the First-Class Procedure interface.</div>
<div>
<br /></div>
<div>
What becomes useful is the encapsulation of multiple First-Class Procedures to undertake functionality of the Module:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC_JWxjph26CGDrhWJYN-uKX6pC5Bg47xAgeoGkvLzVv6ZwX38EdxKtEfiSDAu2ZBtR-fmSxV85M9l6n5tAzkVa7ANtj2XEcROpRM8IUrtvDFvrvIvbYTN3kaQU9md6JTfHoNyREyo9w/s1600/ModuleTwoProcedures.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="228" data-original-width="740" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC_JWxjph26CGDrhWJYN-uKX6pC5Bg47xAgeoGkvLzVv6ZwX38EdxKtEfiSDAu2ZBtR-fmSxV85M9l6n5tAzkVa7ANtj2XEcROpRM8IUrtvDFvrvIvbYTN3kaQU9md6JTfHoNyREyo9w/s320/ModuleTwoProcedures.png" width="320" /></a></div>
<br />
While a new procedure was included within the Module, there was no change to the interface of the Module. Other configuration using the Module would be unaware of the internal addition of another First-Class Procedure.</div>
<div>
<br /></div>
<div>
We also need not limit ourselves to single inputs and outputs. We could have an arbitrarily complex Module that has multiple Inputs and Outputs:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6kcT_KhCHW52d-7vKLl0oHWzhPQfdyX6dpeCfNDftxE97fAoV0vaamrx6AP83FaYkaz8mwLDqhSXrIGWjY6YvQ58U4Da8hVGsHKg8LzzEPIkRNUdEAe35wyj3-vgIUFGNFFkc0hwfrQ/s1600/ModuleComplex.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="360" data-original-width="856" height="134" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6kcT_KhCHW52d-7vKLl0oHWzhPQfdyX6dpeCfNDftxE97fAoV0vaamrx6AP83FaYkaz8mwLDqhSXrIGWjY6YvQ58U4Da8hVGsHKg8LzzEPIkRNUdEAe35wyj3-vgIUFGNFFkc0hwfrQ/s320/ModuleComplex.png" width="320" /></a></div>
</div>
<div>
<br />
The resulting Module encapsulated the detail to have the following interface:</div>
<div>
<ul>
<li>Input "Input"</li>
<li>Input "Input-2"</li>
<li>Output "Output"</li>
<li>Output "Output-2"</li>
<li>Output "Output-3"</li>
</ul>
<br />
<ul>
</ul>
<div>
<h2>
Module Type</h2>
The resulting type for the Module is the following:</div>
</div>
<div>
<br /></div>
<pre><code class="language-java">SectionType {
InputType[] inputs;
OutputType[] outputs
}
</code></pre>
Note that <a href="http://officefloor.net/" target="_blank">OfficeFloor</a>'s naming is derived from its foundation in business concepts and subsequently calls a Module a "Section".<br />
<br />
The Module (Section) has multiple inputs and multiple outputs. These inputs/outputs can then be connected to respective outputs/inputs of other Modules.<br />
<br />
Furthermore, Modules may themselves contain other Modules. As inputs/outputs are connected for composition, Modules have the same input/output connectivity as First-Class Procedures. The following configuration demonstrates embedding the Module at the start of this article within another Module:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9QObB1JoDABwo0QXihBWfSoyUkpOeMLUdQzApETlekYMAnMjgroTROeAq1O8i0xV1XnjfyMfZxI9H1IEAtGKsRREzoXw7qT1jheJnIK-YRhftdsrN5J9kODnup9VpDWRY5ecmBID-lg/s1600/ModuleSubModule.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="208" data-original-width="782" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9QObB1JoDABwo0QXihBWfSoyUkpOeMLUdQzApETlekYMAnMjgroTROeAq1O8i0xV1XnjfyMfZxI9H1IEAtGKsRREzoXw7qT1jheJnIK-YRhftdsrN5J9kODnup9VpDWRY5ecmBID-lg/s320/ModuleSubModule.png" width="320" /></a></div>
<br />
Whether it is the Module containing a single First-Class Procedure or two First-Class Procedures is encapsulated and not of concern within the above configuration. The use of the Module is only on the Inputs / Outputs exposed by the Module. The rest of the complexity of the Module is encapsulated. This allows modularising the application's complexity.<br />
<br />
<h2>
First-Class Module</h2>
So the title mentioned "First-Class Modules", yet we've only discussed visually wiring together the Modules.<br />
<br />
To essentially be "First-Class" the Module needs to be assigned to a variable. Yes, there are other conditions. However, for me, this is the simplest way of thinking about something being first class.<br />
<br />
Well the above graphical configuration is built on Sections (Modules) being configured together programmatically. The graphical configuration is actually a layer above the First-Class Modules (Sections) to enable easier comprehension of how the application is modularised.<br />
<br />
You can see this in OfficeFloor's implementation of the graphical configuration used above in this article. The above graphical configuration is via an Activity. An Activity is a specific specialisation of a Section (<a href="https://github.com/officefloor/OfficeFloor/blob/master/officefloor/activity/officeactivity/src/main/impl/net/officefloor/activity/ActivityLoaderImpl.java" target="_blank">ActivityLoaderImpl source here</a>). The Activity translates the XML from the graphical configuration into the creation of Sections, First-Class Procedures, Inputs, Outputs. Each of these in the Activity implementation are assigned to variables, stored in data structures, passed to functions, returned from functions, etc. This makes the Section (Module) essentially "First-Class".<br />
<br />
This input / output interface based on continuations is extremely flexible. It is so much so that First-Class Procedures themselves are also just a specialised implementation of a Section (<a href="https://github.com/officefloor/OfficeFloor/blob/master/officefloor/activity/officeprocedure/src/main/impl/net/officefloor/activity/procedure/build/ProcedureEmployer.java" target="_blank">see ProcedureEmployer</a>).<br />
<br />
<h2>
Summary</h2>
We have seen how we can encapsulate First-Class Procedures within First-Class Modules, and even First-Class Modules within themselves.<br />
<br />
We have shown how the graphical configuration is actually taking advantage of the "First-Class" nature. The graphical configuration is actually a higher level composition that provides both:<br />
<ul>
<li>easier to comprehend modularising of the application</li>
<li>quicker configuration of the application (effectively just draw lines for composition)</li>
</ul>
Note that it is quite possible to programmatically configure up our application. However, this requires understanding First-Class Procedures / Modules in significantly more depth. Much more than junior developers may want to initially. <br />
<br />
The graphical configuration of First-Class Modules, therefore, provides the simplicity for building modularised applications. This is without having to deal with the complexity of the underlying constructs. Something I'm finding other composition strategies are still having trouble with.<br />
<br />
In the <a href="https://sagenschneider.blogspot.com/2020/01/compose-cats-reactor-zio-effects.html" target="_blank">next article</a> we look at how First-Class Modules can provide composition of varying existing composition strategies. You may find that existing composition strategies only really consider programming in the small, rather than programming in the much larger - where First-Class Modules become a lot more effective in modularising and simplifying your applications.<br />
<br />Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-62487113929834157552019-11-21T07:28:00.000-08:002020-01-25T18:25:04.397-08:00First-Class Procedure Type System for CompositionThis is the first article in a series looking at the Inversion of Coupling Control type system for composition. The series will demonstrate how the resulting type system allows for easy composition. This avoids much of the complexity of Functional / Object-Oriented composition. The resulting type system and it's resulting composition is simple enough even for junior developers to comprehend.<br />
<br />
This series has four articles:<br />
<br />
<ol>
<li>This article discussing the First-Class Procedure type system</li>
<li><a href="https://sagenschneider.blogspot.com/2019/12/first-class-module-type-system-for.html" target="_blank">First-Class Module</a></li>
<li><a href="https://sagenschneider.blogspot.com/2020/01/compose-cats-reactor-zio-effects.html" target="_blank">Demonstration application</a></li>
<li><a href="https://sagenschneider.blogspot.com/2020/01/monad-with-iocc-provides-processthread.html" target="_blank">The underlying theoretical model for composition</a></li>
</ol>
<div>
<br /></div>
<h2>
First-Class Procedure</h2>
This article will look at the type system and composition of <a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">First-Class Procedures</a>.<br />
<br />
We've previously talked about the <a href="https://sagenschneider.blogspot.com/2019/08/what-is-oo-matrix.html" target="_blank">OO Matrix</a>
and how the method (and for that matter the function) suffers from
coupling. We've also discussed how this coupling can be reduced by <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a>. We've also shown how these inverted methods/functions can be <a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">weaved seamlessly together</a>. We've even seen the industry moving towards these concepts with <a href="https://sagenschneider.blogspot.com/2019/05/local-microservices-object-orientation.html" target="_blank">microservices</a>.<br />
<br />
What we haven't yet discussed is the type system and composition available with First-Class Procedures.<br />
<br />
To discuss this, let's start with the well known concept of Dependency Injection.<br />
<br />
<h2>
Dependency Injection </h2>
Meta-data of dependency injection describes a list of dependencies with the following three attributes:<br />
<ul>
<li>Field (or constructor parameter) to inject the dependency (providing the dependency's name - e.g. field name)</li>
<li>Type of the dependency</li>
<li>Optional qualifier (distinguishes dependencies of the same type) </li>
</ul>
<div>
With this information, the matching to dependencies can be undertaken. Note, some dependency injection frameworks have improvements on this. However, the above meta-data is typically adequate for auto-wiring dependencies of the object.</div>
<br />
<h2>
Continuation Injection </h2>
<a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">Continuation Injection</a> reduces a function/method invocation to a similarly simple set of attributes as Dependency Injection.<br />
<br />
As only a single parameter can be passed (remaining are dependency injected), there is only one type required. This is the optional parameter type.<br />
<br />
Also, the continuations from the First-Class Procedure are all named.<br />
<br />
Note that auto-wiring continuations is deemed error prone. Automatically wiring continuation to matching First-Class Procedures requires differing parameter types for each continuation in the system. In practice, most of the time it is the same simple domain data types being passed around. So you end up having to qualify every continuation.<br />
<div>
<br /></div>
<div>
Furthermore, qualifying continuations provides little improvement on reducing complexity. In qualifying all continuations you end up writing configurations for each continuation. In other words, you end up providing a mapping of each continuation name to servicing First-Class Procedure. This configuration is very error prone. We will show how this is made less error prone and easily comprehensible shortly. <br />
<br />
Therefore, each required continuation by the First-Class Procedure is described with the following meta-data:<br />
<ul>
<li>Name of the continuation</li>
<li>Type of the parameter for the continuation (i.e. type of argument sent to continuation)</li>
</ul>
Note that exceptions from the method/function are also modeled as continuations. The type is the exception type. The name is the name of the exception type.<br />
<br />
<h2>
First-Class Procedure Type System </h2>
Putting the Continuation Injection meta-data together with the Dependency Injection meta-data, we get the following meta-data (type) information for the First-Class Procedure:<br />
<br />
<pre><code class="language-java">FirstClassProcedureType {
Class<?> parameterType;
ContinuationType[] continuations;
DependencyType[] dependencies;
}
ContinuationType {
String name;
Class<?> argumentType;
}
DependencyType {
String name;
Class<?> objectType;
String qualifier;
}
</code></pre>
<br />
<br />
The above type can describe all First-Class Procedures. As a method/function requires parameters, these are described by the DependencyType listing. As method/functions require calling other method/functions, this is described by the ContinuationType listing. As there is only one parameter to the First-Class Procedure, the parameter type describes the type of argument that must be supplied by invoking ContinuationType.<br />
<br />
Note that we have not discussed Thread Injection typing. This is actually derived from the DependencyType listing by matching on object's type to thread pool. See <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">Thread Injection</a> for more information.<br />
<br />
As we now can type the First-Class Procedure, we can look at using this type system for composition.<br />
<br />
<h2>
First-Class Procedure Composition</h2>
The composition of First-Class Procedures is focused on wiring together the continuations. Dependency Injection provides the objects (state) to the methods/functions. This wiring of dependencies is done separate to the continuations. Therefore, we need only focus on continuations being wired to their servicing First-Class Procedures.<br />
<br />
Now it is possible to do this in code and even configuration files. However, as the system grows in complexity this listing of continuation name to servicing First-Class Procedures becomes very unwieldy. Trying to decipher the system behaviour from lists of linkages becomes very difficult.<br />
<br />
Therefore, we look at the First-Class Procedure as the following:<br />
<ul>
<li>a processing node with an input anchor</li>
<li>varying number of output anchors for each of it's continuations</li>
<li>linkages as lines from output anchor to input anchor</li>
</ul>
This representation makes for graphical configuration of the composition. The First-Class Procedure is nodes in the graph with lines representing the continuations between them. Therefore, composition of First-Class Procedures is quite literally drawing lines between them.<br />
<br />
As the graphical configuration is visually easy to comprehend, it makes it very easy for even junior developers to understand the application.</div>
<div>
<br /></div>
<div>
<h2>
Summary</h2>
</div>
<div>
We have demonstrated how Continuation Injection simplifies invocation of methods/functions. This simple meta-data model for Continuation Injection is similar to Dependency Injection for objects.<br />
<br />
This simple meta-data enables a type system for First-Class Procedures. This type system enables graphical composition of First-Class Procedures.<br />
<br />
Furthermore, being graphical, the composition is very easy for junior developers to comprehend.</div>
<div>
<br /></div>
The <a href="https://sagenschneider.blogspot.com/2019/12/first-class-module-type-system-for.html" target="_blank">next article</a> will discuss how the First-Class Procedure type system is actually made more general to enable modularising of the application. However, these modules still maintain a similar type system for inclusion in the graphical configuration.<br />
<br />Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-42386173703388759562019-10-15T21:34:00.000-07:002019-10-15T21:34:08.150-07:00OfficeFloor IntelliJ PluginOfficeFloor is now available to develop within IntelliJ.<br />
<br />
While the plugin was originally developed for Eclipse, we have now isolated the functionality into IDE agnostic bundle. This means with a bridging implementation, it is possible to port the OfficeFloor plugin to other IDEs.<br />
<br />
However, for now we are content with Eclipse and IntelliJ for OfficeFloor development.<br />
<br />
Though if you would like to see OfficeFloor development supported by other IDEs, please get involved!<br />
<br />
IntelliJ OfficeFloor Plugin is available at <a href="https://plugins.jetbrains.com/plugin/13151-officefloor" target="_blank">https://plugins.jetbrains.com/plugin/13151-officefloor</a><b> </b>(and in the IntelliJ Marketplace - when using latest IntelliJ version).Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-67919537930030526952019-09-09T21:23:00.000-07:002019-09-09T21:23:09.413-07:00Inverting Functions: Effect Thread binding for Stateless ActorsFunctional programming can be perceived as "hard". Yes, spend time with it and it gets simpler and the benefits make your code definitely better. However, when type errors can start spanning multiple lines, it does suggest the abstract concepts may be "hard" to see clearly.<br />
<br />
We really need to make it easier for junior developers to assist in functional programming of larger systems.<br />
<br />
Now as functional programming pulls heavily on mathematics, I look to a prominent mathematician's early 1800's statement regarding getting better clarity on hard problems:<br />
<blockquote class="tr_bq">
"Invert, always Invert", Mathematician Carl Jacobi</blockquote>
(though he was German, so it was actually "<i>man muss immer umkehren</i>") <br />
<br />
What I understand Carl Jacobi was saying is that invert the problem for a different perspective to try and get an answer. Therefore, maybe in inverting functional programming we can get clarity on making it perceived as "easier".<br />
<br />
So what can we invert about the function?<br />
<br />
We invert the coupling.<br />
<br />
I've written about <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a> in object oriented paradigms. This is even to the point of identifying the <a href="https://sagenschneider.blogspot.com/2019/08/what-is-oo-matrix.html" target="_blank">OO Matrix</a>. In summary, there are 5 couplings of the method that restrict us:<br />
<ol>
<li>Method Name</li>
<li>Varying number of parameters</li>
<li>Varying number of exceptions</li>
<li>Return type</li>
<li>Executing thread</li>
</ol>
Yet, what has this to do with functional programming?<br />
<br />
The function suffers similar coupling. Ok, the exceptions are not thrown but returned as values. However, changing the function's return type, name, parameters, executing thread requires changing all other functions calling that function.<br />
<br />
Now beyond concurrency, Actors provide means to isolate the coupling impact of these changes. As long as the messaging semantics between Actors does not change, the Actor is free to change all its internal functions as it sees fit. This isolates the impact of changing a function to just the Actor.<br />
<br />
So I have to ask. Functional programming is appearing in many mainstream languages. Furthermore, we've now been moving to multi-threaded programming for some time now. So why aren't Actors also becoming more prevalent?<br />
<br />
For me, the reason is the Thread binding in the Actor is to State rather than Effect. This to me makes use of Actors difficult.<br />
<br />
My reasoning comes from these observations:<br />
<ol>
</ol>
<ul>
<li>Actors encapsulate changes to State to make this thread-safe</li>
<li>Effects can wrap changes to State (whether internally in the system or externally)</li>
<li>Multi-threading provides more efficient execution of blocking Effects (such as I/O) * </li>
<li>Threading is configured to the Actor</li>
</ul>
<ol>
</ol>
* multi-threading also enables parallel processing CPU intensive algorithms on multiple CPUs. For the purposes of this discussion, we will model this as an Effect requiring a different Thread.<br />
<br />
Therefore, what I see in Actor modelling is the following relationship:<br />
<blockquote class="tr_bq">
Thread (pool) -> Actor -> State</blockquote>
When it should actually be:<br />
<blockquote class="tr_bq">
Thread (pool) -> (Blocking / Long running) Effect</blockquote>
In attempting to get the right break down of the system into Actors, we have to simultaneously:<br />
<ol>
</ol>
<ul>
<li>Consider an Actor an Effect to assign it the appropriate Thread (pool)</li>
<li>Decompose State of the system into these arbitrary Actors</li>
</ul>
<ol>
</ol>
Now we're caught in the precarious problem of trying to find the right mix of logic, threading and state decomposition. This is a "hard" problem to get right. Once threading becomes involved, it immediately becomes a problem only for intermediate to senior developers. No longer can we have junior developers assist in the system (or at least they need significant supervision).<br />
<br />
Furthermore, developer resources are scarce and we need a way for junior developers to assist in building systems. Yes, there is a beauty and satisfaction in building a finely tuned system that fits together like clockwork. However, businesses don't really want to keep building expensive finely tuned watches just so customers can tell the time. We need to make things easier not harder.<br />
<br />
Hence, that's why I believe we need to invert the function to create a stateless Actor with focus on mapping Threading to Effects. Details of how this can be achieved is available in the following articles:<br />
<ul>
<li><a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of (Coupling) Control</a> </li>
<li><a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">Inverting Thread Coupling</a></li>
<li><a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">Function Inversion of Control</a></li>
</ul>
What this achieves is the following:<br />
<pre><code class="language-scala">def Actor(m: Message, s: State, t: Thread): Array[Effect]
def Effect(r: Resource): AlteredState
</code></pre>
<br />
Simplifying this down:<br />
<pre><code class="language-scala">def Actor(m: Message, s: State, t: Thread, r: Array[Resource]): AlteredState
</code></pre>
<br />
Hey! Effect was just removed!<br />
<br />
Yes, because we don't really make the mapping decision of Thread to Effect. We make it based on the nature of the Effect - blocking / long running. The Effect encapsulates this so we don't really know whether we are just quickly updating internal memory or making a blocking I/O interaction.<br />
<br />
We make the Thread mapping decision based on the resources used by the Effect. If the Effect requires a database connection, it is likely to be making blocking SQL calls. If the Effect requires a HTTP Client, it is likely to be making blocking HTTP calls. If, however, the Effect only uses non-blocking resources, it is very unlikely to be blocking.<br />
<br />
Now if we extract out the Thread from the above Actor, we get:<br />
<br />
<pre><code class="language-scala">def ActorEffect(m: Message, s: State, r: Array[Resources]): AlteredState
def Actor(e: ActorEffect, t: Thread): AlteredState
</code></pre>
<br />
The junior developer is now free of threading to write the ActorEffect.<br />
<br />
Later a senior developer is able to make the correct mappings of Thread to ActorEffect. This is because the determination can be made by the resources (whether blocking or not) used by the ActorEffect.<br />
<br />
Furthermore, the ActorEffect can be written just as a function with State passed in. This makes the ActorEffect stateless so the junior developer is not involved heavily in thread-safety.<br />
<br />
The ActorEffect is now able to be written by the skill level of the junior developer.<br />
<br />
There are further improvements on the weaving together of the ActorEffects. The following article provides working code of how junior level functions can be weaved together with threading configured separately afterwards:<br />
<br />
<a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">Weaving together functions (and other paradigms)</a><br />
<br />
<div>
<div>
Therefore, it is now easy for junior developers to assist in building large functional applications. With the use of Prototype Threading by IoC, this is potentially to millions (even billions) of stateless Actors scattered across thousands of underlying physical machines. But the ease of writing small functions remains for the junior developers making it easier for them to be involved on large scale projects.</div>
</div>
<div>
<br /></div>
<div>
And thus I ask, whether in attempting to improve functional programming by finding even more niche and complex mathematics is the right way forward? Or do we follow Carl Jacobi's advice and invert, always invert!</div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-42728830360718596342019-08-08T16:29:00.001-07:002019-08-08T16:30:30.676-07:00What is The OO Matrix?<i><b>Morpheus</b></i>: I've seen an agent punch holes in designs with only a single dependency. Developers have fought against them with APIs that resulted in nothing but limitations. Yet their strength and their speed are still based in a world that is built on coupling. Because of that, they will never be able to write as simple or as fast code as you can.<br />
<br />
<b><i>Neo</i>:</b> What are you trying to tell me, that I can design objects for easy refactoring within applications?<br />
<br />
<b><i>Morpheus</i>:</b> No, Neo. I'm trying to tell you that when you're ready, you won't have to.<br />
<br />
Take the red pill. Read on and I show you how deep The OO Matrix goes...<br />
<br />
<br />
In my opinion, The OO Matrix is what happened to Object Orientation when the interfacing of objects devolved to the method.<br />
<br />
As per my other article <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of (Coupling) Control</a>, there are 5 caller coupling aspects to the method.<br />
<ol>
<li>Return type</li>
<li>Method name</li>
<li>Variable number of parameters</li>
<li>Variable number of exceptions</li>
<li>Executing thread</li>
</ol>
This method based object interaction is a long way away from the intended message passing vision by Alan Kay (as I understand the history). Typically, we have envisioned Object Orientation to look as follows, with nice round objects linked by lines:<br />
<br />
<img alt="" src="data:image/png;base64,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" /><br />
<br />
However, objects interacting via methods have very different shapes. The variability of the method coupling has objects look a lot more like jigsaw pieces. The connectors are not simple lines, but complex methods that shape the object differently:<br />
<br />
<img alt="" src="data:image/png;base64,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" /> <br />
<br />
Piecing these method interfacing objects together forms a rigid jigsaw. This rigid jigsaw is difficult to refactor due to all the coupling. The result is The OO Matrix:<br />
<br />
<img alt="" src="data:image/png;base64,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" /><br />
<br />
With the birth of Java in the 90's and the ratification of the C++ standard in the same decade, "it is not without a sense of irony" that the Matrix film came out about the same time we locked ourselves into programming within The OO Matrix. Some of us may sense it's existence with refactoring frustrations, while others grew up in it knowing no difference.<br />
<br />
The OO Matrix exists all around our programming coupling us to the machine. If we consider:<br />
<ul>
<li>the method represents pushing/popping state on/off the thread stack</li>
<li>the thread stack represents execution by machines</li>
<li>then designing interfaces based in methods is binding us to the machines</li>
<li>and as such we perpetuate The OO Matrix</li>
</ul>
<br />
And really, where in the real world do we find a thread stack? Object Orientation was derived from chemical reactions. Businesses operate in message passing (e.g. emails and documents). Even my understanding of our brains is built on message passing. In other words, thread stacks are a machine based construct. Using the thread stack derived method for object interaction binds us into the machine - The OO Matrix.<br />
<br />
See my other articles on <a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">First-Class Procedures</a> and <a href="https://sagenschneider.blogspot.com/2019/05/local-microservices-object-orientation.html" target="_blank">Local Microservices</a> about how we can break free from The OO Matrix. These articles demonstrate using messages to interface between objects (i.e. single parameter unnamed methods). This breaks us free from the method, the thread stack, and subsequently freeing our code from machines - The OO Matrix.<br />
<br />
Well, this is how I like to describe it - as it's a pretty dry topic otherwise!<br />
<br />
But I certainly cry about all those hours (if not days/weeks) of refactoring code in my life due to the method coupling problem. Especially, as if we followed Alan Kay's vision of focusing on message passing, this should never have been a problem. And to me, this may actually be a more expensive mistake than <a href="https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions" target="_blank">null</a>.Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com2tag:blogger.com,1999:blog-274357204559150666.post-29269522945475422752019-07-01T08:37:00.000-07:002019-07-24T18:00:46.104-07:00DDD Perth 2019 Preview<br />
This article is a little taster to wet your appetite regarding my talk at <a href="https://dddperth.com/" target="_blank">DDD Perth 2019</a>. Given there are 6 tracks competing for your attention, I'm just here to say that if you have a technical inclination don't miss:<br />
<br />
<h2 style="text-align: center;">
Dependency Injection is only 1/5 of the Inversion of Control problem</h2>
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzqycvs2rW4Zmv3pnL-fAnGCblXYNneQWv57VJuIuUTpqI0voiN4pHBHdlwjQdQ1tuxn25Mso-QuGEornM9vZaKeFva-bq1V2ZJJKsdm0g51sUj0aOGw4iNGfuQccWFbigc_qmN0jKiw/s1600/Matrix.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="595" data-original-width="1058" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzqycvs2rW4Zmv3pnL-fAnGCblXYNneQWv57VJuIuUTpqI0voiN4pHBHdlwjQdQ1tuxn25Mso-QuGEornM9vZaKeFva-bq1V2ZJJKsdm0g51sUj0aOGw4iNGfuQccWFbigc_qmN0jKiw/s400/Matrix.png" width="400" /></a></div>
<br />
<br />
<br />
First of all, the presentation is full of <a href="https://www.youtube.com/watch?v=qC0eO7f1fwU" target="_blank">Matrix references</a>. You get to geek out on not only the latest in tech patterns, but do it with lots of Sci-Fi references. Plus the Matrix is a great analogy for my talk, as I show you what is the OO Matrix.<br />
<br />
Yes, the OO Matrix is very real if you write any mainstream OO languages (and even functional languages). You are all plugged into it! Some of you, like Neo, may sense it's existence. Others of you grew up in it, knowing no difference! History even has some sense of irony that the Matrix film came out around the time the OO Matrix plugged us all in. I will show you what it is and there is no going back, once you see it. Get ready to swallow the "red pill" and join me in Zion.<br />
<br />
And if that alone does not entice you enough, then get the "geek credit" for being present at the first talk where I introduce:<br />
<ul>
<li>Continuation Injection</li>
<li>Thread Injection</li>
</ul>
If you think Dependency Injection shaped much of mainstream development, then you'll be able to tell your co-workers, new interns, even your kids that you were present when Continuation Injection and Thread Injection were first announced at a conference!<br />
<div>
<br /></div>
<div>
You may think Inversion of Control and Dependency Injection are dry topics. I assure you will be far from bored, and I'll leave you like you did walking out of the Matrix. In the words of Keanu Reeves.... <a href="https://www.youtube.com/watch?v=Odo5hwu9-wM" target="_blank">"WHOA"!</a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizXizMIyYHKjPCwT0aPkym0qTEec5fBintNrTzKazrfSwomSYi0VJ7oVz0_6xwWZKeMG-e-TzSIH9ZWnppg2xt1KOEaw0KQX0cqZ7_FeAO3Sg1wYOjbUO9peOxodMayLY00nQQBgmQnA/s1600/dddperth.com_twitter%25403x.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="534" data-original-width="1600" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizXizMIyYHKjPCwT0aPkym0qTEec5fBintNrTzKazrfSwomSYi0VJ7oVz0_6xwWZKeMG-e-TzSIH9ZWnppg2xt1KOEaw0KQX0cqZ7_FeAO3Sg1wYOjbUO9peOxodMayLY00nQQBgmQnA/s640/dddperth.com_twitter%25403x.png" width="640" /></a></div>
<br />
<br />Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-91553316374572740432019-06-18T22:13:00.000-07:002019-06-19T00:20:30.365-07:00Local Microservices: First-Class ProceduresThis is the third article in a three part series on local microservices. The first two articles looked at:<br />
<ul>
<li><a href="https://sagenschneider.blogspot.com/2019/05/local-microservices-object-orientation.html" target="_blank">Object Orientation Behaviour Coupling Problem</a></li>
<li><a href="https://sagenschneider.blogspot.com/2019/06/local-microservices-breaking-up-jigsaw.html" target="_blank">Breaking the Jigsaw</a></li>
</ul>
These articles identified the method coupling of Object Orientation creates a monolithic jigsaw of different shaped objects. Microservices are breaking these into more manageable, smaller jigsaws that appear similar in shape.<br />
<br />
This article continues the breaking down to consider local (pass by reference) microservices. <br />
<br />
<h2>
Part Three: Local Microservices via First-Class Procedures</h2>
The first two articles in this series identified:<br />
<ol>
<li>Object references are a nice graph of nodes (objects) and lines (fields)</li>
<li>Object methods have a significant coupling problem creating a jigsaw of behaviour</li>
<li>Microservices break the method couple to return behaviour to a graph of nodes (microservices) and lines (HTTP requests, / Queue messages)</li>
</ol>
There is an underlying pattern to representing this decoupled behaviour. It is HTTP URL / Queue name and payload / message type. This decoupled client calling pattern can be represented with the following general interface:<br />
<br />
<pre><code class="language-java">interface ClientCall<T> {
void invokeService(T singleObject);
}
</code></pre>
<br />
This client calling interface is then implemented by the appropriate HTTP request <span style="font-family: "courier new" , "courier" , monospace;">service(...)</span> method or Queue <span style="font-family: "courier new" , "courier" , monospace;">onMessage(...)</span> method. These methods are usually found on the following objects:
<br />
<br />
<pre><code class="language-java">public void SomeHttpServicerImpl {
@Inject SomeRepository someRepository;
@Inject AnotherRepository anotherRepository;
@Inject ClientCall<SomeArgument> anotherMicroservice;
// other dependencies
public void service(SomeObject httpRequestEntity) {
// service HTTP request with injected dependencies
}
}
</code></pre>
<pre><code class="language-java">public void SomeQueueConsumerImpl {
@Inject SomeRepository someRepository;
@Inject AnotherRepository anotherRepository;
@Inject ClientCall<SomeArgument> anotherMicroservice;
// other dependencies
public void onMessage(SomeQueueMessage message) {
// service Queue message with injected dependencies
}
}
</code></pre>
<br />
Furthermore, what is not shown clearly is the threading model. As the HTTP servicer or Queue consumer are in their own process, they are run with their own threads.<br />
<br />
The result is the following pattern for implementing the microservice:
<br />
<ul>
<li>Single object provided by client</li>
<li>Remaining objects are dependency injected</li>
<li>Thread used is based on service/consumer implementation</li>
<li>Interaction with other microservices is via single parameter ClientCall</li>
</ul>
<div>
The issue with this pattern is that all calls to other microservices require the microservice to be executed by another thread. As the mciroservice resides behind HTTP requests / Queues, there is process boundaries preventing the calling thread from executing the microservice.</div>
<div>
<br /></div>
<div>
The process boundary separation provides a bounded context, so that the microservices are isolated from each other. However, this separation puts a lot of communication overheads and network error handling into microservice solutions. Plus it disallows microservices from being executed by the same thread.</div>
<div>
<br /></div>
So can we have the microservice called and executed by the same thread, and still continue to provide the microservice advantages of bounded contexts? (in other words, the smaller jigsaws)<br />
<br />
<h2>
Local Bounded Context</h2>
To see how local (same thread calling/executing) microservices can be achieved, we need to transform the above implementations slightly.<br />
<br />
Rather than field/setter injection, let's look at using constructor injection. We could turn the above implementation into the following:<br />
<br />
<pre><code class="language-java">public void SomeMicroserviceImpl {
private final SomeRepository someRepository;
private final AnotherRepository anotherRepository;
private final ClientCall<SomeArgument> anotherMicroservice;
@Inject
public SomeMicroserviceImpl(
SomeRepository someRepository,
AnotherRepository anotherRepository,
ClientCall<SomeArgument> anotherMicroservice) {
this.someRepository = someRepository;
this.anotherRepository = anotherRepository;
this.anotherMicroservice = anotherMicroservice;
}
public void service(SomeObject httpRequestEntity) {
// service HTTP request with injected dependencies
}
}
</code></pre>
<div>
</div>
<br />
However, that's a lot of code!<br />
<br />
Rather, why not just inject the dependencies directly into the method:<br />
<pre><code class="language-java">
public static void service(
SomeObject httpRequestEntity,
SomeRepository someRepository,
AnotherRepository anotherRepository,
ClientCall<SomeArgument> anotherMicroservice) {
// service HTTP request with injected dependencies
}
</code></pre>
<br />
The method has effectively become a procedure. The object and all it's fields are no longer necessary. The above procedure links the required objects together by being parameters.<br />
<br />
This execution is now:<br />
<ol>
<li>ClientCall used to invoke a procedure</li>
<li>Procedure pulls in appropriate dependencies</li>
<li>Procedure then invokes other procedures via the ClientCall interface</li>
</ol>
<div>
The execution is no longer methods navigating the Object references, locking you into monolithic jigsaw. It is now procedures invoking each other, pulling in only the required dependencies for the procedure.</div>
<div>
<br /></div>
<div>
As the procedure pulls in only its required objects, it provides a bounded context. One procedure may pull in a particular set of objects, while another procedure may pull in a totally different set of objects. As the procedure joins the objects, we no longer have to create a big graph of all objects referencing each other. We can separate the objects into smaller graphs. This break down allows separation of objects into bounded contexts.</div>
<div>
<br /></div>
<div>
Now the question comes of how can we implement this so the procedures run within the same process space?</div>
<br />
<h2>
First-Class Procedure</h2>
Well this procedure is remarkably similar to the First-Class Procedure. See:<br />
<ul>
<li><a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">OO Functional Imperative Reactive weaved together</a> (for a running code example)</li>
<li><a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">Function IoC for First Class Procedure</a> (for more of the theory and how the containerising works)</li>
</ul>
What the First-Class Procedures allows is containerising small snippets of logic within a procedure. These procedures communicate via loosely coupled continuations that require only a single object (payload message). The remaining objects are dependency injected. Furthermore, threading models can be specific to each procedure.<br />
<br />
The two bounded context approaches have similar characteristics:<br />
<ul>
<li>HTTP/Queue communication can be considered a single argument Continuation</li>
<li>Threading models can be different within each first-class procedure / microservice process</li>
<li>Dependency Injection of both allows access to only the required object graph allowing smaller object jigsaw puzzles (no monoliths). In other words, bounded contexts.</li>
</ul>
The difference is that the same thread can call and execute the First-Class Procedure. In other words, First-Class Procedures run locally with each other.<br />
<br />
<h2>
Remote vs Local</h2>
But don't microservices want to be process separated to allow different release cycles and scalability?
<br />
Yes, that is absolutely true once up and running in production with heavy load of users. However, what about getting started with microservices?
<br />
<br />
For me this falls into the problem of being <a href="https://sagenschneider.blogspot.com/2019/03/perils-of-opinionated-frameworks-like.html" target="_blank">opinionated too early</a>. To get the right mix of microservices takes a significant amount of requirements gathering and architecture. Why? Because refactoring microservice architectures can be expensive. Microservices involve a lot of overhead in typically different code repositories, build pipelines, network failure handling, etc. Finding you got the microservice mix wrong involves a lot of effort to change.<br />
<br />
By starting out with first-class procedures, you get to try a local microservice mix. If the mixture is wrong, it is very quick to change them. First-class procedures are weaved together graphically. Therefore, to change the mixture is simply rewriting the procedures and then drawing the new connections between them. Yep, that's it. No code moving between repositories. No changing build pipelines. No extra error handling because of network failures. You can get on with trying out various mixes of local microservices (first-class procedures) all on your local development machine.
<br />
<br />
Once you find a mix you are happy with, deploy all of them in the one container. Why? Because unless you have a large user based, you can run your first-class procedures in just one node (possibly two for redundancy). Having less deployed nodes, means less cloud instances. Less cloud instances, is well less dollars.
<br />
<br />
Then as your load increases, you can split out the first-class procedures into separate nodes. Just change the continuation link between them to either a HTTP call or Queue. Furthermore, this split can then be for various reasons you may discover along the way:
<br />
<ul>
<li>differing functionality change cycles</li>
<li>differing team responsibilities (e.g. Conway's Law)</li>
<li>data governance may mean geographic restrictions</li>
<li>security may require some to run on premise</li>
<li>on premise capacity limits may mean pushing some to public clouds </li>
</ul>
The above is not an exhaustive list.<br />
<br />
Having to requirements gather and architect the microservice mix given all of the above could get quite exhausting. Especially, as some aspects are quite fluid (e.g. teams change, companies buying other companies, capacity limits on in house data centres, etc). There are significant factors making it difficult to find the right mix of microservices up front.
<br />
<br />
Plus this also works in reverse. As things change and some aspects don't experience higher loads or significant functional changes, they can be combined back into single instances. This reduces the number of cloud instances required, and again reduces dollars.
<br />
<br />
<h2>
Summary</h2>
For me, local microservices (i.e. pass by reference mircoservices) is going to eventuate. This is similar to session EJBs being introduced because the EJB 1.0 specification of only remote calls was just too heavy. Yes, we have better infrastructure and networks than 20 years ago. However, the financial overhead costs of only remote microservices may soon be considered heavy weight and expensive given that local (pass by reference) First-Class Procedures are available.<br />
<br />
So if you are finding the "remote" microservice architect a heavy weight and expensive consideration, try out First-Class Procedures as a local microservice solution. This gets you many of the benefits of microservices without the expense. Then, as your load increases and your revenues increase, scale into a remote microservice architecture. But this is only where you see real need, so you can keep your infrastructure costs down.<br />
<br />Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-72796496353421032272019-06-06T22:05:00.000-07:002019-06-06T22:05:44.740-07:00Local Microservices: Breaking up the JigsawThis is part two in a three part series looking at local microservices running in the same process. Part one identified the coupling problems in Object Orientation behaviour (found <a href="https://sagenschneider.blogspot.com/2019/05/local-microservices-object-orientation.html" target="_blank">here</a>). This article will look at how microservices are helping reduce the coupling problem. <br />
<br />
<h2>
Part Two: Breaking up the Jigsaw</h2>
Part one identified that object behaviour coupling is similar to a jigsaw puzzle. This is a highly coupled jigsaw of varying shaped objects. These different shaped objects makes their re-use and refactoring difficult within monolithic applications.<br />
<br />
So, you may be asking how are microservices helping this problem? <br />
<br />
For me, I see the evolution of microservices to be an evolution to break down the rigid behavioural coupling imposed by object methods.<br />
<br />
We had applications grow to become monoliths:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9XUooEltIH70Waq96HGh9SqN5oQm_Lrn5aHZyDLGsQmZsK4BtqR2y6bocKui3TQ7tb37xz14rBZ3XQWe_xKkRrjK8WYYm0akwLih8Wurk_WdRVBDn86RZDEg0f20td3T0_mrfWID8qw/s1600/jigsaw-puzzle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="640" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9XUooEltIH70Waq96HGh9SqN5oQm_Lrn5aHZyDLGsQmZsK4BtqR2y6bocKui3TQ7tb37xz14rBZ3XQWe_xKkRrjK8WYYm0akwLih8Wurk_WdRVBDn86RZDEg0f20td3T0_mrfWID8qw/s320/jigsaw-puzzle.png" width="320" /></a></div>
<br />
This became unmanageable to enhance or re-use, as everything was tightly coupled together in a rigid jigsaw.<br />
<br />
Our first attempts was to try re-using parts of the jigsaw with Service-Orientated Architectures. This looked like the following:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl-L2hs3uMxQWdt3NdvCTwanlSBfiB5snQVcUfjl-PvfvadlDPykJMmS7Jh2FHIobGTjxZ0bnieiKjUWbz5jkO3Q9c6OuK6_76E31tbchFaNu50NAKKAObuazBs6VAkv7Foj9BRI03jQ/s1600/SOA.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="219" data-original-width="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhl-L2hs3uMxQWdt3NdvCTwanlSBfiB5snQVcUfjl-PvfvadlDPykJMmS7Jh2FHIobGTjxZ0bnieiKjUWbz5jkO3Q9c6OuK6_76E31tbchFaNu50NAKKAObuazBs6VAkv7Foj9BRI03jQ/s1600/SOA.png" /></a></div>
<br />
<br />
The service-oriented architecture was, in my opinion, a doomed to failure attempt to the expose method connectors outside the system for re-use. Yay, we can now call into our monoliths to re-use aspects of them. Oh, wait there was too much coupling to that method that it was just too hard to separate it from the rest of the monolith.<br />
<br />
Ok, we could put in governance and some great coding practices to avoid this. However: <br />
<ul>
<li>deadlines</li>
<li>shortcuts </li>
<li>new team members</li>
<li>occasional bad design decisions </li>
<li>etc </li>
</ul>
allows the coupling to increase over time. As much as we wanted to believe in the ideals, the behaviour coupling of methods just took over to create the monolith jigsaw.<br />
<br />
We needed to break things down and keep them isolated.<br />
<br />
So we split the jigsaw up into smaller puzzles. The result is the following smaller puzzles joined by HTTP requests / Queues:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_yPzl7w1hrfkNkDZY_tUDNoFOheTx2D05cH96rv6tcSAJFrUv9nikwfyXNN89Cj1B8FpL-KANkeSLRM-zu8NSXni5ajjyYX8DimwKeHXzd0d_bojQ1cXHW-Zml2zhYLnWhvfBYuzurA/s1600/BrokenDownOO.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="600" data-original-width="800" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_yPzl7w1hrfkNkDZY_tUDNoFOheTx2D05cH96rv6tcSAJFrUv9nikwfyXNN89Cj1B8FpL-KANkeSLRM-zu8NSXni5ajjyYX8DimwKeHXzd0d_bojQ1cXHW-Zml2zhYLnWhvfBYuzurA/s320/BrokenDownOO.png" width="320" /></a></div>
<br />
And for me, microservices were born.<br />
<br />
At first glance, this looks very similar to the original EJB 1.0 specification of only remote calls. Now one might argue that microservices are not single objects like EJBs typically were. This, however, is not why I see microservices an improvement over remote EJBs.<br />
<br />
EJBs use remote procedure calls that allow multiple parameters and varying exceptions to be thrown. This does nothing to decouple you from the varying shape of the method call. EJBs only enable methods to be called remotely. These remote method calls continue to have all the jigsaw coupling issues of method calls. Except, now they are less reliable due to network failures. Hence, EJBs suffer the method coupling problems that leads you to a distributed monolithic jigsaw.<br />
<br />
Microservices on the other hand, standardised calls to other microservices via HTTP requests / queue messages. Looking at the five coupling aspects of the method call (<a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a>), HTTP requests / queue messages remove most of the method call
coupling:<br />
<div>
<br /></div>
<table class="pure-table">
<thead>
<tr><td style="width: 20%;">Method Coupling Aspect</td><td style="width: 40%;">HTTP Request</td><td style="width: 40%;">Queue</td></tr>
</thead>
<tbody>
<tr>
<td>Method Name</td><td>URL<br />
<br />
Though, can be decoupled indirection via lookup in service directory/registry</td><td>Outbound queue<br />
<br />
Provides decoupled indirection to target consumer (via message routing)</td>
</tr>
<tr class="pure-table-odd">
<td>Return Type</td><td>May provide return entity.<br />
<br />
However, typically this is only for front-ends with users waiting.<br />
<br />
Note: be careful of synchronous returns between microservices, as they can create synchronous coupling that can lead to distributed monoliths</td><td>N/A, as decoupled from any synchronous return values</td>
</tr>
<tr>
<td>Parameters</td><td>Only single payload<br />
<br />
Typically JSON/XML serialised object.</td><td>Only single payload<br />
<br />
Typically JSON/XML serialised object.</td>
</tr>
<tr class="pure-table-odd">
<td>Exceptions</td><td>Standardised REST status codes.<br />
<br />
Note: be careful of relying on error response payloads, as they may be indications of cohesiveness problems in the microservice</td><td>N/A, as decoupled from any synchronous processing </td>
</tr>
<tr>
<td>Threading</td><td>Decoupled as separate process<br />
<br />
Any threading model enabling synchronous response</td><td>Decoupled as separate process<br />
<br />
No restriction on threading model</td>
</tr>
</tbody></table>
<br />
<br />
Therefore, using HTTP requests / queues, the microservice calling shape is effectively standardised. Given the payload is typically a serialised object
(e.g. JSON/XML), this removes the ability to pass multiple parameters. Standardising the HTTP status codes disallows varying
exceptions. Plus, my preferred microservice communication of queues is decoupled by its very nature.<br />
<br />
So by making the communication HTTP requests / queue messages, microservices are removing the method coupling problems. It makes it easier to call different microservices, as the shape is only a name (HTTP URL / Queue name) and a single parameter (payload).<br />
<br />
This, actually, is similar to the object reference shape of type and reference discussed in part one. However, now type is parameter type (payload serialised object) and reference is name (URL / Queue name). This allows microservice behaviour to somewhat be represented like the idealised object graph at the start of part one - lines to standard shaped microservice call connectors.<br />
<br />
Stay tuned for part three where we look at further isolating the microservice container to the servicing method to effectively enable local microservices.Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-53519252476064814432019-05-28T20:53:00.000-07:002019-05-29T21:48:10.690-07:00Local Microservices: Object Orientation Behaviour Coupling ProblemThis is the first in a three part series on looking at creating "local" microservices.<br />
<br />
What I mean by local microservices is pass by reference microservices running in the same process. Right now I see microservices similar to the original EJB 1.0 specification. All calls between the EJBs were remote, just like microservices are now. Due to remote call overheads, the EJB 2.0 specification brought in session (local, pass by reference) EJBs running in the same process.<br />
<br />
Now, before getting to local microservices, we need to look at identifying the Object Orientation behaviour coupling problem. This to me, identifies a big problem that microservices resolve. It is also the reason enabling local microservices.<br />
<br />
<h2>
Part One: Object Orientation Behaviour Coupling Problem</h2>
Structurally Object
Orientation joins objects together in a very nice graph. These
typically look something like the following:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5z0GlK6DIKrJ2enyHjRg7WZI_CT6cj2N1d9blyk3xw5ego10OWv7uNQWUorWLfkg5_wFeqzf2oZXzEiJ-UIRs4FQTALP1uoe7uGXSUF0r6zEutJENjAm7_dyZi9IeEyAhO1C_r3a-yQ/s1600/objectgraph.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="417" data-original-width="500" height="266" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5z0GlK6DIKrJ2enyHjRg7WZI_CT6cj2N1d9blyk3xw5ego10OWv7uNQWUorWLfkg5_wFeqzf2oZXzEiJ-UIRs4FQTALP1uoe7uGXSUF0r6zEutJENjAm7_dyZi9IeEyAhO1C_r3a-yQ/s320/objectgraph.png" width="320" /></a></div>
<br />
These
graphs represent the object relationships in your application. Each
line is a field reference to another object. This, for example, allows
modelling your personal details to have addresses, phone number and
various other objects containing information.<br />
<br />
However, I can't
call an object reference. I use the object reference to access a method
on the object. Behaviour of your application actually follows the
method calls. In other words,
program
control follows method calls on the thread stack. Yes, the object references make methods accessible to be called, however the methods calling each other is how behaviour of your application is achieved.<br />
<br />
So,
we can just draw the above graph with the methods calls, right? No, the
method coupling is a lot more complicated than just an object reference
that varies at most by type (see <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Coupling Control</a>). Methods have:<br />
<ul>
<li>a particular return type</li>
<li>a name</li>
<li>varying number of parameters with differing types</li>
<li>varying number of exceptions with differing types</li>
<li>thread to execute them</li>
</ul>
<div>
Drawing a <i>simple</i> line between objects to represent
behavioural relationships (program control flow) does not respect the method coupling complexity. In the object structural
graph, changing a line is simply changing the reference (memory
address) to another object. Yes, restrictions apply based on the type of
object referenced, but it is a single address value that couples the two objects
into a structural relationship. This is not the case with methods.</div>
<div>
<br /></div>
<div>
Each method call is a different shape. In terms of object structural
connectors the shape of the object reference is object type and memory
address. This is consistent across all object references. However,
for methods the call (connectors) are different shapes due to the above 5
aspects. In other words, one method may have 1 parameter, while another
has 3 and throws 2 exceptions. The shape of each method call
connector varies significantly.</div>
<div>
<br /></div>
<div>
Drawing the behaviour diagram of object method calls is more akin to the following:</div>
<div>
<br /></div>
<div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC6lzzN8sv0VT6JhaMawGfr9VjEauifPGwuQyaF59_Tt2SmKzS_Syo_Soy8OGzSJRxMC_pn5b68673ZUkx33Zl_bdhYCZeW9RoKPKkKXUkC9tiMLtt32-IhAODq625ck0wn2EAQD6ltw/s1600/jigsaw-puzzle.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="640" height="160" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjC6lzzN8sv0VT6JhaMawGfr9VjEauifPGwuQyaF59_Tt2SmKzS_Syo_Soy8OGzSJRxMC_pn5b68673ZUkx33Zl_bdhYCZeW9RoKPKkKXUkC9tiMLtt32-IhAODq625ck0wn2EAQD6ltw/s320/jigsaw-puzzle.png" width="320" /></a></div>
<br /></div>
<div>
Each call (connector) between the methods is a different shape, just like a jigsaw.</div>
<div>
<br /></div>
<div>
We
piece objects together into a jigsaw to achieve the behaviour of the
application. This is why refactoring your application is so difficult.
It's like trying to move pieces of a jigsaw around to make a new
picture. We end up having to change the pieces significantly just so
they even attempt to fit into the new picture.</div>
<div>
<br /></div>
<div>
It
is also the reason, I believe, why object orientation never provided
that ideal class re-use. Re-using objects is like trying to re-use
jigsaw pieces of one puzzle to complete another puzzle. Now if the
puzzles are somewhat alike, you can kinda jam them together. However,
more often than not you have to change the piece (object) to fit into
the other jigsaw (application) losing re-use.</div>
<div>
<br />
Hence, the method coupling problem creates a significant behavioural coupling problem in monolithic Object Oriented systems. Refactoring is an expensive exercise, as its not redrawing lines between nice round objects. Refactoring is reshaping pieces to fit into a new jigsaw picture.<br />
<br />
Now I can continue the analogy further with much of API development attempting to standardise jigsaw pieces and finding generic pictures that represent majority of systems. However, I'm hoping you can join me in seeing that much of Object Orientation behaviour coupling problem is not with the objects but rather the use of methods.<br />
<br />
And yes, for Object Orientation purists, Object Orientation is more about loosely coupled message passing. In other words, languages such as Erlang may be more closer to what the intention of Object Orientation really was supposed to be. However, my focus here is the "mainstream" understanding of Object Orientation being objects and methods.<br />
<br />
Stay tuned for my next part on how microservices are helping with relieving the Object Orientation method coupling problem.</div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-62981020963979611422019-04-28T19:16:00.000-07:002019-04-28T19:16:30.752-07:00Function IoC for First Class ProcedureThis is the second article of two to introduce the term I'm suggesting of "first class procedure". The <a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">first article</a> provided a working example of the first class procedure to see them in action. This article delves into the detail and some theory on how the first class procedure has evolved.<br />
<br />
The evolution of the "first class procedure" starts with looking at the function. The function takes in parameters to then produce the result:<br />
<br />
<pre><code class="language-scala"> type Function = Array[Any] => Any
// Example of first class function
def exampleFunction(paramOne: Int, paramTwo: Double): String
val firstClassFunction: Function = (parameters) => exampleFunction(parameters(0).asInstanceOf[Int], parameters(1).asInstanceOf[Double])
</code></pre>
<br />
However, before being able to obtain any results, the function also requires a thread to be run. This is what I refer to as the "implicit thread". The function does not define details regarding the thread to use, so defaults to the invoking thread of the function (the implicit thread).<br />
<br />
Ideally, we should enhance the function signature to indicate the thread more explicitly so we can allow more control in how the composed functions are executed:<br />
<br />
<pre><code class="language-scala"> type Executor = (Function, Array[Any]) => Any
def invoke(executor: Executor, function: Function, parameters: Array[Any]) =
executor(function, parameters)
</code></pre>
<br />
Now the thread to execute the function is made explicit. Note that the executor is means to invoke with the implicit thread or a separate explicit thread via a thread pool.<br />
<br />
An argument might be that threading is hard and should be left to compilers/frameworks/etc. However, I'm believing that I still want some control over the execution profile of the application. A reason for this would be the following example.<br />
<br />
I'm running a multi-user application on a large server with multiple processors that does various blocking I/O and expensive CPU computations to service a request. I really want to optimise the CPU computations to have them have affinity to a core to avoid cache misses and thread context switching overheads. Plus I want to isolate the blocking I/O to a separate thread pool so the CPU computations do not block causing idle CPUs. Given the load of I/O I might want to isolate one core to do all I/O leaving the remaining cores free for the CPU computations. Conversely, I might find the I/O is minimal and can time slice with the CPU computations so I can get an extra core for the CPU computations to gain increased throughput. Ideally, I would like means to tweak this for the application.<br />
<br />
Then requirements change and I now want to use the same application to service a single user that is running the application on a single core (e.g. a cheap portable embedded system). In this circumstance, I'm happy for the CPU computations to block while the I/O is underway. Basically, I just want one implicit thread to run all the functions.<br />
<br />
In both the above, it is the same application logic but just different execution profiles based on the environment the application is running within.<br />
<br />
So taking our above explicit function signature we now require to have the higher order functions provide appropriate threading information to invoke each composed function:<br />
<br />
<pre><code class="language-scala"> def higher(executorIO: Executor, executorCpuIntensive: Executor, parameters: Array[Any]) =
executorIO(functionIO, Array(executorCpuIntensive(functionCpuIntensive, parameters)) ++ parameters)
</code></pre>
<br />
This now requires the higher order function to determine the thread for each contained function. This can blow out the higher order function's signature. Therefore, let's for now create a function that can determine the executor for a function:<br />
<br />
<pre><code class="language-scala"> type ExecutorLocator = Function => Executor
</code></pre>
<br />
So this now changes the higher order function to be:<br />
<br />
<pre><code class="language-scala"> def higher(executorLocator: ExecutorLocator, parameters: Array[Any]) =
executorLocator(functionIO)(functionIO, Array(executorLocator(functionCpuIntensive)(functionCpuIntensive, parameters)) ++ parameters)
</code></pre>
<br />
So we've stopped the blow out of the higher order function signature, but it starts to highlight a problem of passing results between the composed functions. Well not so much in passing results, but in which parts of the logic to execute with which thread.<br />
<br />
To get the result from functionA to pass to functionB, we have two approaches: <br />
<ul>
<li>As functionA completes, the system returns the result to the higher order function's thread that then passes it onto functionB</li>
<li>As functionA completes, it carries onto execute functionB</li>
</ul>
The difference is very subtle, however significant for thread context switching overheads.<br />
<br />
Note: in my naive understanding of functional programming, I believe the first approach can be considered turning each function into an Actor, while the second approach is a Continuation (continuation passing style).<br />
<br />
Anyway, before misunderstanding too much of the functional programming literature, the problem with the first approach is excessive thread context switching. If the higher order function is a different executor to it's composed functions, it creates two thread context switches for every composed function. The execution would be: <br />
<ol>
<li>Higher order function executes</li>
<li>Invokes composed function on another thread</li>
<li>Result returned to higher order function that thread context switches back to itself</li>
<li>Invokes next composed function on another thread (possibly the same thread required for step 2)</li>
</ol>
The thread context switch that happens in step 3 is not really required. Furthermore, the cost of switching the thread would be more than the few operations to pass the result of the first function to the second function.<br />
<br />
Note: I refer to thread context switching overheads assuming threads need to be scheduled in to handle each part. However, even if threads were running continuously on separate cores, there is overheads in having to get the messages between the threads.<br />
<br />
There is also a second problem of exceptions. Yes, I understand exceptions are not very functional, however I'll come to this later in regards to composition.<br />
<br />
So if we take approach 2 of continuations, then the execution would be as follows:<br />
<ol>
<li>Higher order function executes</li>
<li>Invokes composed functionA on another thread (passing in the next composed functionB)</li>
<li>On result, the composed functionA continues with the next composed functionB</li>
</ol>
We have eliminated the extra context switch in the first approach by letting the composed functions continue on with each other.<br />
<br />
Now this is not overly special. This is just Continuation Passing Style with the ability to execute the continuation with the implicit thread or delegating to a different thread. In doing so, we try to use the implicit thread as much as possible to reduce threading overheads. However when functions have different execution characteristics (such as blocking I/O, expensive CPU computations) we swap threads to enable appropriate execution of the functions to keep the overall application performant.<br />
<br />
Another way of thinking about this threading is to consider the threads running on separate cores. The first approach is very much synchronous communication. Composed function is invoked and the higher order function effectively waits until the result is available. Continuations, on the other hand, are more akin to asynchronous communication. Higher order function triggers the composed function and then is free to continue other functions. The composed function will itself continue with the next composed function.<br />
<br />
But continuations do not come easily.<br />
<br />
Continuation passing has implications for the function signature, as we must pass the next continuation into all functions. This now has our functions looking like this:<br />
<br />
<pre><code class="language-scala"> type Continuation = (Any) => Unit
def function(executorLocator: ExecutorLocator, parameters: Array[Any], continuation: Continuation)
</code></pre>
<br />
Now might I dare say there is more than one outcome to a function - well to me anyway. Yes, we could return a data type defining both success and error. Case statements then handle these various outcomes. However, for each new error type we're having to add new case statement handling. This reminds me of reflection problems of having to interrogate for each error type. Personally, I like to handle these outcomes separately.<br />
<br />
Rather than combining the result and error into the one next continuation, we can provide a continuation for each. In my understanding, this is not too different to try/catch blocks (except that we can now execute the catch block with the implicit thread or different thread). In other words, we provide multiple continuations:<br />
<br />
<pre><code class="language-scala"> def function(executorLocator: ExecutorLocator, parameters: Array[Any],
successfulContinuation: Continuation,
errorOneContinuation: Continuation,
errorTwoContinuation: Continuation)
</code></pre>
<br />
But why stop there. We can also have different paths through the function for say if statements. If condition is true follow the first continuation, else follow the second continuation.<br />
<br />
<pre><code class="language-scala"> def function(executorLocator: ExecutorLocator, parameters: Array[Any],
trueContinuation: Continuation,
falseContinuation: Continuation,
errorOneContinuation: Continuation,
errorTwoContinuation: Continuation)
</code></pre>
<br />
This is starting to blow out the function signature again, especially when composing into higher order functions that have to handle many exceptions. This is also the reason I tend to find many frameworks are moving away from checked exceptions. However, with first class procedures, we very much like checked exceptions (though this is probably not as you typically know them). But we'll come to this soon.<br />
<br />
So to avoid the signature blow out, let's do what we did with the choice of executor and wrap the continuation decision into a function. For now, let's assume we can have some key to aid the function to determine the appropriate continuation. This function would look as follows:<br />
<br />
<pre><code class="language-scala"> type ContinuationLocator = (Function, Any) => Continuation
</code></pre>
<br />
This then turns all our functions into the following:<br />
<br />
<pre><code class="language-scala"> def function(
executorLocator: ExecutorLocator,
parameters: Array[Any],
continuationLocator: ContinuationLocator)
</code></pre>
<br />
So now we have this very flexible execution model than minimises the thread context switching.<br />
<br />
However, how do we implement the executorLocator and continuationLocator functions?<br />
<br />
Well the naming of the functions is deliberate, as they follow the ServiceLocator pattern. Given a key provide back the dependency. However, in this case, it is not an object but rather an executor for thread choice and continuation for invoking the next function.<br />
<br />
Yay, we can now go create key/value configuration for every function in the system. Well, maybe not.<br />
<br />
This granularity of configuration ends up being a nightmare. I can certainly say my first versions of implementing first class procedures showed this very much to be the case. Plus given we have an assumed key to identify the continuation, how do we know we have every continuation configured for a complete system? In other words, how can we make this compile safe?<br />
<br />
To solve this problem, we do what we typically always do in software, add more indirection.<br />
<br />
Huh, more dynamic indirection to create a type safe compiled solution? Well, yes.<br />
<br />
To explain how indirection has helped, let's start with the Continuation Injection.<br />
<br />
Firstly, we are going to give the function state (or possibly better described as meta-data). Arguably this is potentially turning the function into an object, but I'm going to avoid trying to relate things to the literature right now and focus on how the first class procedure has evolved.<br />
<br />
So we now have a wrapping object:<br />
<br />
<pre><code class="language-scala"> class ManagedFunction(
val logic: Function,
val continuations: Map[Any, Continuation])
</code></pre>
<br />
So we've associated the continuations to the function, but this really is only a dynamic map based on key. Therefore, to be compile safe, we need to give the key some meaning the compiler/framework can understand.<br />
<br />
Well to do this, let's go back to the exploded function signature:<br />
<br />
<pre><code class="language-scala"> def function(parameters: Array[Any],
trueContinuation: Continuation,
falseContinuation: Continuation)
</code></pre>
<br />
Given the parameters are always ordered, we can use the index of the continuation as the key. This has the ManagedFunction look as follows:<br />
<br />
<pre><code class="language-scala"> class ManagedFunction(
val logic: Function,
val continuations: Map[Any, Continuation]) {
def cont(key: Any): Continuation = continuations.get(key) match { case Some(cont) => cont }
def run(parameters: Array[Any]) = logic(parameters ++ Array(cont(1), cont(2)))
}
</code></pre>
<br />
Now, I mentioned first class procedures actually like using checked exceptions. The reason is that the checked exception is stated on the signature. This would look like:<br />
<br />
<pre><code class="language-java"> function(Object[] paramaeters) throws ErrorOne, ErrorTwo;
</code></pre>
<br />
Checked exceptions are not ordered, but their types are unique. Therefore, we can use the checked exception's type as the key. This now turns the ManagedFunction into the following:<br />
<br />
<pre><code class="language-scala"> class ManagedFunction(
val logic: Function,
val continuations: Map[Any, Continuation]) {
def cont(key: Any): Continuation = continuations.get(key) match { case Some(cont) => cont }
def run(parameters: Array[Any]) = {
try {
logic(parameters ++ Array(cont(1), cont(2)))
} catch {
case ex: Throwable => cont(ex.getClass())(ex)
}
}
}
</code></pre>
<br />
Now, to make compile/framework safe, we provide a function that produces the required list of keys for the logic function:<br />
<br />
<pre><code class="language-scala"> def extractContinuations(logic: Function): Array[Any] = {
var parameterIndex = 0
extractParameterTypes(logic)
.filter((parameterType) => classOf[Continuation].isAssignableFrom(parameterType)).map((paramContinuation) => { parameterIndex += 1; parameterIndex }) ++
extractExceptionTypes(logic)
}
</code></pre>
<br />
The compiler/framework will then confirm that configuration mappings are provided for each key. This allows validating that all continuations are configured for the function to operate. Furthermore, doing this across all ManagedFunction instances within the application, we can confirm a complete configured application. We now have compile/framework startup safe validation that all continuations are configured.<br />
<br />
However, now we are having problems of passing state between the functions contained within the ManagedFunction. As only one argument can be passed with the continuation, how can a function have more than one parameter?<br />
<br />
Ideally, we want to have each ManagedFunction have the following run method:<br />
<br />
<pre><code class="language-scala"> abstract class ManagedFunction {
def run(parameter: Any) // not, parameters: Array[Any]
}
</code></pre>
<br />
So, how can we provide the additional parameters for the function?<br />
<br />
Before answering this, we need to consider how the first continuation is triggered to start the chain of ManagedFunction executions. As the application is now being realised as a mapping of continuation to ManagedFunctions, we need means to trigger a continuation from outside a ManagedFunction.<br />
<br />
Well, why can't we give objects continuations?<br />
<br />
We can create a ManagedObject that contains continuations:<br />
<br />
<pre><code class="language-scala"> class ManagedObject(
@Inject val continuationOne: Continuation,
@Inject val continuationTwo: Continuation) {
// ... object methods
}
</code></pre>
<br />
This now allows objects to trigger logic. Why is this useful? Well, for example, we can have a HTTP socket listener object that receives a request and services the request by invoking a continuation. Further ManagedFunction instances will then use details of the request, to route it via continuations to appropriate handling ManagedFunction instances to then service the request.<br />
<br />
The HTTP example actually points us to a design pattern already solving the issue of multiple parameters for a function. A typical thread-per-request web server has a request, session and application context. Now let's ignore session and application contexts as they are not concurrency safe. It is the request context pattern that helps us.<br />
<br />
A request context allows passing objects between controllers and view rendering components. What are the controllers and view renders? They are snippets of logic that take in a request scope to access/mutate the request scope to capture enough state to provide a response (with possible side effects of saving state in databases, logging details, etc).<br />
<br />
These snippets of logic fit well into the ManagedFunction, with request scopes created for each continuation tree invoked from a ManagedObject. ManagedObjects are created in the application that are hooked into the network of continuations to ManagedFunctions. When the ManagedObject receives an event (HTTP request, queue message, etc), it does two things: <br />
<ol>
<li>Starts a new request scope </li>
<li>Triggers the first continuation with the scope that carries through for all further continuations triggered</li>
<li> ManagedFunctions can now grab their required parameters from the scope</li>
</ol>
This can be taken further to include dependency injection. Rather than the ManagedFunction being responsible for managing the request scope, the request scope objects are provided through dependency injection. This is the following dependency context for the ManagedFunction:<br />
<br />
<pre><code class="language-scala"> type ServiceLocator = String => Any
class DependencyContext(val serviceLocator: ServiceLocator) {
val objects = scala.collection.mutable.Map[String, Any]()
def getObject(name: String) = {
objects.get(name) match {
case Some(obj) => obj
case None => {
val obj = serviceLocator(name)
objects(name) = obj
obj
}
}
}
}
</code></pre>
<br />
Side benefit of providing Dependency Context is that we can re-use existing Dependency Injection frameworks for managing objects. For example, the ServiceLocator can be a Spring BeanFactory. Furthermore, we can also dependency inject ManagedObject implementations to allow objects to maintain state, but also trigger continuations in the background (e.g. background polling for JWT key changes in providing JWT authentication state).<br />
<br />
The ManagedFunction now becomes:<br />
<br />
<pre><code class="language-scala"> type ContinuationFactory = DependencyContext => Continuation
class ManagedFunction(
val logic: Function,
val parameterScopeNames: List[String],
val continuations: Map[Any, ContinuationFactory]) {
def obj(index: Int, context: DependencyContext): Any = context.getObject(parameterScopeNames(index))
def cont(key: Any, context: DependencyContext): Continuation = continuations.get(key) match { case Some(factory) => factory(context) }
def run(parameterFromContinuation: Any, context: DependencyContext) = {
try {
logic(Array(parameterFromContinuation, obj(1, context), obj(2, context), cont(1, context), cont(2, context)))
} catch {
case ex: Throwable => cont(ex.getClass(), context)(ex)
}
}
}
</code></pre>
<br />
To populate the scope names, we can again use reflection on the logic signature. However, rather than having to provide explicit configuration, we can use auto-wire configuration based on parameter type and possible qualifier. This then becomes normal dependency injection for constructors, except that we are injecting into the logic function.<br />
<br />
We can now have database connections, HTTP clients, etc provided to the logic, however it does not answer the problem of passing state across the continuation boundaries.<br />
<br />
To solve passing state, we just create a state object. This object acts much like a variable. It's value can be set and retrieved. However, this introduces mutability and timing concerns regarding the flow of continuations. It is unclear on whether a ManagedFunction is only safely accessing the variable's value, or is unsafely mutating the variable. Therefore, for variables we provide additional support within the ManagedFunction to identify the use of the variable.<br />
<br />
For variable state objects, we allow the ManagedFunction to use various interfaces to identify the nature of using the variable. This allows the following interfaces for a variable state:<br />
<br />
<pre><code class="language-scala"> trait Out[T] { def set(value: T) }
trait In[T] { def get(): T }
trait Var[T] extends Out[T] with In[T]
</code></pre>
<br />
ManagedFunctions can then use the appropriate interface to identify their intention on the state of the variable.<br />
<br />
Note that it is now possible to traverse the graph from ManagedObject continuations to confirm variable state outputs of ManagedFunctions are always upstream of respective inputs. This creates an ability for compile safe state generation. Furthermore, if all objects loaded to scope variables are immutable it allows reasoning for identifying the ManagedFunction producing incorrect state (just look for the ManagedFunctions requiring the Out of the variable).<br />
<br />
What this now also provides is multiple inputs and multiple outputs. Composition is no longer derived by output of one function being passed as input to the next function. State is maintained in scope with ManagedFunctions pulling/pushing state as appropriate to the scope. Continuations are now separated from having to be concerned with all the state needed to invoke a ManagedFunction.<br />
<br />
Now, the above implementation assumes some order of parameters followed by continuations in invoking the logic. As this information is reflectively retrieved from the logic function, the order is not necessary. We can then have a ManagedFunction look as follows:<br />
<br />
<pre><code class="language-scala"> class ManagedFunction(
val logic: Function,
val parameterScopeNames: List[String],
val continuations: Map[Any, ContinuationFactory]) {
def obj(index: Int, context: DependencyContext): Any = context.getObject(parameterScopeNames(index))
def cont(key: Any, context: DependencyContext): Continuation = continuations.get(key) match { case Some(factory) => factory(context) }
def run(parameterFromContinuation: Any, context: DependencyContext) = {
var continuationIndex = 0
var objectIndex = 0
val arguments = extractParameterTypes(logic).map(_ match {
case p if p.isAnnotationPresent(classOf[Parameter]) => parameterFromContinuation
case c if classOf[Continuation].isAssignableFrom(c) => cont({ continuationIndex += 1; continuationIndex }, context)
case _ => obj({ objectIndex += 1; objectIndex }, context)
})
try {
logic(arguments)
} catch {
case ex: Throwable => cont(ex.getClass(), context)(ex)
}
}
}
</code></pre>
<br />
Notice that the return value from the function (logic) is no longer necessary. Hence, why we're considering this "first class procedures".<br />
<br />
This can then be represented as follows:<br />
<br />
<pre><code class="language-scala"> class ManagedFunction(
val procedure: Array[Any] => Unit,
val parameterScopeNames: List[String],
val continuations: Map[Any, ContinuationFactory]) {
def obj(index: Int, context: DependencyContext): Any = context.getObject(parameterScopeNames(index))
def cont(key: Any, context: DependencyContext): Continuation = continuations.get(key) match { case Some(factory) => factory(context) }
def run(parameterFromContinuation: Any, context: DependencyContext): Unit = {
var continuationIndex = 0
var objectIndex = 0
val arguments = extractParameterTypes(procedure).map(_ match {
case p if p.isAnnotationPresent(classOf[Parameter]) => parameterFromContinuation
case c if classOf[Continuation].isAssignableFrom(c) => cont({ continuationIndex += 1; continuationIndex }, context)
case _ => obj({ objectIndex += 1; objectIndex }, context)
})
try {
procedure(arguments)
} catch {
case ex: Throwable => cont(ex.getClass(), context)(ex)
}
}
}
</code></pre>
<br />
So we've provided composition of logic with state management, but we've not solved the original implicit thread problem that sparked this.<br />
<br />
To solve specifying explicit threads, we need to implement the ExecutorLocator. This is achieved by looking at the parameter types of the function. As all state (objects) are now injected from the DependencyContext, we can determine the execution characteristics from the parameters. In other words, if the logic depends on a Database connection, it is likely to be making blocking calls. Therefore, we can use the parameter types to implement the ExecutorLocator:<br />
<br />
<pre><code class="language-scala"> class ManagedFunction(
val procedure: Array[Any] => Unit,
val parameterScopeNames: List[String],
val continuations: Map[Any, ContinuationFactory],
val executorConfiguration: Map[Class[_], Executor]) {
def obj(index: Int, context: DependencyContext): Any = context.getObject(parameterScopeNames(index))
def cont(key: Any, context: DependencyContext): Continuation = continuations.get(key) match { case Some(factory) => factory(context) }
def executorLocator(): Executor = {
var executor: Executor = (logic, arguments) => logic(arguments) // default executor is synchronous (implicit thread)
extractParameterTypes(procedure).map((parameterType) => executorConfiguration.get(parameterType) match {
case Some(e) => { executor = e; e } // matched so override
case None => executor
})
executor
}
def run(parameterFromContinuation: Any, context: DependencyContext): Unit = {
var continuationIndex = 0
var objectIndex = 0
val arguments = extractParameterTypes(procedure).map(_ match {
case p if p.isAnnotationPresent(classOf[Parameter]) => parameterFromContinuation
case c if classOf[Continuation].isAssignableFrom(c) => cont({ continuationIndex += 1; continuationIndex }, context)
case _ => obj({ objectIndex += 1; objectIndex }, context)
})
executorLocator()((arguments) => {
try {
procedure(arguments)
} catch {
case ex: Throwable => cont(ex.getClass(), context)(ex)
}
}, arguments)
}
}
</code></pre>
<br />
This enables choice of Executor to be managed within configuration. This separates it from concerns of composition and state management.<br />
<br />
And now you are up to speed with the general concepts behind the first class procedure.<br />
<br />
Though, do note that the actual implementation uses a lot more memoization, as function signatures are static allowing the reflection to be done at compile/startup time.<br />
<br />
Furthermore, the overall effect is that higher order functions do not need to provide all arguments to call the function (procedure). The control is inverted so configuration and the procedure itself defines what is injected into it. Higher order composition need only use the continuations to invoke the first class procedures.<br />
<br />
Plus, I find it lifts a constraint in functional programming of having to fit all results through the small key hole of the function's return type. The return type of the function needs to provide success and error details, and is coupled to have to pass this through the chain of composed functions. First class procedures, via variables, decouples this so any upstream procedure can output the value for any downstream procedure to consume. Furthermore, checked exceptions continue error flows to remove this from function return types (output variable types).<br />
<br />
There are also other concepts built on first class procedures, such as:<br />
<ul>
<li>process, thread, function scoped dependency contexts for concurrency/parallel processing</li>
<li>higher order compositions (Sections)</li>
<li>thread affinity and other thread management (via Executive)</li>
<li>providing context for state, such as transactions (Governance)</li>
<li>additional ManagedFunctions inserted into flows similar to aspects (Administration)</li>
</ul>
However, this article is focused on the first class procedure and is already long enough.<br />
<br />
So, in conclusion, the first class procedure is applying inversion of control to the function to inject in state, continuations and thread (via Executor). This means the first class procedure no longer requires composition via return values of the function. This makes it significantly easier to weave impure/pure functionality together. Furthermore, it allows execution strategies for the application to be configured in at deployment time.<br />
<br />
And to see all this in action, please see the <a href="https://sagenschneider.blogspot.com/2019/04/oo-functional-imperative-reactive.html" target="_blank">first article</a>.<br />
<br />
For more information, see this paper <a href="http://doi.acm.org/10.1145/2739011.2739013" target="_blank">OfficeFloor: using office patterns to improve software design</a> (free download <a href="http://www.officefloor.net/about.html" target="_blank">here</a>). <br />
<br />Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-88581790135718087362019-04-27T22:51:00.002-07:002019-04-30T21:55:19.107-07:00OO Functional Imperative Reactive weaved togetherThis is first of a two part article to discuss how different paradigms in programming can be weaved together seamlessly via the "First Class Procedure", a term I'm using to best describe the concept. <br />
<br />
The working code in this article demonstrates how you can seamlessly weave together the following to service a request:<br />
<ol>
<li>Validate a request (on socket event loop thread).</li>
<li>Start a transaction and register the request in the database. This will be on another thread to avoid halting the socket event loop thread.</li>
<li>Make reactive calls to pull in data from other services.</li>
<li>Run some functional code to work out the standard deviation on service times.</li>
<li>Undertake alternate flows to handle special cases (including handling exceptions). Then if no exceptions causing rollback, store results in the database. This again is on a different thread to not tie up the reactive event loop thread.</li>
<li>Send the response after committing the transaction</li>
</ol>
This allows you to use the programming paradigm best suited to the various problems at hand. Note the request servicing in the demonstration is arbitrary. The focus is on showing how the various programming paradigms can be weaved together.<br />
<br />
Now to write a complete description of how this works with the first class procedure is beyond a single article. There are many patterns used together to enable the composition through first class procedures. Therefore, I'm going to provide an introduction to first class procedures in two parts:<br />
<ul>
<li>This article to demonstrate with working code how flexible and easy composition is with first class procedures</li>
<li><a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">Next article</a> to provide an explanation more closely aligned to the theory on how the first class procedure has evolved to its current understanding</li>
</ul>
We'll start with some simple examples and then get to the more interesting above case of weaving multiple programming paradigms together.<br />
<br />
<h2>
First class procedure</h2>
<h3>
Simple event loop</h3>
The following first class procedure services a REST request. This will be run on the HTTP socket event loop thread.<br />
<br />
<pre><code class="language-java">public void service(ObjectResponse<ServicedThreadResponse> response) {
response.send(new ServicedThreadResponse(Thread.currentThread().getName(), "Event", System.currentTimeMillis()));
}
</code></pre>
<br />
<h3>
Simple thread-per-request</h3>
The following first class procedure services a REST request by pulling a value from the database and sending it in the response. This will be run by a separate thread pool.<br />
<br />
<pre><code class="language-java">public void service(ServicedThreadRequest request, ThreadPerRequestRepository repository, ObjectResponse<ServicedThreadResponse> response) {
int identifier = request.getIdentifier() % 10;
ThreadPerRequest entity = repository.findById(identifier).get();
response.send(new ServicedThreadResponse(Thread.currentThread().getName(), entity.getName(), System.currentTimeMillis()));
}
</code></pre>
<br />
<br />
The distinction of thread to use will be discussed later. However, for now notice that a Spring Repository is used by only the thread-per-request first class procedure.<br />
<br />
<h2>
First Class Procedures weaved together</h2>
Ok, the above is little boring. We've seen this in web application servers before. Show us something interesting!<br />
<br />
To show something more interesting we are going to weave first class procedures together to achieve the example detailed at the start of this article.<br />
<br />
Each step in the request servicing is implemented as a first class procedure. We'll address each first class procedure in the order specified.<br />
<br />
<h3>
Validate request (on socket event loop)</h3>
This is simple validation that the request is correct. As it is straight forward logic, we use the thread of the socket event loop. This way we don't have to pay overheads of a thread context switch and threading overheads to reject invalid requests. The code is as follows:<br />
<br />
<pre><code class="language-javascript">const HttpException = Java.type("net.officefloor.server.http.HttpException");
const Integer = Java.type("java.lang.Integer")
function validate(identifier, requestIdentifier) {
if (Number(identifier) <= 0) {
throw new HttpException(422, "Invalid identifier");
}
requestIdentifier.set(Integer.valueOf(identifier))
}
validate.officefloor = [
{ httpPathParameter: "identifier" },
{ out: Integer },
{ next : "valid" }
];
</code></pre>
<br />
Note that the validation is written in JavaScript. This is so that the client side JavaScript validation rules can be re-used to validate requests to ensure consistency between client and server.<br />
<br />
The <span style="font-family: "courier new" , "courier" , monospace;">officefloor</span> attribute added to the function provides meta-data. This is necessary, as JavaScript does not provide the strongly typed information required of first class procedures.<br />
<br />
<h3>
Imperative to register request in database</h3>
After validation, the request identifier is registered in the database. This also creates a unique number for the request based on an IDENTITY column in the database.<br />
<br />
<pre><code class="language-java">@Next("registered")
public static void registerRequest(@Val int requestIdentifier, WeavedRequestRepository repository, Out<WeavedRequest> weavedRequest) {
WeavedRequest entity = new WeavedRequest(requestIdentifier);
repository.save(entity);
weavedRequest.set(entity);
}
</code></pre>
<br />
<h3>
Reactive</h3>
The next is some Reactive code to concurrently call the two REST end points detailed at the start of this article (simple event loop and simple thread-per-request). Because we are using Reactive we can call them concurrently to improve performance.<br />
<br />
Note that while waiting on the responses, the flow is effectively idle with threads servicing other functionality. This is asynchronous handling so that threads are not tied up waiting. Once both sets of results come back, they notify the respective asynchronous flow to continue processing.<br />
<br />
<pre><code class="language-java">private final static String URL = "http://localhost:7878/{path}";
@Next("useData")
public static void retrieveData(WebClient client,
AsynchronousFlow eventLoopFlow, @EventLoopResponse Out<ServicedThreadResponse> eventLoopResponse,
@Val WeavedRequest request, AsynchronousFlow threadPerRequestFlow, @ThreadPerRequestResponse Out<ServicedThreadResponse> threadPerRequestResponse) {
Flux.range(1, 10)
.map((index) -> client.get().uri(URL, "event-loop").retrieve().bodyToMono(ServicedThreadResponse.class))
.flatMap((response) -> response).collectList().subscribe((responses) -> eventLoopFlow.complete(
() -> eventLoopResponse.set(responses.stream().toArray(ServicedThreadResponse[]::new))));
Flux.range(1, 10)
.map((index) -> client.post().uri(URL, "thread-per-request").contentType(MediaType.APPLICATION_JSON)
.syncBody(new ServicedThreadRequest(request.getId())).retrieve()
.bodyToMono(ServicedThreadResponse.class))
.flatMap((response) -> response).collectList().subscribe((responses) -> threadPerRequestFlow.complete(
() -> threadPerRequestResponse.set(responses.stream().toArray(ServicedThreadResponse[]::new))));
}
</code></pre>
<br />
By now you may be noticing the <span style="font-family: "courier new" , "courier" , monospace;">Out</span>/<span style="font-family: "courier new" , "courier" , monospace;">@Val</span> combinations. This is how values can be passed from one first class procedure to another first class procedure. Note that if type for different values is the same, a qualifier can be used to distinguish them. The rest of the arguments are provided from dependency injection (in this case Spring).<br />
<br />
<h3>
Functional</h3>
Next the reactive responses are provided to Scala functional code to determine the standard deviation of service times.<br />
<br />
<pre><code class="language-scala">def mean(timestamps: Iterable[Long]): Double = timestamps.sum.toDouble / timestamps.size
def variance(timestamps: Iterable[Long]): Double = {
val avg = mean(timestamps)
timestamps.map(timestamp => math.pow(timestamp.toDouble - avg, 2)).sum / timestamps.size
}
def stdDev(timestamps: Iterable[Long]): Double = math.sqrt(variance(timestamps))
@Next("use")
def standardDeviation(@EventLoopResponse @Val eventLoopResponses: Array[ServicedThreadResponse], @ThreadPerRequestResponse @Val threadPerRequestResponses: Array[ServicedThreadResponse]): Double =
stdDev((eventLoopResponses ++ threadPerRequestResponses).map(response => response.getTimestamp))
</code></pre>
<br />
Note that a library could be used to reduce this code. However, we've done this to demonstrate how functional code can be integrated into first class procedures.<br />
<br />
<h3>
Flow control</h3>
The next first class procedure triggers a flow to handle special cases. Should there be no issues with the special cases, then it stores the standard deviation in the database.<br />
<br />
<pre><code class="language-java">@FlowInterface
public static interface Flows {
void handleSpecialCases(FlowSuccessful callback);
void stored();
}
public static void store(@Parameter double standardDeviation, Flows flows, @Val WeavedRequest request, WeavedRequestRepository repository, Out<RequestStandardDeviation> stDevOut) {
flows.handleSpecialCases(() -> {
request.setRequestStandardDeviation(new RequestStandardDeviation(standardDeviation, request));
repository.save(request);
stDevOut.set(request.getRequestStandardDeviation());
flows.stored();
});
}
</code></pre>
<br />
The handling of the special cases is by the following first class procedure.<br />
<br />
<pre><code class="language-java">public static void handleSpecialCase(@Val WeavedRequest request) throws WeavedRollbackException, WeavedCommitException {
switch (request.getRequestIdentifier()) {
case 3:
throw new WeavedRollbackException(request);
case 4:
throw new WeavedCommitException(request);
}
}
</code></pre>
<br />
<h3>
Touch of exception handling</h3>
The two exception handling first class procedures are as follows.<br />
<br />
<pre><code class="language-java">public static void handle(@Parameter WeavedRollbackException exception, ObjectResponse<WeavedErrorResponse> response) {
WeavedRequest request = exception.getWeavedRequest();
response.send(new WeavedErrorResponse(request.getRequestIdentifier(), request.getId()));
}
public static void handle(@Parameter WeavedCommitException exception, WeavedRequestRepository repository, ObjectResponse<WeavedErrorResponse> response) {
WeavedRequest request = exception.getWeavedRequest();
request.setWeavedError(new WeavedError("Request Identifier (" + request.getRequestIdentifier() + ") is special case", request));
repository.save(request);
response.send(new WeavedErrorResponse(request.getRequestIdentifier(), request.getId()));
}
</code></pre>
<br />
The second handler works within the transaction, so includes further data stored in the database.<br />
<br />
Note that due to first class procedure composition not requiring the caller to catch exceptions, checked exceptions are embraced. We consider checked exceptions very useful information in flow composition. However, the distinction is that it should not be the caller's concern but rather the flow's concern. To me this is a big difference and stops the catch and log exception handling problem. Exception handling is now a separate concern that can be coded in afterwards.<br />
<br />
<h3>
Successful response</h3>
On successful storage of the request details in the database, the following first class procedure sends the response.<br />
<br />
<pre><code class="language-java">public void send(@Val WeavedRequest request, @Val RequestStandardDeviation standardDeviation, @EventLoopResponse @Val ServicedThreadResponse[] eventLoopResponse,
@ThreadPerRequestResponse @Val ServicedThreadResponse[] threadPerRequestResponse, ObjectResponse<WeavedResponse> response) {
response.send(new WeavedResponse(request.getRequestIdentifier(), request.getId(), eventLoopResponse, threadPerRequestResponse, standardDeviation.getStandardDeviation()));
}
</code></pre>
<br />
<h3>
Kotlin for some OO</h3>
Oh, and just for a little bit more polyglot fun, the OO objects used to represent the JSON request/responses are the following.<br />
<br />
<pre><code class="language-kotlin">@HttpObject
data class ServicedThreadRequest(val identifier: Int)
data class ServicedThreadResponse(val threadName: String, val lookupName: String, val timestamp: Long)
data class WeavedErrorResponse(val requestIdentifier: Int, val requestNumber: Int)
data class WeavedResponse(val requestIdentifier: Int
, val requestNumber: Int
, val eventLoopResponses: Array<servicedthreadresponse>
, val threadPerRequestResponses: Array<servicedthreadresponse>
, val standardDeviation: Double)
</servicedthreadresponse></servicedthreadresponse></code></pre>
<br />
<h3>
Proving it works</h3>
The following is a test to confirm the flow of first class procedures services the request.<br />
<br />
<pre><code class="language-java">public static final SpringRule spring = new SpringRule();
public static final OfficeFloorRule officeFloor = new OfficeFloorRule();
@ClassRule
public static final RuleChain ordered = RuleChain.outerRule(spring).around(officeFloor);
@Rule
public final HttpClientRule client = new HttpClientRule();
private static final ObjectMapper mapper = new ObjectMapper();
static {
mapper.registerModule(new KotlinModule());
}
@Test
public void confirmWeavedTogether() throws Exception {
HttpResponse response = this.client.execute(new HttpPost(this.client.url("/weave/1")));
assertEquals("Should be successful", 200, response.getStatusLine().getStatusCode());
WeavedResponse body = mapper.readValue(EntityUtils.toString(response.getEntity()), WeavedResponse.class);
WeavedRequest entity = spring.getBean(WeavedRequestRepository.class).findById(body.getRequestNumber()).get();
assertNotNull("Should have standard deviation stored", entity.getRequestStandardDeviation());
}
</code></pre>
<br />
<h3>
Weaving together</h3>
The following diagram is the configuration to weave the above first class procedures together.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgreNu6dNg0aeAxDeYVCSm2JqY_rLepvqh5DX581AFUSwTMfI7wc6g31Dkgx0b7MZCRpPRzYx0cBEh-orKobYrlt9I9XB48_zEwYB6Daz5XzPnQOIx4Vh1JFSodm70MM-ohJEE6ig9AFg/s1600/WeaveConfiguration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="538" data-original-width="1600" height="214" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgreNu6dNg0aeAxDeYVCSm2JqY_rLepvqh5DX581AFUSwTMfI7wc6g31Dkgx0b7MZCRpPRzYx0cBEh-orKobYrlt9I9XB48_zEwYB6Daz5XzPnQOIx4Vh1JFSodm70MM-ohJEE6ig9AFg/s640/WeaveConfiguration.png" width="640" /></a></div>
<br />
This is the only configuration/code necessary to compose the first class procedures together. Notice the names represent the first class procedure names and their respective meta-data.<br />
<br />
What this means, is check the port on the all the calls and tests. Yes, everything you see above is running off the one port. Yep, you don't have to choose between a framework that provides only thread-per-request or single threaded event loops. This is because of the execution strategy provided by Thread Injection of first class procedures.<br />
<br />
<h2>
Thread Injection</h2>
The threading configuration is actually the following:<br />
<br />
<pre><code class="language-xml"><teams>
<team source="net.officefloor.frame.impl.spi.team.ExecutorCachedTeamSource" type="org.springframework.data.repository.CrudRepository" />
</teams>
</code></pre>
<br />
Here we flag all procedures requiring a Spring Repository to be executed by a thread pool. Remember I said keep note of use of Spring Repository. Well the above configuration has any first class procedure requiring a Spring Repository executed by the configured thread pool. Note that thread pools are named teams, due to the modeling origins of first class procedures coming from Offices.<br />
<br />
Therefore, looking at the flow again, the thread execution is as follows: <br />
<ol>
<li>Validate uses the thread of the socket listener event loop</li>
<li>Register request uses a Spring Repository, so execution is swapped to a thread from the configured thread pool</li>
<li>This thread carries onto trigger the asynchronous reactive calls</li>
<li>The reactive event loop thread then invokes the callbacks. As the Scala code is quick to execute, the reactive event loop thread carries on to execute the Scala pure function. Here it is deemed that a thread context switch is too much overhead, and it is more efficient to just invoke the highly optimised Scala pure function. However, if we want to separate the Scala function to different thread pool, we can configure in a different thread pool (typically via marker dependency on the first class procedure).</li>
<li>The remaining imperative code has a switch back to a thread from the configured thread pool, as depends on Spring repository. Furthermore, the thread locals between the threads are propagated to each used thread, so the Spring Repository transaction is not lost (i.e. transaction is active for all first class procedures within the transaction bounds).</li>
<li>Response is then sent.</li>
</ol>
Now all the above is configurable via <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">Thread Injection</a>. If we have, for example, more than one synchronous data store, we can create a thread pool to interact with each data store to avoid one slow data store tying up all threads of the application.<br />
<br />
This also means you can configure different threading for different environments without having to change any code.<br />
<br />
<h2>
Disclaimer</h2>
In a real world applications, I would try to avoid so many of the above programming languages together. I'd try to streamline them to just a couple to avoid too many skill sets involved driving up maintenance costs of your application (plus reduces problems for mixed compiling). This is only a demonstration of how OO, Functional, Imperative and Reactive code can all be weaved together with first class procedures. Furthermore, it demonstrates how you can <a href="https://sagenschneider.blogspot.com/2019/03/perils-of-opinionated-frameworks-like.html" target="_blank">write concrete solutions before abstracting</a>.<br />
<br />
Also, as you can see we've had to cover a lot of breadth in each programming paradigm. If the code is not a good representation of the paradigm, we're very happy to take feedback on improvements from those more acquainted with a particular paradigm.<br />
<br />
And if we've missed an important paradigm, please let me know so we can consider including it. When it comes to coding we appreciate diversity to give developers choice. We're trying to tear down fences between the paradigms to have one big happy coding family.<br />
<br />
<h2>
Summary</h2>
We've demonstrated how the first class procedure can weave together polyglot code written in different paradigms to service a request. The code outlined above in the article is all the code required for the application. There is no further weaving code required.<br />
<br />
Furthermore, to avoid the problems of it only works on my machine (in this article), the code for the above is available <a href="https://github.com/sagenschneider/OoFunctionImperativeReactive" target="_blank">here</a>. See the <a href="https://github.com/sagenschneider/OoFunctionImperativeReactive/blob/master/README.md" target="_blank">readme</a> on how to run it.<br />
<br />
For more understanding of what's going on, see the <a href="http://officefloor.net/tutorials/" target="_blank">tutorials</a>, my <a href="https://sagenschneider.blogspot.com/" target="_blank">other articles</a> and in particular my <a href="https://sagenschneider.blogspot.com/2019/04/function-ioc-for-first-class-procedure.html" target="_blank">next article</a>.Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com1tag:blogger.com,1999:blog-274357204559150666.post-87087630728869662932019-04-08T04:16:00.000-07:002019-04-08T04:16:48.198-07:00IT "Floor Plan"OfficeFloor's graphical configuration is inspired from the construction industry's <i>floor plan</i>.<br />
<br />
Now, we did consider auto-wiring flows together based on parameter types between the first class procedures. This is still possible if there is interest. However, we went graphical for another reason that has less to do with the technical problems of the system but more in helping build and maintain the correct system.<br />
<br />
This inspiration came from having been around house construction with my father and later when building my own house. Building a house is definitely not simply putting a slab down and walls up with a roof, possibly with a door to get in and out. There is a lot of engineering going into houses to ensure the foundations are correct, the house is not going to fall over and even on the more advanced side of ensuring it fits with the home owner's style of living.<br />
<br />
Now, I certainly claim no expertise in the house construction industry but they a have tool that made understanding and reasoning about the construction easier:<br />
<br />
<div style="text-align: center;">
Floor Plan</div>
<br />
The floor plan to me was a powerful communication tool within the home construction industry. Now I had some background in construction, but engineering concerns such as house footings, load bearing walls, etc are beyond me. However, around the floor plan we could discuss how the house was to be built.<br />
<br />
Reflecting on my experience of building a house, I could see this discussion working even for those that had not a background around construction. One does not need to be too technical to follow the room layouts and be able to visualise how the house is going to turn out. Then when asking for something difficult (such as moving a load bearing wall), it is reasonably easy for the construction company to explain using the floor plan why that would incur extra costs. Plus this same conversation can be had when renovating the house - something in IT we continually do by enhancing systems.<br />
<br />
Now in this relationship, I saw myself as the business is to information technology. I knew what I wanted out of the house (IT system) and the floor plan helped the communication with the (IT) construction company. I saw the home construction industry having similar problems of non-technical customers wanting something technical, and solved this with the floor plan.<br />
<br />
So it had me ask the question:<br />
<br />
<b>What do we produce in the information technology space to be the "floor plan" of IT systems?</b><br />
<br />
I believe we've tried many approaches, but I find they get lost in the complex, intangible details of IT systems. We've tried model driven designs specific to certain domains with some success, however these become difficult to maintain and enhance. We've used many modelling techniques such as UML and lots of others in the business analysis space, but these are divorced of the code and quickly stale (especially with the Agile approach of building a room at a time). We can even incorporate functional programming as means to demonstrate how code is composed together. However, I as a customer would not be expected to understand engineering mathematics of construction, so why should I be subjected to computing maths.<br />
<br />
The best I've seen is story boards, but this does not convey the complexity of the internals of systems. All too often I hear, <i>it's only a button, why's it cost so much?</i> Now if we could bring out the "floor plan" of the internals of the IT system we could have a conversation around what aspects of the system is needing changes. For example, that's load bearing impacting these rooms (components) of the house (system), so cost to change is going to be expensive.<br />
<br />
Now when I refer to the internals of the system, I'm also not meaning front-end applications that only use the server to store data in databases. For many of these applications, most things are quite tangible in screens to the user. What I'm referring to is more complex server side components servicing the requests that are quite intangible to the user. In other words, the details necessary to explain why adding this new button is 10 times more costly than the button added last week.<br />
<br />
Furthermore, I tend to find most approaches are focused on one-way communication of capturing requirements to convey to technical individuals to build. There is little in going the other way. In other words, in providing understandable information back to the users on why some changes are harder than others.<br />
<br />
This is even evident in Business Process Model and Notation (BPMN) in it becoming an executable specification. This has been great to model business processes for technical people to implement systems. In doing so, I'm finding it starting to incorporate the technical details of UML. This starts becoming very technical and makes it difficult for non-technical individuals to pick up.<br />
<br />
So I reflect on how I convey this information to users, and well the whiteboard with boxes and lines is something I keep drawing. I tend to find drawing boxes representing <i>things</i> with lines indicating flow provides enough visualisation to have a discussion in 5 minutes about why something is easier or harder to change.<br />
<br />
So is there a way to extract the boxes and lines out of the system for this conversation with the user?<br />
<br />
Now to get technical for a moment, OfficeFloor allows composition through continuations. For those not familiar with continuations you can can skip the rest of this paragraph and just know that continuations allow connecting code flow by drawing lines between procedures. For those wanting a little more detail, the state passed by the continuation in OfficeFloor is decoupled from the continuation (state is Dependency Injected into the procedure from <a href="https://sagenschneider.blogspot.com/2019/03/functional-languages-and-reactive.html" target="_blank">Dependency Contexts</a>). This allows the first class procedures of OfficeFloor to be composed together separate of state (<a href="https://sagenschneider.blogspot.com/2019/03/functional-languages-and-reactive.html" target="_blank">Dependency Injection</a>) and execution strategies (<a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">Thread Injection</a>). Therefore, OfficeFloor composition is merely configuring the output continuations of a procedure to the appropriate handling procedure. This can be represented as a graph of nodes (procedures) with connectors (continuations) and directed edges (mapping configuration of continuation to procedure) - hence prime for graphical configuration.<br />
<br />
So armed with first class procedures and means to draw lines between them to control program flow, we have the opportunity to represent the application flow composition as boxes and lines.<br />
<br />
Therefore, when asked why graphical configuration for OfficeFloor. It just made sense to use graphical configuration for ease of communicating the system's "floor plan". This makes it easy for users to understand the system. It also makes it very easy for new developers to pick up the system. This is especially useful when having to work between many micro-services.<br />
<br />
Therefore, OfficeFloor uses it's Continuation Injection graphical configuration to be the "floor plan" to how the IT system is constructed to make communication between user and construction company easier.Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-68831482934644820642019-03-11T02:04:00.000-07:002019-03-14T00:33:08.904-07:00Perils of opinionated frameworks, like Spring Boot. Inverting for opinionated code.We developers like abstraction. Without it, we could not build applications. Our programming disciplines even require that we code to abstractions and avoid coupling our code to detailed implementations.<br />
<br />
However, what is the right abstractions for your application?<br />
<br />
Sadly, the choice of abstractions really comes from our choice of framework. Frameworks are basically abstract solutions that we extend to
solve our problem.<br />
<br />
Unfortunately frameworks, like Spring Boot, come opinionated about
the threading models you use, interfaces you need to extend, possibly
the data repositories applicable and various other assumptions about
your problem space. That's a lot of restrictions before I've even written my first line of code.<br />
<br />
What we really want to do is explore the problem space first. This is what test driven design is all about. We write tests to define what is successful code. Then we implement code to pass those tests. As we go along writing tests to cover off requirements, we subsequently churn out working code for the application. In time we get enough working code to release as the application.<br />
<br />
So this leads me to ask, when do we test the choice of framework?<br />
<br />
<h2>
Opinionated frameworks force abstractions too early in the development process</h2>
Well, I guess we pay very experienced senior people to make this choice. So this choice must be correct. It would not be for reasons like:<br />
<ul>
<li>I (or our company) only know this framework, so we are using it</li>
<li>New shiny with lots of buzz words, we must use it</li>
<li>My CVs a little old, let's try something new</li>
<li>This one is cheaper</li>
<li>Architecture believed what <i>it says on the tin</i></li>
</ul>
Regardless of the reason, the only way to test the framework choice is to build the application with it. And just for those of you who like opinionated frameworks (like Spring Boot), please tell me you write the most risky aspects first. This is so you can quickly discover if the framework's opinions match with your problem.<br />
<br />
Sadly, even if you test with the most risky aspects, finding out the framework decision is wrong can lead to a lot of wasted code. This arguably wastes is a lot of money for the business and can lead to failing projects.<br />
<br />
For example, say we choose Spring Reactive. Yay, we can make concurrent
asynchronous calls out to various micro-services. We can also use the
latest in NoSQL data stores. This was all a great decision. However,
over time we realise we have a small amount of data where integrity of the
data is very important. We find we want to use a relational database
to solve this, and then incorporate JPA on this database for easier
interaction. However, our choice of Spring Reactive has disallowed this
because it requires all I/O to be asynchronous (JPA is synchronous
database calls). Ok, yes, we can use Schedulers, but I seem to be continually doing work arounds for lack of transactions. The data consistency issues are starting to mount up and we're missing deadlines. I'm now in a position of do I throw out all the Reactive code, or do I keep making work arounds hoping it might all hang together. I definitely need to swap jobs before this hits production and we start supporting it. In my next job, I've learnt to use Spring Servlets for this type of problem.<br />
<br />
The
flip side of this could also be easily the case. We start out wanting
Spring Servlet for JPA interaction with a database. However, over time
we realise the database interaction is mostly read-only. What we
really wanted was asynchronous I/O from Spring Reactive to collect data
from multiple micro-services and data stores concurrently. Unfortunately, with our up front Spring Servlet choice, the data collection is just too slow. Our work around is to use async Servlets and spawn threads to make concurrent requests. This worked initially, but over time the load increased. This significantly increased thread counts, resulting in thread scheduling starvation, which resulted in timeouts. I've really got no way to fix this without significant rewrites of the application. In my next job, I've learnt to use Spring Reactive for this type of problem.<br />
<br />
So can look to test the framework without having to throw out all our code?<br />
<br />
<h2>
Inverting framework control</h2>
Dependency Injection went a long way in inverting control. When I write my Servlet handling method, I no longer need to pass in all my dependent objects. I would define dependencies, via <span style="font-family: "courier new" , "courier" , monospace;">@Inject</span>, to have the framework make them available. The framework, subsequently, no longer dictates what objects my implementation can depend on.<br />
<br />
However, there is a lot more to a framework than just the objects. Frameworks will impose some threading model and require me to extend certain methods. While dependency injection provides references to objects, the framework still has to call the methods on the objects to do anything useful. For example, Spring goes along way to make the methods flexible, but still couples you to Reactive or Servlet coding by the required return type from the method.<br />
<br />
As I need the Spring framework to undertake Dependency Injection for my tests, I'm coupled to the particular Spring Servlet/Reactive abstractions before I even write my first line of code. An upfront choice that could be quite costly to change if I get wrong!<br />
<br />
What I really want to do is:<br />
<ol>
<li>Write tests for my implementations (<i>as we are always test driven, of course</i>)</li>
<li>Write my implementations</li>
<li>Wire up my implementations together to become the application</li>
</ol>
Well the first two is very simple:
<br />
<ol>
<li>Write tests calling a method passing in mock objects</li>
<li>Write implementation of the method to pass the test</li>
</ol>
The last becomes very hard. The reason the last becomes very hard is there is no consistent way to call every method. Methods have different names, different parameters, different exceptions, possibly different threading requirements and different return types. What we need is some facade over the methods to make them appear the same.
<br />
<br />
The <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of (Coupling) Control (IoC)</a> provides this facade over the method via the <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">ManagedFunction</a>. The <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">ManagedFunction</a> interface does not indicate what thread to use, what parameters/return types are required, nor what exceptions may be thrown. This is all specified by the contained method implementation. The coupling is inverted so the implementation specifies what it requires.<br />
<br />
This inversion of coupling allows framework decisions to be deferred. As I can have all my methods invoked in a consistent way, I can go ahead and start writing implementations. These implementations may require Reactive coding to undertake asynchronous calls out to different micro-services. Some of these implementations may require using JPA to write to relational databases. I really should not care at the start of building the system. I'm tackling the concrete problems to gain a better understanding of the real problem space. I know my methods can be invoked by the framework via wrapping them in a <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">ManagedFunction</a>. We can deal with determining the <i>right</i> framework later on, once we know more.<br />
<div>
<br /></div>
Actually, this is allowing the implementations to choose the appropriate abstractions to be provided by the framework. My implementations define what objects they require, what other methods they require calling and what thread models they will require. The implementations are, effectively, defining what abstractions are required from the framework. <br />
<br />
Therefore, it is no longer the framework being opinionated. It is your developer code that is allowed to be opinionated.
<br />
<br />
This then allows your implementations to be opinionated about the most appropriate framework to use. No longer do you have to guess the framework based on vague understanding of the problem space. You can see what abstractions your implementations require and make a more informed choice of framework.<br />
<br />
In effect, IoC has deferred choice of the framework to much later in the development process. This is so you can can make the decision much more confidently. And isn't this what Agile says, defer the commitment until the last responsible moment.<br />
<br />
<h2>
Summary</h2>
In summary, why be forced to make too many up front decisions about your application? In choosing the framework, you are making some significant choices is solving your problem space. As frameworks are opinionated, they impose a lot of coupling on your solution.<br />
<br />
Rather, why can't I just start writing solutions to concrete problems and worry about how they fit together later on? This allows me to make choices regarding the appropriate abstractions (and subsequently framework) when I know a lot more about the problem space.<br />
<br />
<a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of (Coupling) Control</a> gives this ability to defer abstraction and framework choices to much later in the development process, when you are more informed to make the decision correctly.
<br />
<br />Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com2tag:blogger.com,1999:blog-274357204559150666.post-23368093618177781652019-03-06T21:39:00.000-08:002019-04-11T06:55:10.639-07:00Inversion of Control (explained non-technically)A design pattern for the <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of Control</a> principle was presented in a <a href="http://doi.acm.org/10.1145/2739011.2739013" target="_blank">paper</a> published in 2015 (a free download is available <a href="http://www.officefloor.net/about.html" target="_blank">here</a>). The premise of the paper was "can we learn something from how businesses organise themselves and translate this into software design improvements?" Basically, businesses have been around a lot longer than software systems. So, how did businesses deal with problems, such as scale, before computers existed?<br />
<br />
So running with this analogy, I looked at how businesses evolve. Businesses don't set out day one to be a Fortune 500. Typically, they start with you in your garage (maybe with a friend). Overtime your business grows and you hire people, assign clearer functional responsibilities and start to scale up your business. Businesses have to do this, while also changing quickly to stay competitive.<br />
<br />
Within software, we have moved from Waterfall to Agile. Waterfall can be considered your set out to build a Fortune 500 company day one approach. Agile, on the other hand, says build only things of value and evolve your system over time. Also, Agile focuses on being quicker to react to change. Therefore, Agile is a lot closer to how businesses grow, evolve and stay competitive.<br />
<br />
Unfortunately, our software architectures have still stayed a "waterfall" top down approach. Architects will produce technology stack diagrams that indicate how the architectural layers of the system work (<i>those technical pictures full of rectangles on top of each other</i>). The nature of these <i>layers</i> is always a bureaucratic control from the top layer to the bottom layer. This is very similar to large companies with many layers of management. So our software architectures force us to design the <i>Fortune 500 company</i> before developers even get to write the first line of code.<br />
<div>
<br /></div>
<div>
Inversion of Control is like empowering employees in a business. Rather than the manager dictating exactly how the employees will work, the manager trusts the employees to undertake the goals of the business. In other words, the employees are in control of how the work gets done. They will decide what help to get (Continuation Injection). They will decide what business resources they require (Dependency Injection). They may decide to escalate issues with the work (Continuation Injection). They may even decide another employee may be better suited to do the work (Thread Injection).</div>
<div>
<br /></div>
<div>
By empowering the employee, we have inverted the control. The employee is now in control of how the work gets done. This is similar to the Inversion of Control in software. The developer is now in control of how they write code. They are not restricted by bureaucratic top down architecture controls from their managers. This allows the developer to evolve the business's software quickly so it may grow and stay competitive.</div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-76723399332032302902019-03-04T01:43:00.000-08:002019-03-19T22:29:59.978-07:00Reactive frameworks "rob Peter to pay Paul"! Avoiding the problem with Dependency ContextsReactive frameworks, typically, align to message driven architectures.<br />
<br />
The problem with building message driven systems, is the message provides the context. The nature of message driven architectures is that the handler of the message is disconnected from the producer of the message. The only information connecting them is the message. Hence, the message needs to provide all the necessary context and data for the handler to process the message.<br />
<br />
This becomes complicated when downstream message handlers require more context (such as transactions). How do you pass a transaction via a message? Yes, we can use XA transactions to suspend and resume transactions but this creates a lot of overhead to the performance and scale these Reactive frameworks are chasing. Furthermore, <a href="http://disq.us/p/1gi31s9" target="_blank">Spring Data even considers transactions not a good fit for reactive</a>.<br />
<br />
So how can we create a Reactive framework that enables context for such things as transactions?<br />
<br />
<h2>
Dependency Contexts</h2>
Well the first problem is co-ordination. Firing off lots of events serviced by different functions in different threads, creates a lot of multi-threading co-ordination. How does one know when to commit the transaction? Or possibly decide to rollback the transaction? Or what if an asynchronous I/O takes too long causing the held transaction to time out. We would be required to monitor all messages and co-ordinate their results to then make a decision on commit / rollback (along with handling further non-application events, such as transaction timeout events). This puts a lot of coding decisions on the developer outside the normal application logic. Gone are the days the developer just threw an exception and the transaction is rolled back.<br />
<br />
So let's bring back order to the event handling chaos. Load the events to a queue and process events in the order they are added to the queue. As requests on the system should be independent, we create a separate queue for each request to keep requests isolated from each other.<br />
<br />
The resulting event loop would look as follows:<br />
<br />
<pre><code class="language-java">
public void startRequest(Function function) {
this.functions.add(function);
}
BlockingQueue<Function> functions = new LinkedBlockingQueue<>();
public void eventLoop() throws InterruptedException {
for (;;) {
// Obtain next function to execute
Function function = this.functions.take();
// Determine if new request (no context)
FunctionContext context = (function instanceof ContextualFunction)
? ((ContextualFunction) function).context
: new FunctionContext();
// Allow for multi-threading in executing
synchronized (context) {
function.doFunction(context);
}
// Register the next function to execute
Function nextFunction = context.functions.pollFirst();
if (nextFunction != null) {
this.functions.add(nextFunction);
}
}
}
public interface Function {
void doFunction(FunctionContext context);
}
public class FunctionContext {
private Deque<Function> functions = new LinkedList<>();
public void triggerFunction(Function function) {
this.functions.add(new ContextualFunction(function, this));
}
}
public class ContextualFunction implements Function {
private final Function delegate;
private final FunctionContext context;
public ContextualFunction(Function delegate, FunctionContext context) {
this.delegate = delegate;
this.context = context;
}
@Override
public void doFunction(FunctionContext context) {
this.delegate.doFunction(context);
}
}</code></pre>
<br />
Ok, a lot of code but it is now doing two things:<br />
<ul>
<li>ordering all functions to be executed sequentially</li>
<li>providing a context that travels with the execution chain of functions</li>
</ul>
<div>
But how do we make use of the FunctionContext to begin and manage the transaction?</div>
<div>
<br /></div>
<div>
We incorporate the <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">ManagedFunction of Invervsion of Control</a> and use a <a href="https://martinfowler.com/articles/injection.html" target="_blank">ServiceLocator</a> to enable storing the dependencies within the context:</div>
<div>
<br /></div>
<div>
<pre><code class="language-java"> public interface ServiceLocator {
// Uses context for transitive dependencies
Object locateService(String serviceName, FunctionContext context);
}
ServiceLocator serviceLocator = ...; // can, for example, wrap Spring BeanFactory
public class FunctionContext {
// ... triggerFunction logic omitted for brevity
private Map<String, Object> contextDependencies = new HashMap<>();
public Object getDependency(String dependencyName) {
// Pull dependency from context cache
Object dependency = this.contextDependencies.get(dependencyName);
if (dependency == null) {
// Not cached, so create new and cache in context
dependency = serviceLocator.locateService(dependencyName, this);
this.contextDependencies.put(dependencyName, dependency);
}
// Return dependency for Function to use
return dependency;
}
}
</code></pre>
</div>
<div>
<br /></div>
<div>
The Functions are now able to use the <span style="font-family: "courier new" , "courier" , monospace;">getDependency("name")</span> method to retrieve the same objects for a request. As the dependency objects are cached within the context, the various Functions involved in servicing the request are able to retrieve the same object.<br />
<br />
Therefore, a transaction can be managed across Functions. The first Function retrieves the Connection and starts the transaction. Further Functions execute, pulling in the same Connection (with transaction established). The final Function in the chain then commits the transaction.<br />
<br />
Should there be a failure, the <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">injected Exception handlers of the ManagedFunction</a> can rollback the transaction. Within thread-per-request architectures, exceptions are thrown by the developer's code typically rolling back the transaction. By having the ManagedFunction injected handlers also rollback the transaction, this reproduces the ease of thread-per-request transaction management for exceptions.<br />
<br />
Furthermore, the exception handlers would clear the FunctionContext queue of Functions. As the transaction has been rolled back, there is no point further executing the remaining Functions. In typical thread-per-request handling, the remaining part of the try block would be skipped. By clearing the FunctionContext queue this mimics skipping the remaining logic and goes straight to the catch block. In the case of ManagedFunction exception handler, this would be triggering a new function to handle the failure.<br />
<br />
But we've just reduced Reactive framework to a single sequence of functions, losing the concurrency it can provide!<br />
<br />
Well beyond making it easier to code now that there is some order in function execution, we can introduce concurrency by spawning another sequence of functions. As the FunctionContext ties the sequence of functions together, we just create a new FunctionContext to enable concurrency. The following code shows this:<br />
<br />
<pre><code class="language-java"> public class FunctionContext {
private Deque<Function> functions = new LinkedList<>();
public void triggerFunction(Function function) {
this.functions.add(new ContextualFunction(function, this));
}
public void spawnNewSequence(Function function) {
this.functions.add(function); // event loop will create new FunctionContext
}
// ... getDependency(...) removed for brevity
}
</code></pre>
<br />
In actual fact, we have just created <i>Threads </i>running on an event loop. The sequence of functions are executed in order just like imperative statements are executed in order by a thread. So we now have <i>Threads</i> without the overheads of a thread-per-request. The dependencies are bound to the context and subsequently the <i>Thread </i>of execution - making them effectively <i>ThreadLocal</i>. As ThreadLocals are thread safe, we now have safe multi-threading functional code.<br />
<br />
As dependencies are effectively <i>ThreadLocal</i> to the sequence of Functions, they can be mutated for the next Function to pick up the change. Yes, immutability better removes developer errors, however this should not be reason to restrict the developer from doing it. This is especially the case if you want to mutate objects via an ORM (e.g. JPA or Spring Repositories) to do updates in the database.<br />
</div>
<div>
<br />
OfficeFloor (<a href="http://officefloor.net/">http://officefloor.net</a>) implements Dependency Contexts in it's <a href="https://sagenschneider.blogspot.com/2019/02/is-spring-reactive-already-obsolete.html" target="_blank">threading models</a>. OfficeFloor, actually, makes this easier to develop by introducing the concept of Governance. Governance does the above transaction management by configuration declaration (much like a <span style="font-family: "courier new" , "courier" , monospace;">@Transaction</span> annotation on a method). However, as OfficeFloor uses graphical configuration, this is done graphically. Rather than annotating the code directly, OfficeFloor graphically marks functions for transaction governance for better code re-use and flexibility in configuring applications. An example of this configuration is as follows:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1f2agI1wjKxt2xFvmnAxb080vYdv3ynPoUIofCofWL_vuJ2WNZCfdzVu1D1pAAnggVXS3-fZR0jz9e9bojgfntdKt5X9mgvYb_dIhRrdli2Jqxsfx0UUXpE1rVm8ejtYUZ4Oz2YHRdg/s1600/GraphicalConfiguration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="642" data-original-width="886" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj1f2agI1wjKxt2xFvmnAxb080vYdv3ynPoUIofCofWL_vuJ2WNZCfdzVu1D1pAAnggVXS3-fZR0jz9e9bojgfntdKt5X9mgvYb_dIhRrdli2Jqxsfx0UUXpE1rVm8ejtYUZ4Oz2YHRdg/s320/GraphicalConfiguration.png" width="320" /></a></div>
<div>
<br />
Please try out OfficeFloor (<a href="http://officefloor.net/tutorials" target="_blank">tutorials</a>) and we value all feedback.</div>
<div>
<br />
<h2>
Summary</h2>
So when Reactive frameworks are tooting their horn, they are actually doing this while restricting you further as a developer. Because the reactive frameworks can't handle the context problem, they push this problem onto you the developer in avoiding context.<br />
<br />
Subsequently, reactive frameworks rob developers (Peter) of context to pay for the message passing problem in their frameworks (Paul).<br />
<br />
By incorporating dependency contexts into event loops, you can incorporate context that we have grown to love in thread-per-request for managing things such as transactions.</div>
Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-60205978632332048872019-02-25T23:01:00.000-08:002019-02-25T23:46:53.611-08:00Is Spring Reactive already obsolete? Inversion of Thread CouplingBeyond Spring's Dependency Injection <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">only solving 1/5 of the Inversion of Control problem</a>, Spring Reactive bases itself on the event loop. While there are other popular event loop driven solutions (NodeJS, Nginx), the single threaded event loop is a pendulum swing in the other direction from thread-per-request (thread pools). With event loops competing against thread-per-request is there not some pattern that underlies both of them? Well, actually yes!<br />
<br />
But before getting to this, let's look at the issues regarding event loops and thread-per-request. If you are more interested in the solution, you can skip the next two sections.<br />
<br />
<h2>
Thread coupling problems</h2>
<h3>
Event loop</h3>
First of all, "thread coupling"? Why is this a concern? Well for event loops the single threaded nature requires all I/O to be undertaken asynchronously. Should a database or HTTP call need to block, it will block the single event loop thread and hold up the system. This restriction is in itself a big coupling problem, as to go Reactive all your I/O is coupled to now go asynchronous. This means no more ORMs like JPA to make access to databases easier (as JPA requires blocking database calls). Yep, something that used to remove 40-60% of boiler plate code in applications is now not unusable (enjoy writing this all over again!)<br />
<br />
Beyond the restrictive I/O in your decision to use Reactive patterns, the ability to use multiple processors is restricted as there is only one thread. Ok, instances of the Reactive engine are duplicated to each CPU, however they can not share state. The multi-threaded implications of sharing state between two event loops is difficult. Reactive programming is hard enough, let alone adding multi-threading into it. Yes, communication between event loops can be via events. However, using this to keep duplicated copies of shared state in sync across event loops creates problems that are just avoided. Basically you are told to design your Reactive systems to avoid this with immutability.<br />
<br />
Therefore, you are stuck coupled to the one thread. So what? Well if you have computationally expensive operations, such as security cryptography (JWT), it creates scheduling problems. By being on a single thread, this operation must be completed before anything else can be undertaken. With multiple threads, other threads can be time sliced in by the operating system to progress other less CPU intensive requests. However, you only have the one thread so all that lovely operating system thread scheduling is now lost. You're stuck waiting for the expensive CPU intensive operations to complete before servicing anything else.<br />
<br />
Oh please, just ignore these problems! We developers like performance. Reactive is all in the aim of greater performance and improved scalability. Lesser threads allows reduced overheads to allow improved throughput. Ok, yes, I'll have better performing production systems potentially reducing hardware costs. However, it's going to be a lot slower to build and enhance that production system due to coupling restrictions that comes from single threaded event loops. Not to mention, having to rewrite algorithms to not hog the CPU. Given the scarcity of developers compared to the over abundant supply of cloud hardware, arguing about costs of scale may only be for those rare significantly large systems.<br />
<br />
We do loose a lot going Reactive. This is possibly to the point that we have not thought it through enough. Hence, possibly why Reactive frameworks warn against changing to it whole sale. They usually indicate Reactive patterns only work for smaller less complicated systems.<br />
<br />
<h3>
Thread-per-request (thread pools)</h3>
On the flip side, thread-per-request patterns (such as Servlet 2.x) use thread pools to handle scale. They assign a thread to service the request and scale out by having multiple (typically pooled) threads.<br />
<br />
We can probably read many articles touting Reactive over the scale limitations of thread-per-request, but the main issue with thread-per-request is not actually in performance nor scale. The issue with thread-per-request is lot more permissive to your application and can actually pollute your whole architecture.<br />
<br />
To see this problem, just look at invoking a method:<br />
<br />
<pre><code class="language-java">Response result = object.method(identifier);
</code></pre>
<br />
Should the implementation of the method be as follows:<br />
<br />
<pre><code class="language-java">@Inject Connection connection;
@Inject HttpClient client;
public Result method(Long identifier) {
// Retrieve synchronous database result
ResultSet resultSet = connection.createStatement()
.executeQuery("<some SQL> where id = " + identifier);
resultSet.next();
String databaseValue = resultSet.getString("value");
// Retrieve synchronous HTTP result
HttpResponse response = client.send("<some URL>/" + databaseValue);
// Return result requiring synchronous results to complete
return new Result(response.getEntity());
}
</code></pre>
<br />
This creates a coupling problem to the thread of the request, that can pollute out to your whole architecture. Yes, you've just placed a coupling on the request thread out to your other systems.<br />
<br />
While the database call is synchronous, the HTTP call is also forcing the downstream system to respond synchronously. We can't change the HTTP call to be asynchronous, because the request thread wants to continue with a result to return from the method. This synchronous coupling to the request thread not only limits the call, but also limits the downstream system to have to provide a synchronous response. Hence, the thread-per-request thread coupling can pollute out to your other systems and possibly across your entire architecture. No wonder the REST micro-service pattern of synchronous HTTP calls are so popular! It is a pattern that forces itself top down on your system. Sounds like thread-per-request and Reactive share this same opinion on forcing everything top down to support themselves.<br />
<br />
<h2>
Threading to support I/O</h2>
In summary, the problems are as follows.<br />
<br />
Single threaded event loops:<br />
<ul>
<li>couple you to asynchronous communication only (simple JPA code is no longer available)</li>
<li>just avoids multi-threading, as two threads executing events from the event queue would create considerable synchronisation problems (likely slowing solution and causing concurrency bugs that are hard to code against for the best of developers)</li>
<li>loose the advantage of the thread scheduling that operating systems have spent considerable effort optimising</li>
</ul>
While thread-per-request solutions:<br />
<ul>
<li>couples you to synchronous communication only (as the result is expected immediately; and not some time later via callback)</li>
<li>have higher overheads (to single thread event loops) due to managing more threads and therefore less scalable</li>
</ul>
The pendulum swing between thread pools and Reactive single threaded can actually be considered going from synchronous communication (thread-per-request) to asynchronous communication (single threaded event loops). The remaining problems are actually implementation constraints of a threading model built specifically to support each type of communication. Plus given the coupling on downstream systems that synchronous communication poses, this pendulum swing to asynchronous communication is not all a bad thing.<br />
<br />
So the question is, why are we forced to choose only one communication style? Why can't we use synchronous and asynchronous communication styles together?<br />
<br />
Well, we can't put asynchronous calls inside synchronous method calls. There is no opportunity for callbacks. Yes, we can block waiting on the callback but Reactive will consider itself superior in scale due to additional threading overheads involved in this. Therefore, we need asynchronous code to allow synchronous calls.<br />
<br />
However, we can't put synchronous calls inside event loops, as it halts the event loop thread. Hence, we need extra threads to undertake the synchronous calls to allow the event loop thread to carry on with other events.<br />
<br />
Reactive has the answer. Use a Scheduler:<br />
<br />
<pre><code class="language-java">Mono blockingWrapper = Mono.fromCallable(() -> {
return /* make a remote synchronous call */
}).subscribeOn(Schedulers.elastic());
</code></pre>
<br />
<div style="text-align: right;">
<span style="font-size: xx-small;">Code taken from <a href="http://projectreactor.io/docs/core/release/reference/#faq.wrap-blocking" target="_blank">http://projectreactor.io/docs/core/release/reference/#faq.wrap-blocking</a></span></div>
<br />
Yay, now we can do synchronous calls within the event loop. Problem solved (well sort of).<br />
<br />
Well it's sorted if you can trust that you properly wrapped all synchronous calls in Callables. Get one wrong, and well you are blocking your event loop thread and halting your application. At least in multi-threaded applications only the particular request suffered, not the whole application.<br />
<br />
This seems, to me anyway, more a work around than an actual solution to the problem. Oh wait, everything needs to be Reactive top down so that solves this problem. Just don't do blocking calls and change all your drivers and your whole technology stack to Reactive. The whole "change everything to suit us, in a way that only integrates with us" seems very close to technology vendor lock in - in my opinion anyway.<br />
<br />
Therefore, can we consider a solution that allows synchronous calls and does not rely so heavily on the developer getting it right? Why, yes!<br />
<br />
<h2>
Inverting the Thread Coupling</h2>
The asynchronous communication driven Reactive single threaded event loop (excuse the mouth full) is identified as the right solution. Synchronous communication is solved by developers using Schedulers. In both cases, the Reactive functions are run with a thread dictated for them:<br />
<ul>
<li>asynchronous functions are executed with the thread of the event loop</li>
<li>synchronous functions executed with thread from the Scheduler</li>
</ul>
The control of the function's executing thread is heavily dependent on the developer getting it right. The developer has enough on their plate focusing on building code to meet feature requirements. Now the developer is intimately involved in the threading of the application (something thread-per-request always somewhat abstracted away from the developer). This intimacy to threading significantly increases the learning curve for building anything Reactive. Plus it will have the developer loose a lot of hair when they pull it out at 2 am trying to get the code working for that deadline or production fix.<br />
<br />
So can we remove the developer from having to get the threading right? Or more importantly, where do we give control of selecting the thread?<br />
<br />
Let's look at a simple event loop:<br />
<br />
<pre><code class="language-java">public interface AsynchronousFunction {
void run();
}
public void eventLoop() {
for (;;) {
AsynchronousFunction function = getNextFunction();
function.run();
}
}
</code></pre>
<br />
Well, the only thing we can target for control is the asynchronous function itself. Using an Executor to specify the thread, we can enhance the event loop as follows:<br />
<br />
<pre><code class="language-java">public interface AsynchronousFunction {
Executor getExecutor();
void run();
}
public void eventLoop() {
for (;;) {
AsynchronousFunction function = getNextFunction();
function.getExecutor().execute(() -> function.run());
}
}
</code></pre>
<br />
This now allows the asynchronous function to specify its required threading, as:<br />
<ul>
<li>using the event loop thread is via a synchronous Executor: <span style="font-family: "courier new" , "courier" , monospace;">getExecutor() { return (runnable) -> runnable.run(); }</span></li>
<li>using separate thread for synchronous calls is via Executor backed by thread pool: <span style="font-family: "courier new" , "courier" , monospace;">getExecutor() { return Executors.newCachedThreadPool(); }</span></li>
</ul>
Control is inverted so that the developer is no longer responsible for specifying the thread. The function now specifies the thread for executing itself.<br />
<br />
But how do we associate an Executor to a function?<br />
<br />
We use the <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">ManagedFunction of Inversion of Control</a>:<br />
<br />
<pre><code class="language-java">public interface ManagedFunction {
void run();
}
public class ManagedFunctionImpl
implements ManagedFunction, AynchronousFunction {
@Inject P1 p1;
@Inject P2 p2;
@Inject Executor executor;
@Override
public void run() {
executor.execute(() -> implementation(p1, p2));
}
private void implementation(P1 p1, P2 p2) {
// Use injected objects for functionality
}
}
</code></pre>
<br />
Note that only the relevant ManagedFunction details have been included. Please see <a href="https://sagenschneider.blogspot.com/2019/02/inversion-of-coupling-control.html" target="_blank">Inversion of (Coupling) Control</a> for more details of the ManagedFunction.<br />
<br />
By using the ManagedFunction, we can associate an Executor to each function for the enhanced event loop. (Actually, we can go back to the original event loop, as the Executor is encapsulated within the ManagedFunction).<br />
<br />
So now the developer is no longer required to use Schedulers, as the ManagedFunction takes care of which thread to use for executing the function's logic.<br />
<br />
But this just moves the problem of the developer getting it right from code to configuration. How can we make it possible to reduce developer error in specifying the correct thread (Executor) for the function?<br />
<br />
<h2>
Deciding the executing thread</h2>
One property of the ManagedFunction is that all objects are Dependency Injected. Unless Dependency Injected, there are no references to other aspects of the system (and static references are highly discouraged). Hence, the Dependency Injection meta-data of the ManagedFunction provides details of all the objects used by the ManagedFunction.<br />
<br />
Knowing the objects used by a function helps in determining the asynchronous/synchronous nature of the function. To use JPA with the database a Connection (or DataSource) object is required. To make synchronous calls to micro-services a HttpClient object is required. Should none of these be required by the ManagedFunction, it is likely safe to consider no blocking communication is being undertaken. In other words, if the ManagedFunction does not have a HttpClient injected, it can't make HttpClient synchronous blocking calls. The ManagedFunction is, therefore, safe to be executed by the event loop thread and not halt the whole application.<br />
<br />
We can, therefore, identify a set of dependencies that indicate if the ManagedFunction requires execution by a separate thread pool. As we know all dependencies in the system, we can categorise them as asynchronous/synchronous. Or more appropriately, whether the dependency is safe to use on the event loop thread. If the dependency is not safe, then the ManagedFunctions requiring that dependency are executed by a separate thread pool. But what thread pool?<br />
<br />
Do we just use a single thread pool? Well, Reactive Schedulers give the flexibility to use / re-use varying thread pools for the various functions involving blocking calls. Hence, we need similar flexibility in using multiple thread pools.<br />
<br />
We use multiple thread pools by mapping thread pools to dependencies. Ok, this is a little bit to get your head around. So let's illustrate with an example:<br />
<br />
<pre><code class="language-java">public class ManagedFunctionOne implements ManagedFunction {
// No dependencies
// ... remaining omitted for brevity
}
public class ManagedFunctionTwo implements ManagedFunction {
@Inject InMemoryCache cache;
// ...
}
public class ManagedFunctionThree implements ManagedFunction {
@Inject HttpClient client;
// ...
}
public class ManagedFunctionFour implements ManagedFunction {
@Inject EntityManager entityManager;
// meta-data also indicates transitive dependency on Connection
// ...
}
</code></pre>
<br />
Now, we have the thread configuration as follows:<br />
<br />
<table class="pure-table">
<thead>
<tr><td>Dependency</td><td>Thread Pool</td></tr>
</thead>
<tbody>
<tr><td>HttpClient</td><td>Thread Pool One</td></tr>
<tr class="pure-table-odd"><td>Connection</td><td>Thread Pool Two</td></tr>
</tbody></table>
<br />
We then use the dependencies to map ManagedFunctions to Thread Pools:<br />
<br />
<table class="pure-table">
<thead>
<tr><td>ManagedFunction</td><td>Dependency</td><td>Executor</td></tr>
</thead>
<tbody>
<tr><td>ManagedFunctionOne,<br />
ManagedFunctionTwo</td><td>(none in thread pool table)</td><td>Event Loop Thread</td></tr>
<tr class="pure-table-odd"><td>ManagedFunctionThree</td><td>HttpClient</td><td>Thread Pool One</td></tr>
<tr><td>ManagedFunctionFour</td><td>Connection (as transitive dependency of EntityManager)</td><td>Thread Pool Two</td></tr>
</tbody>
</table>
<br />
The decision of the thread pool (Executor) to use for the ManagedFunction is now just mapping configuration. Should a dependency invoke blocking calls, it is added to the thread pool mappings. The ManagedFunction using this dependency will no longer be executed on the event thread loop, avoiding the application halting.<br />
<br />
Furthermore, the likelihood of missing blocking calls is significantly reduced. As it is relatively easy to categorise the dependencies, it leaves less chance of missing blocking calls. Plus if a dependency is missed, it is only a configuration change to the thread pool mappings. It is fixed without code changes. Something especially useful as the application grows and evolves. This is unlike Reactive Schedulers that require code changes and significant thought by the developer.<br />
<br />
As the executing thread to execute a ManagedFunction is now controlled by the framework (not the application code), it effectively inverts control of the executing thread. No longer does the developer code threading. The framework configures it based on the dependency characteristics of the ManagedFunctions.<br />
<br />
<h2>
OfficeFloor</h2>
This is all good in theory, but show me the working code!<br />
<br />
OfficeFloor (<a href="http://officefloor.net/" target="_blank">http://officefloor.net</a>) is an implementation of the inversion of thread control patterns discussed in this article. We find frameworks are too rigid with their threading models that causes work arounds, such as Reactive Schedulers. We are looking for the underlying patterns to create a framework that does not require such work arounds. Code examples can be found in the <a href="http://officefloor.net/tutorials/" target="_blank">tutorials</a> and we value all feedback.<br />
<br />
Note that while OfficeFloor follows inversion of thread control, it's actual threading model is more complex to take other aspects into consideration (e.g. dependency context, mutating state, thread locals, thread affinity, back pressure and reduced locking to increase performance). These, however, are topics for other articles. But, as this article highlights, the threading for OfficeFloor applications is a simple configuration file based on dependency mappings.<br />
<br />
<h2>
Conclusion</h2>
Inversion of control for the thread allows the function to specify it's own thread. As the thread is controlled by the injected Executor, this pattern is named <i>Thread Injection</i>. By allowing the injection, the choice of thread is determined by configuration rather than code. This relieves the developer of the potentially error prone, buggy task of coding threading into applications.<br />
<br />
The side benefit of Thread Injection is that thread mapping configurations can be tailored to the machine the application is running on. On a machine with many CPUs, more thread pools can be configured to take advantage of thread scheduling by the operating system. On smaller machines (e.g. embedded) there can be more re-use of thread pools (potentially even none for single purpose applications that can tollerate blocking to keep thread counts down). This would involve no code changes to your application, just configuration changes.<br />
<br />
Furthermore, computationally expensive functions that may tie up the event loop can also be moved to a separate thread pool. Just add in a dependency for this computation to the thread pool mappings and all ManagedFunctions undertaking the computation are now not holding up the event loop thread. The flexibility of Thread Injection is beyond just supporting synchronous/asynchronous communication.<br />
<br />
As Thread Injection is all driven from configuration, it does not require code changes. It actually does not require any threading coding by the developer at all. This is something Reactive Schedulers are incapable of providing.<br />
<br />
So the question is, do you want to tie yourself to the single threaded event loop that really is just a single purpose implementation for asynchronous I/O? Or do you want to use something a lot more flexible?Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com0tag:blogger.com,1999:blog-274357204559150666.post-59970203997651855832019-02-25T20:36:00.000-08:002019-12-26T18:48:20.039-08:00Inversion of (Coupling) ControlThe question of "What is Inversion of Control?" or "What is Dependency Injection?" is met with code examples, vague explanations and even on StackOverflow identified as low quality answers - <a href="https://stackoverflow.com/questions/3058/what-is-inversion-of-control" target="_blank">https://stackoverflow.com/questions/3058/what-is-inversion-of-control</a><br />
<br />
We use inversion of control and dependency injection and even push it as the correct way to build applications. Yet, we can not clearly articulate why!!!<br />
<br />
The reason is we have not clearly identified what "control" is. Once we understand what we are inverting, the concept of Inversion of Control vs Dependency Injection is not actually the question to be asked. It actually becomes the following:<br />
<br />
<blockquote class="tr_bq">
Inversion of Control = Dependency (state) Injection + Thread Injection + Continuation (function) Injection</blockquote>
<br />
To explain this, well, let's do some code. (And yes, the apparent problem of using code to explain Inversion of Control is repeating, but bear with me - the answer has always been right before your eyes).<br />
<br />
One clear use of Inversion of Control / Dependency Injection is the repository pattern to avoid passing around a connection. Instead of the following:<br />
<br />
<pre><code class="language-java">public class NoDependencyInjectionRepository implements Repository<Entity> {
public void save(Entity entity, Connection connection) throws SQLException {
// Use connection to save entity to database
}
}
</code></pre>
<br />
Dependency Injection allows the repository to be re-implemented as:<br />
<br />
<pre><code class="language-java">public class DependencyInjectionRepository implements Repository<Entity> {
@Inject Connection connection;
public void save(Entity entity) throws SQLException {
// Use injected connection to save entity to database
}
}
</code></pre>
<br />
Now, do you see the problem it just solved?<br />
<br />
If you are thinking, I can now change the Connection to say REST calls and this is all flexible to change. Well, you would be close.<br />
<br />
To see the problem it solved, do not look at the implementation. Look at the interface. The client calling code has gone from:<br />
<br />
<pre><code class="language-java">repository.save(entity, connection);
</code></pre>
<br />
to the following:<br />
<br />
<pre><code class="language-java">repository.save(entity);
</code></pre>
<br />
We have removed the coupling of the client code to provide a connection on calling the method. By removing the coupling, we can substitute a different implementation of the repository (again, boring old news, but bear with me):<br />
<br />
<pre><code class="language-java">public class WebServiceRepository implements Repository<Entity> {
@Inject WebClient client;
public void save(Entity entity) {
// Use injected web client to save entity
}
}
</code></pre>
<br />
With the client able to continue to call the method just the same:<br />
<br />
<pre><code class="language-java">repository.save(entity);
</code></pre>
<br />
The client is unaware that the repository is now calling a micro-service to save the entity, rather than talking directly to a database. (Actually, the client is aware but we will come to that shortly.)<br />
<br />
So taking this to an abstract level regarding the method:<br />
<br />
<pre><code class="language-java"> R method(P1 p1, P2 p2) throws E1, E2
// with dependency injection becomes
@Inject P1 p1;
@Inject P2 p2;
R method() throws E1, E2
</code></pre>
<br />
The coupling of the client to provide arguments to the method is removed by Dependency Injection.<br />
<br />
<br />
<br />
Now, do you see the four other problems of coupling?<br />
<br />
<br />
<br />
At this point, I warn you that you will never look at code the same again once I show you the coupling problems. This is the point in the Matrix where I ask you if you want to take the red or blue pill, because there is no going back once I show you how far down the rabbit hole this problem really is - say that refactoring is actually not necessary and there are issues in the fundamentals of modelling logic in computer science (ok, big statement but read on and I can't put it any other way).<br />
<br />
<br />
<br />
So you chose the red pill.<br />
<br />
<br />
<br />
Let's prepare you.<br />
<br />
<br />
<br />
To identify the four extra coupling problems, let's look at the abstract method again:<br />
<br />
<pre><code class="language-java"> @Inject P1 p1;
@Inject P2 p2;
R method() throws E1, E2
// and invoking it
try {
R result = object.method();
} catch (E1 | E2 ex) {
// handle exception
}
</code></pre>
<br />
What is coupled by the client code?<br />
<ul>
<li>the return type</li>
<li>the method name</li>
<li>the handling of exceptions</li>
<li>the thread provided to the method</li>
</ul>
Dependency Injection allowed me to change the objects required by the method without changing the client code calling the method. However, if I want to change my implementing method by:<br />
<ul>
<li>changing it's return type</li>
<li>changing it's name</li>
<li>throwing a new exception (in the above case of swapping to a micro-service repository, throwing a HTTP exception rather than a SQL exception)</li>
<li>using a different thread (pool) to execute the method than the thread provided by the client call</li>
</ul>
This involves "refactoring" all client code for my method. Why should the caller dictate the coupling when the implementation has the hard job of actually doing the functionality? We should actually invert the coupling so that the implementation can dictate the method signature (not the caller).<br />
<br />
This is likely the point you look at me like Neo does in the Matrix going "huh"? Let implementations define their method signatures? But isn't the whole OO principle about overriding and implementing abstract method signature definitions? And that's just chaos because how do I call the method if it's return type, name, exceptions, arguments keep changing as the implementation evolves?<br />
<br />
Easy. You already know the patterns. You just have not seen them used together where their sum becomes a lot more powerful than their parts.<br />
<br />
So let's walk through the five coupling points (return type, method name, arguments, exceptions, invoking thread) of the method and decouple them.<br />
<br />
We have already seen Dependency Injection remove the argument coupling by the client, so one down.<br />
<br />
Next let's tackle the method name.<br />
<br />
<h2>
Method Name Decoupling</h2>
Many languages, including Java with lambda's, are allowing/have functions as first class citizens of the language. By creating a function reference to a method, we no longer need to know the method name to invoke the method:<br />
<br />
<pre><code class="language-java">Runnable f1 = () -> object.method();
// Client call now decoupled from method name
f1.run()
</code></pre>
<br />
We can even now pass different implementation of the method around with Dependency Injection:<br />
<br />
<pre><code class="language-java">@Inject Runnable f1;
void clientCode() {
f1.run(); // to invoke the injected method
}
</code></pre>
<br />
Ok, a bit of extra code for not much value. But again bear with me. We have decoupled the method's name from the caller.<br />
<br />
Next let's tackle the exceptions from the method.<br />
<br />
<h2>
Method Exceptions Decoupling</h2>
By using the above technique of injecting functions, we inject functions to handle exceptions:<br />
<br />
<pre><code class="language-java">Runnable f1 = () -> {
@Inject Consumer<E1> h1;
@Inject Consumer<E2> h2;
try {
object.method();
} catch (E1 e1) {
h1.accept(e1);
} catch (E2 e2) {
h2.accept(e2);
}
}
// Note: above is abstract pseudo code to identify the concept (and we will get to compiling code shortly)
</code></pre>
<br />
Now exceptions are no longer the client caller's problem. Injected methods now handle the exceptions decoupling the caller from having to handle exceptions.<br />
<br />
Next let's tackle the invoking thread.<br />
<br />
<h2>
Method's Invoking Thread Decoupling</h2>
By using an asynchronous function signature and injecting an Executor, we can decouple the thread invoking the implementing method from that provided by the caller:<br />
<br />
<pre><code class="language-java">Runnable f1 = () -> {
@Inject Executor executor;
executor.execute(() -> {
object.method();
});
}
</code></pre>
<br />
By injecting the appropriate Executor, we can have the implementing method invoked by any thread pool we require. To re-use the client's invoking thread we just use a synchronous Exectutor:<br />
<br />
<pre><code class="language-java">Executor synchronous = (runnable) -> runnable.run();
</code></pre>
<br />
So now we can decouple thread to execute the implementing method from the calling code's thread.<br />
<br />
But with no return value, how do we pass state (objects) between methods? Let's combine it all together with Dependency Injection.<br />
<br />
<h2>
Inversion of (Coupling) Control</h2>
Let's combine the above patterns together with Dependency Injection to get the ManagedFunction:<br />
<br />
<pre><code class="language-java">public interface ManagedFunction {
void run();
}
public class ManagedFunctionImpl implements ManagedFunction {
@Inject P1 p1;
@Inject P2 p2;
@Inject ManagedFunction f1; // other method implementations to invoke
@Inject ManagedFunction f2;
@Inject Consumer<E1> h1;
@Inject Consumer<E2> h2;
@Inject Executor executor;
@Override
public void run() {
executor.execute(() -> {
try {
implementation(p1, p2, f1, f2);
} catch (E1 e1) {
h1.accept(e1);
} catch (E2 e2) {
h2.accept(e2);
});
}
private void implementation(
P1 p1, P2 p2,
ManagedFunction f1, ManagedFunction f2
) throws E1, E2 {
// use dependency inject objects p1, p2
// invoke other methods via f1, f2
// allow throwing exceptions E1, E2
}
}
</code></pre>
<br />
Ok, there's a lot going on here but it's just the patterns above combined together. The client code is now completely decoupled from the method implementation, as it just runs:<br />
<br />
<pre><code class="language-java">@Inject ManagedFunction function;
public void clientCode() {
function.run();
}
</code></pre>
<br />
The implementing method is now free to change without impacting the client calling code:<br />
<ul>
<li>there is no return type from methods (slight restriction always being void, however necessary for asynchronous code) </li>
<li>the implementing method name may change, as it is wrapped by the ManagedFunction.run()</li>
<li>parameters are no longer required by the ManagedFunction. These are Dependency Injected, allowing the implementing method to select which parameters (objects) it requires</li>
<li>exceptions are handled by injected Consumers. The implementing method may now dictate what exceptions it throws, requiring only different Consumers injected. The client calling code is unaware that the implementing method may now be throwing a HTTPException instead of SQLException. Furthermore, Consumers can actually be implemented by ManagedFunctions injecting the Exception.</li>
<li>the injection of the Executor allows the implementing method to dictate it's thread of execution by specifying the Executor to inject. This could result in re-using the client's calling thread or have the implementation run by a separate thread or thread pool</li>
</ul>
<br />
All five coupling points of the method by it's caller are now decoupled.<br />
<br />
We have actually "Inverted Control of the Coupling". In other words, the client caller no longer dictates what the implementing method can be named, use as parameters, throw as exceptions, which thread to use, etc. Control of coupling is inverted so that the implementing method can dictate what it couples to by specifying it's required injection.<br />
<br />
Furthermore, as there is no coupling by the caller there is no need to refactor code. The implementation changes and then configures in it's coupling (injection) to the rest of the system. Client calling code no longer needs to be refactored.<br />
<br />
So in effect Dependency Injection only solved 1/5 of the method coupling problem. For something that is so successful for only solving 20% of the problem, it does show how much of a problem coupling of the method really is.<br />
<br />
<h2>
OfficeFloor</h2>
Implementing the above patterns would create more code than it's worth in your systems. That's why the OfficeFloor (<a href="http://officefloor.net/" target="_blank">http://officefloor.net</a>) "true" inversion of control framework has been put together to lessen the burdon of this code. This has been an experiment in the above concepts to see if real systems are easier to build and maintain with "true" inversion of control. Try the tutorials out to see the concepts in action (<a href="http://officefloor.net/tutorials" target="_blank">http://officefloor.net/tutorials</a>). We value your feedback, as we ourselves feel so claustrophobic with the coupling imposed by the method signature.<br />
<br />
OfficeFloor is also an implementation of many other innovative patterns that is going to take many more articles to cover. However, the concepts have been published should you like some heavy academic reading (<a href="http://doi.acm.org/10.1145/2739011.2739013" target="_blank">http://doi.acm.org/10.1145/2739011.2739013</a> with free download available from <a href="http://www.officefloor.net/about.html" target="_blank">http://www.officefloor.net/about.html</a>).<br />
<br />
Possibly the most interesting aspect of these patterns is that the configuration is no longer in code, but actually done graphically. The follow is an example of this configuration:<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMOEsi6Foa4KERKQLiRxItU9Cr2IGDvSPB3wNXAzkkcUj2GkfyQWGN6FvJ4-_V9aUA7IAcEibCE_thyphenhyphen0yj-V1jEpN8NfcfTBaie65cJ3PmwEAOszqUDdVShbos4GC_F-RhvvQIquZ2aQ/s1600/GraphicalConfiguration.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="642" data-original-width="886" height="231" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMOEsi6Foa4KERKQLiRxItU9Cr2IGDvSPB3wNXAzkkcUj2GkfyQWGN6FvJ4-_V9aUA7IAcEibCE_thyphenhyphen0yj-V1jEpN8NfcfTBaie65cJ3PmwEAOszqUDdVShbos4GC_F-RhvvQIquZ2aQ/s320/GraphicalConfiguration.png" width="320" /></a></div>
<br />
<h2>
Summary</h2>
So next time you reach for the Refactor Button/Command, realise that this is brought on by coupling of the method that has been staring us in the face every time we write code.<br />
<br />
And really why do we have the method signature? It is because of the thread stack. We need to load memory onto a thread stack, and the method signature follows this behaviour of the computer. However, in the real world modelling of behaviour between objects there is no thread stack. Objects are loosely coupled with very small touch points - not the five coupling aspects imposed by the method.<br />
<br />
Furthermore, in computing we strive towards low coupling and high cohesion. One might possibly put forward a case that in comparison to ManagedFunctions, that methods are:<br />
<br />
<ul>
<li><i>high coupling</i>: as methods have five aspects of coupling to the client calling code</li>
<li><i>low cohesion</i>: as the handling of exceptions and return types from methods starts blurring the responsibility of the methods over time. Continuous change and shortcuts can quickly degrade the cohesiveness of the implementation of the method to start handling logic beyond it's responsibility</li>
</ul>
<br />
So given, as a discipline we strive for low coupling and high cohesion, our most fundamental building block (the method and also for that matter the function) may actually go against our most core principles.Daniel Sagenschneiderhttp://www.blogger.com/profile/13630220451589425944noreply@blogger.com8