Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.
Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.
Stats
| Reputation: | 1148 |
| Pageviews: | 225.6K |
| Articles: | 3 |
| Comments: | 17 |
Comments
Oct 24, 2020 · Daniel Sagenschneider
Happy to discuss
Jan 25, 2020 · Daniel Sagenschneider
May 22, 2019 · Daniel Sagenschneider
Hi Jarrod. I acknowledge the mistakes in my previous article. Much of this was my confusion of trying to fit this within functional paradigms.
The discussion actually helped me clarify that I'm not trying to fit into one paradigm, but rather containerizing the programming paradigms. These "procedure containers" enable mutability within them to allow for the various programming paradigms. The containers then ensure the mutated state is synchronised to allow concurrent/parallel processing.
May 21, 2019 · Daniel Sagenschneider
Second article: https://dzone.com/articles/function-ioc-for-first-class-procedure
May 20, 2019 · Daniel Sagenschneider
Yes, the Kotlin is very simplistic objects. I was trying to keep the application relatively simple without creating complex object models. The Spring Repositories and Web Client used in the imperative code is a lot more (Java) OO. Plus as an aside, the transaction is actually Aspect Oriented Programming (not mentioned as article already long enough).
In regards to different languages, I could have written it all in Java. However, I found the different languages help accentuate the various paradigms (JavaScript for asynchronous event loop code, Java for imperative, Reactive just stands out, Scala for functional, leaving Kotlin for OO).
So, yes, the contentious aspect of combining the paradigms is looking for similarities:
- imperative is already procedures
- OO is message passing between objects (considered either in methods wrapped in procedures or as my second article will get too, continuations passing message arguments)
- functions can be wrapped in procedures
- reactive is declarative style that transforms a stream of inputs to outputs (similarly procedure of inputs and outputs)
So if a procedure can effectively wrap each paradigm's core logic building block, it to me is the "container" to make them appear similar (especially in containerising each paradigm's threading model). Then we compose/weave these containers together to become the application. In doing so, the procedure becomes a somewhat "first class citizen" to the composition. So yes, it is procedures but procedures used to weave the containerised paradigms together.
Apr 29, 2019 · Daniel Sagenschneider
Happy to discuss
Mar 20, 2019 · Erik Pragt
I'd hope you are already using Lombok.
What I gather from the article is that replacing data objects is a good place to start if I want to migrate my existing Java solution with Lombok to Kotlin.
Mar 07, 2019 · Daniel Sagenschneider
John, yes, the purity of design vs the realities of an impure world :)
My experience of this, is that we typically associate:
What I then find is we tend to abstract way to early in the development process. We see commonalities and then start writing abstractions to start modelling the solution - much before we have even understood the full problem space.
And this tendency to abstract way too early, is where we get frameworks. Frameworks, typically, are seen as implementations of proven solutions. However, a "framework" can also be considered an externalised abstraction. Therefefore, by using a framework, you again abstract too early in the development process.
Then it comes to one of my favourite quotes:
However, saying that, I don't want to have to write socket listening code, HTTP protocols and JSON parsing everytime I want to write a REST handler.
I want a framework that does the reverse of the quote (or at least does not make things worse for me). Basically, if I want to:
- do multiple calls out to different micro-services asynchronously (reactively) to pull in data
- then use JPA with transactions (synchronously) to update the database
I, as the developer, should be allowed this.
However, if I wanted to do this with say Spring, I would be forced to choose either Spring's Servlet Stack or Reactive Stack. Each does one step well and the other poorly. This is because each couples you to a very "oppinionated" threading model.
What I really want to do is:
1) write some reactive functional code to concurrently make all the micro-service HTTP calls
2) write some OO / imperative code to work with JPA to make changes into the database, then
3) hook these up together to service the request
Basically, I want to write the implementations first and worry about coupling them together later. This pushes abstraction (frameworks) as a later decision, rather than an upfront decision.
And this is what Agile says. Defer your decisions until you need to make them.
Most frameworks (abstractions) take way too much oppinionated control of the couplings for your code way too early in the development process. This, I find, causes the problems you describe.
With OfficeFloor, I'm looking to inverse this coupling control on your code to avoid abstraction too early. You write implemenations first, then worry about wiring them up later. Decisions on abstractions are deferred to much later in the development cycle (when you know a lot more about the problem space to use the appropriate abstractions).
And this is where some of the definition of IoC in this article is coming from - invert control of coupling away from the framework to allow your implementations to control the coupling.
Mar 06, 2019 · Daniel Sagenschneider
Well, firstly, it is good to see we are now transcending OO, functional, etc to the concept of "what should control coupling?"
Now, I'm certainly not claiming to use IoC to do all coupling. Just like DI would not be used to compose every object together.
IoC just extends the object reference inverse coupling of DI, to:
- function invocation inverse coupling (Continuation Injection), and
- thread execution inverse coupling (Thread Injection)
As we move forward to more functional programming on multi-core machines, I expect your OO systems will want to start incorporating the benefits of functional programming and multi-threading. IoC is just giving these aspects the same inverse coupling capability that we have for object references.
Now to answer, injecting exception handlers, this is more to do with functional code. Typical imperative / OO code is written as:
try {
// Implementation logic one
// Implementation logic two
// Implementation logic three
} catch (SqlException ex) (
// Implementation logic to handle SQL exception
) catch (HttpException ex) {
// Implemetnation logic to handle HTTP exception
}
While functional (asynchronous) code, the try/catch code is more:
promise_future_mono_flux_etc.then((result) -> {
// Implementation logic one
)).then((result) -> {
// Implementation logic two
}).then((result) -> {
// Implementation logic three
}).catch((error) -> {
// Implementation to generically handle error
})
As OfficeFloor runs on a multi-threaded event loop, it provides the second. However, it does it without you having to write the promise/future/mono/flux/etc chaining. The:
- Continuation (function) Injection provides this chaining (composition)
- Thread Injection then comes in to change the execution thread appropriately for each implementation
- Continuation (function) Injection can also provide specific handling for each type of exception
- Dependencies can then be injected into the functions to provide context across the functions for such things as transactions (see article here)
In isolation, yes, each would be an overhead (and questionable). However, putting all the patterns together for IoC gives you a lot more flexibility.
Note: if you want natural coupling direction, write your code in the one implementation function. If you want to inverse the coupling, let the framework handle the complexities of this (like DI does for you).
Mar 05, 2019 · Daniel Sagenschneider
John, I totally agree with you on this one. For supporting some Dependency Injection frameworks, I feel like:
someone has scattered the pages of the novel all over the floor and I have to piece it together to get a coherent understanding of the story
Early on I found this problem. Hence, the function (injection) composition configuration is done graphically. The first thing in supporting applications built with OfficeFloor, is open applicaiton.woof file (with IDE plugin). This is to see a graphical overview of "how all the pages are pieced together". For me this is the DRY principle, as I now no longer have to repeat design overviews with UML diagrams (and the like). The idea is the configuration itself provides this overview. Within added benefit of it always being up to date, as it actually configures the system.
Mar 05, 2019 · Daniel Sagenschneider
Yes, I've had to touch on many areas and many disciplines to build out the framework implementing the IoC pattern.
However, I still find an OO slant to a lot of this discussion, particularly in thinking we are wiring together methods of objects.
What I've found in very generalistic terms:
- OO programming is great at modeling things, but poor at modeling behaviour
- Functional programing is great at modelling behaviour, however poor at modelling things
- writing impure functions to mutate objects is a means to get the best of both
So in attempts to take the best of both:
Dependency Injection is an OO concept to compose objects together.
Continuation (function) Injection is a functional concept to compose functions together (in similar implementation defined injection style).
Thread Injection is doing this for mapping to Operating System concepts (such as multi-threading).
Inversion of Control, I've found, is just putting the above three things together.
Mar 05, 2019 · Daniel Sagenschneider
Yes, I would consider IoC a failure if it can't integrate existing solutions. The resulting application code should still be very familar to developers. DI, really, only ever replaced the "new" keyword with a factory for indirection. IoC just takes this further from the constructor to the methods (or more correctly, functions using objects - with functions still calling Object methods directly). You should still be able to use all the above proven solutions. IoC is not a replacement like Reactive that says you have to write everything differently. IoC should just slip into your application architecture (like DI) to help improve design and ease evolution. Albeit, it does close some gaps in fundamental patterns (topics way too "dry" to get into here).
In regards to academic references, I've already admitted I write code much better than I document (excuse the paper length and the many long sentences). Plus, since writing the paper, I've integrated a lot more functional concepts. Saying that, section 4.4 background, details the critique.
However, yes, developers do like examples of apps:
- all tutorials are working apps (with code here)
- OfficeFloor is entered in the TechEmpower Benchmarks (code here)
- I'm working with start-ups, but I unfortunately can't divulge the code (nor what they are doing)
- in my remaining "copious" amount of free time I'm building a registration application (most code at moment on branches so watch this space)
So, unfortunately, nothing overly commercially public to show. But, saying that, I've not known too many commercial businesses to release their application code. So yes it is early days, but I'm only getting positive responses regarding developing with OfficeFloor.
However, as much as I want to get into details of building apps with OfficeFloor, I want to keep focus on the IoC definition for this article. Otherwise, we just get into debate wars over design nuances (the Internet is full DI implementation debates, e.g. setter vs constructor injection). I've got a lot more blogs in the pipeline to have these debates over (e.g. for something a little less controversial :p Is Spring Reactive Already Obsolete?).
Mar 05, 2019 · Daniel Sagenschneider
Hi Robert
One thing I must admit is that I'm a better coder than documenter. I've just starting blogging about OfficeFloor after a very good friend has been pushing me for a while.
The concept of OfficeFloor was presented to the European Conference on Pattern Languages of Program in 2013 in a paper published later in 2015 (http://doi.acm.org/10.1145/2739011.2739013). A free download is available from here.
The premise of the paper was "can we learn something from how business organise themselves and translate this into software design improvements?" Basically, businesses have been around a lot longer than software systems, so how did they deal with problems such as scale before computers existed?
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. Overtime your business grows and you hire more people, assign clearer functional responsibilities and start to scale up your business. Businesses have to do this, while also changing quickly to stay competitive.
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. Agile is a lot more closer to how businesses grow and evolve.
Unfortunately, our software patterns have still stayed "waterfall" top down approach. We have changed our development practices, via Agile, to evolve. However, we have not changed our software patterns to evolve. Object orientation, functional, imperative still enforce top down micro-managing control over implementations. In a business, I would not micro-manage employees undertaking functions within the business. So why should software continue to provide this micro-managing of functions (implementations)?
The Inversion of Control presented is to enable bottom up evolution of software systems. The idea is to remove the top down designs we are currently required to do in starting new systems. This is to move software architectures inline with the flexibility of our software development practices (e.g. Agile). I start small writing the implementations of value. Then evolve by adding more implementations. I care little for what the end architecture will look like (much like I won't know how my business will look as it grows). However, I'm able to grow, evolve and change the software easily to stay competitive.
Mar 05, 2019 · Daniel Sagenschneider
Thanks, yes for DI there is a lot of discussion on injection by constructor/setter. However, this is for injecting object dependencies into other objects.
The @Inject within the ManageFunction is only to highlight the concepts. For OfficeFloor, methods are reflectively interogated for dependencies. Within the Continuation (function) Injection there is no constructor/setter injection. Dependencies are injected as parameters (arguments) directly into the method. In other words, OfficeFloor takes care of writing the ManagedFunctionImpl for you so you only need to write the implementing methods. See here for more details.
Mar 05, 2019 · Daniel Sagenschneider
I understand what you are saying. This is the common descriptions of Inversion of Control across the Internet that focuses only on Object Oriented concepts.
What I'm trying to do is incorporate other Computer Science disciplines. This is so applications can be developed bottom up, rather than the typical top down imposed by coupling.
The easiest way to clarify this distinction of OO focused IoC, is that this asks to define IoC with the following caller coupling:
defineIoC(OO concepts) {
// Caller coupling to OO concepts will give definition as per write ups on Internet
// Oh wait, caller did not provide reference to Internet so I can't access them
}
When I as the implementer of the definition, want to answer as:
defineIoC() {
@Inject OO ooConcepts; // for interfaces to allow DI
@Inject Functional functionalConcepts; // for continuations
@Inject OperatingSystem osConcepts; // for multi-threading (and where do above disciplines even discuss multi-threading?)
// Implementation couples to appropriate Computer Science concepts to give this article
}
However, because developers have been heavily coupled to OO concepts, some refactoring in their thinking is going to be required to really understand the implementation (definition) provided by this article. In particular, how you can now build applications bottom up from implementations, rather than being forced by method caller coupling to design them top down.
Mar 01, 2019 · Mike Gates
Problem with IoC in this article is that it is being viewed through an OO frame of mind. How do you "control" objects? Well you call the methods on them. In this case, you have specifically focused on construction. However, the Hollywood Principle of "Don't call us, we call you" applies to methods of the object as well. Dependency Injection only becomes part (actually 1/5) of the patterns to a "true" inversion of control pattern. More details here.
Feb 28, 2019 · Daniel Sagenschneider
For something "new", yes, you might assume IoC has no tooling. However, IoC re-uses all your existing tooling, and then adds further enhanced tooling on top.
For example, can the execution of your facade methods be wired together graphically? See tutorials for examples, and in particular here.
Or for example, can you completely change the threading of your application in configuration? Something in Reactive systems would require writing Schedulers throughout your code, and changing would be signficant work. OfficeFloor can have different configurations of threading for different evironments, without changing any code.
However, the focus of this article is not on the debate of whether to use IoC (or it's benefits). This article is focused on clearly defining IoC. While Dependency Injection took developers a bit to get their head around the concepts, I'm expecting it will take similar time to understand Continuation (function) Injection and Thread Injection concepts.
Saying that, the easiest way to understand this, is to refer to IoC's other description - Hollywood Principle:
"Don't call us, we'll call you"
Well, how do you call an object? You do it via a method. IoC has always been about calling the method.