Dependency Injection: Method(s) and a Challenge

[)roi(]

Executive Member
Joined
Apr 15, 2005
Messages
6,282
Reaction score
405
Location
What is Dependency Injection (DI)?
Dependency injection is a method to replace rigid dependencies in a codebase with its configurable counterpart, by implementing a design where a dependent resource is passed as a configurable parameter.

Dependency Injection Objectives:
  • Application / Classes are independent from the creation of their dependencies.
  • Separate configuration of the dependencies.
  • Ability to support different configurations
  • Test mocking.
Why do we even need something like Dependency Injection?
  • Encapsulating objects directly within the class makes the class instances inflexible because it rigidly commits a class to particular object; making it impossible to change that instantiation later without affecting the code of that class.
  • More so it limits the reusability of code e.g. when the only difference is a different another configuration of the dependency.
  • This rigidity also makes the class difficult to test, because live processing is innately unpredictable and so too mutability i.e. with a rigid design there is simply no way to inject a mock pure object to simulate a fixed input to output scenario.
Method(s)
The following is a summary of the different approaches to work around fixed dependencies in a codebase.
  • Interface / Protocol and Constructor Injection
  • Interface / Protocol and Property Injection
  • Singleton
  • Partial Application: with referential (mutable) types.
  • Paradigm shift: replacing mutable surface with functional purity; including partial application with immutable types.
  • Reader Monad *
  • Free Monad *
Basically in this thread I'm going to try to walk through each of these methods, in order to review their basic construction and to ultimately assess the pros / cons of each.

* Added for completeness
As for the Reader Monad and Free Monad, both of these functional approaches will only be briefly explained in this thread so as to not detract from referential (mutable) dependency injection (versus immutability). These anyway as generic algebras deserve a separate thread for a more comprehensive overview.
Ps. Please feel free to add details of any methods you think I've failed to include, or even to provide more clarity on anything I may have overlooked, oversimplified, etc.

Challenge
In line with the other threads; I'm going to put out a DI related challenge for anyone who wants to submit a solution and/or use the opportunity to demonstrate an alternative approach and /or to simply provide some missing clarity.

Summary of DI related application:
We're going to build a simple app that connects to the Github repository API for a configurable user's account, and then populates an array structure containing the fields we need in our interface.

JSON API: https://api.github.com/users/google/repos
Required JSON fields: "archived", "description", "html_url", "name", "pushed_at".

Dependency / Mock Requirement(s):
Naturally this type of computation is directly tied to a network based transaction, which with a rigid design would make it impossible to work on this code:
  • When we're coding offline
  • With a different API, for example to get the latest weather forecast
  • For testing; because testing typically needs a fixed input to output relationship; which cannot be guaranteed with a live API.

A successful solution should ideally demonstrate:
  • Injection of a live process : connecting to Github and retrieving the repos for a nominated user
  • How to substitute in a Mock dependency for both success and failure scenarios : i.e. process purity which can be used for offline coding and/or unit testing.
The method used for dependency injection is left for you to decide, and similarly the choice of how far you extend your code to demonstrate the flexibility of your design e.g. whether your code ultimately ties into an interface (Model / View / Controller) is entirely optional.

At the conclusion of this thread's challenge (+- 2 weeks), I'll be submitting examples in Swift and C#:
  • The Swift code will demonstrate both constructor and singleton injection methods together with a rudimentary Tableview interface in Xcode playgrounds.
  • The C# code will focus only a similar design to Swift for singleton injection, and the interface will be a rudimentary console (terminal) output.
Naturally I'll where possible also try to keep parts of the construction pure i.e. to maximise the surface for unit testing -- however for overall consumption of the code I'll avoid too many FP bits.

Preview of Swift Playground UI with Google's repositories.
Screen Shot 2018-08-15 at 00.21.38.png

Over the next 2 weeks;
I'll be posting some very basic code examples in C# and/or Swift to try demonstrate / discuss the different approaches to DI.
 
Last edited:
Love the formatting... Nice and neat. I think this thread will be a great to illustrate the power of DI and techniques of using DI to decouple code and make code bases more extensible. Many people have a-ha moments when looking at decent examples, so I would be posting some as well.
 
Love the formatting... Nice and neat. I think this thread will be a great to illustrate the power of DI and techniques of using DI to decouple code and make code bases more extensible. Many people have a-ha moments when looking at decent examples, so I would be posting some as well.
Thanks @Spacerat always good to have a different take on all of this; so I'm looking forward to your posts.

I'm planning to post something this evening on the general idea of Dependency Injection and how it plays out in the broader sense in code I.e. it's certainly not limited to the more typical OOP constructor and setter scenarios.

BTW In the thread where we discussed the idea for this thread; you touched on the notion of temporal coupling concerns with setter injection -- I'm aiming to also demonstrate a simple helper extension that works a lot like VB's with block to allow us to ensure that the instance and its setters are initialized at the same time, and how this simple concept can be extended in the general sense for things like flexible templating.
 
Last edited:
[)roi(];21945429 said:
Thanks [MENTION=375958]Spacerat[/MENTION]; always good to have a different take on all of this; so I'm looking forward to your posts.

I'm planning to post something this evening on the general idea of Dependency Injection and how it plays out in the broader sense in code I.e. it's certainly not limited to the more typical OOP constructor and setter scenarios.

BTW In the thread where we discussed the idea for this thread; you touched on the notion of temporal coupling concerns with setter injection -- I'm aiming to also demonstrate a simple helper extension that works a lot like VB's with block to allow us to ensure that the instance and its setters are initialized at the same time, and how this simple concept can be extended in the general sense for things like flexible templating.

Droid, I created a thread specific for discussing temporal coupling as it not only relates to DI but also to other scenarios, so I thought that it warranted its own thread.
https://mybroadband.co.za/vb/showthread.php/970365-Temporal-coupling?p=21946703#post21946703
 
Last edited:
Dependency: Mutable vs. Immutable
Reasoning about code is always going to far more challenging when a dependency is mutable.
Immutability in contrast makes reasoning about code not only easy, but also predictable.

Note:
Dependency refers to F(A) => B)


Immutability:
So what do we mean when we refer to something as being immutable? Here's a short bit of code to illustrate this:

C#:
class Immutable {
  public static int Add(int x, int y)
  {
    return x + y;
  }
}
Here we have a simple function named Add which has two dependencies: x and y, both Integer values and it returns an Integer value, the sum of x and y.

Reasoning about this code
This code is simple to reason about because we don't have to be concerned about x or y; being value types we know that the compiler will ensure that their state is always predictable.

So the only thing left to do is to make sense of this bit of code:
C#:
return x + y;
Testing this function is also easy because we know that every time we substitute 2 and 3 for x and y, the function will always return a 5. There's simply no other eventualities that we need to account for both in our live environment and in testing.
C#:
Console.Writeline(Immutable.Add(2, 3)) // will always return a 5


Mutability:
Mutability as the term implies is a "tendency for something to change", or stated differently: "for something to be unpredictable". When something isn't guaranteed we have no choice but to include additional code to cover for this, for example:

If we wanted to make a hotdog; we have a direct dependency on hotdog buns, sausages and the sauces we like. If we didn't check that these dependencies could be fulfilled we end up either going hungry or with an indeterminate hotdog state, for example:
Code:
a hotdog without the dog.

Many things in life and computing have mutable state; so there will always be parts that simply cannot avoid mutability, and that's ok.
Hence for mutability we need solutions to make dealing with our mutable dependencies easier, but let's not forget that these solutions always come at a cost; more code scaffolding will be required.

Let's look at rewrite of the Add function where the y dependency is mutable i.e. variable.
In the case of the hotdog, we may need to have a solution that allows us still go ahead when we have a different type of bun -- the situation when the bakery has sold out of hotdog buns.

First thing we do in code with a mutable dependency is to define what we need; this in C# is more typically done as an interface.
C#:
public interface Addend
{
  int GetY();
}
Our Addend interface defines a method that returns an Integer value when we try to get a y.

Let's now rewrite our Add function to work with a mutable y:
C#:
class Mutable {
  public static int Add(int x, Addend addend)
  {
    return x + addend.GetY();
  }
}
Next let's define a class that conforms to this interface and provides a value for the y when we ask for it.
C#:
public class MutableAddendMock : Addend
{
  int y;

  public MutableAddendMock(int y) {
    this.y = y;
  }

  public int GetY()
  {
    return this.y;
  }
}
And using our MutableAddendMock we can get the same result from our Mutable.Add function.
C#:
Console.Writeline(Mutable.Add(2, new MutableAddendMock(3))); // return a 5
Aside from more code; everything superficially looks solid -- Right? ... uh huh ... time to throw the 1st curve ball.

Let's create another class that conforms to the Addend interface:
C#:
public class MutableAddendMockCurveBall : Addend
{
  int y;

  public MutableAddendMockCurveBall(int y)
  {
    this.y = 2;
  }

  public int GetY()
  {
    return this.y;
  }
}
Running this code with MutableAddendMockCurveBall simplistically shows that mutable dependencies are not always predictable.
C#:
Console.Writeline(Mutable.Add(2, new MutableAddendMockCurveBall(3))); // return a 4
This is not end of mutable unpredictability; because we have a subtle bug hidden in our Mutable.Add function -- did you identify it?

To demonstrate this I'm going to create another class that conforms to the Addend interface, but it's going to purposefullymisbehave; our 2nd curve ball.
C#:
public class MutableAddendNetwork : Addend
{
  int y;

  public MutableAddendNetwork(int y)
  {
    this.y = y;
  }

  public int GetY()
  {
    throw (new Exception("Let's crash... because sometimes things fail."));
    return this.y;
  }
}
Running this code with MutableAddendNetwork will crash.
C#:
Console.WriteLine(Mutable.Add(2, new MutableAddendNetwork(3))); // System.Exception is thrown
That kind of summarises why mutable state is so difficult to work with; because even with interface conformances we simply cannot expect mutable code to behave in a predictable way -- if we could we wouldn't need to use stuff like mock objects to artificially create a happy path for testing.

The second thing is to look at how much extra code is required for a very simple mutable dependency scenario...
C#:
public interface Addend
{
  int GetY();
}

public class MutableAddendMock : Addend
{
  int y;

  public MutableAddendMock(int y) {
    this.y = y;
  }

  public int GetY()
  {
    return this.y;
  }
}

public class MutableAddendNetwork : Addend
{
  int y;

  public MutableAddendNetwork(int y)
  {
    this.y = y;
  }

  public int GetY()
  {
    throw (new Exception("Let's crash... because sometimes network things fail."));
    return this.y;
  }
}
...this extra structural stuff is simply not required with immutable computations, and let's be honest with all this extra baggage, we just end up obfuscating the purpose for the computation.

Mutability has a big cost
Managing dependencies with mutability always has a big cost in a codebase, because it not only means we have to write more code, it also means our code is far less predicable and we also have to watch out for those hidden runtime bugs. This alone should be enough motivation to try to limit where you employ mutable state; in practice the overwhelming majority of most codebases does not need to be 100% mutable; we simply need to choose to not add so much structural and muddling code to our codebases.

There's BTW a term for codebases that are structurally over complicated:
a big ball of mud
... because the actual crux of computations are muddied with a lot of structural "baggage" code.

Conclusion
I'm certainly not saying that mutable style dependency injection has no place in a codebase; like mutability in general it simply can't easily be avoided, and the cost of trying to avoid it is arguably just as counter-productive as the big ball of mud.

What I'm instead saying is that we should avoid making it the hammer for every computational nail, for that we should rather embrace our immutable hammer, and only add mutability where is cannot be avoided.
 
Last edited:
Mutability versus Immutability - Example Project.
Continuing from yesterday's post about differences between mutable versus immutable, and why a codebase should try to exploit immutability more.

I thought the best way to demonstrate this would be with a simple calculator engine, built according to these two different approaches:
  • Mutable and Imperative.
  • Immutable and a bit more Functional.
Well here goes... this is mostly going to be code.
 
Mutable and Imperative : Calculator Engine

File: Operation.cs
Purpose: Defines the operations that our calculator supports. Start is the first operation

C#:
using System;
namespace Calculator
{
  public enum Operation
  {
    Add,
    Subtract,
    Divide,
    Multiply,
    Start
  }
}

File: OpValueM.cs
Purpose: Defines a type that stores the combination of an Operation and a Value e.g. Add 1
C#:
namespace Calculator
{
  public class OpValueM
  {
    double value;
    Operation operation;

    public OpValueM(double value, Operation operation)
    {
      this.value = value;
      this.operation = operation;
    }

    public double GetValue() {
      return this.value;
    }

    public Operation GetOperation()
    {
      return this.operation;
    }

    override public string ToString()
    {
      return string.Format("OpValueI: [value: {0}, operation: {1}]", value, operation);
    }
  }
}

File: CalculatorM.cs
Purpose: This is core of the calculator engine
C#:
using System;
using System.Collections.Generic;

namespace Calculator
{
  public class CalculatorM
  {
    List<OpValueM> lov;
    double total;

    public CalculatorM(int value = 0)
    {
      lov = new List<OpValueM>();
      AddOpValue(Operation.Start, value);
      total = 0;
    }

    public void AddOpValue(Operation operation, double value)
    {
      lov.Add(new OpValueM(value, operation));
    }

    void ComputeTotal()
    {
      double tempTotal = 0;
      foreach (OpValueM opValue in this.lov) {
        switch (opValue.GetOperation()) {
          case Operation.Start:
            tempTotal = opValue.GetValue();
            break;
          case Operation.Add:
            tempTotal += opValue.GetValue();
            break;
          case Operation.Subtract:
            tempTotal -= opValue.GetValue();
            break;
          case Operation.Divide:
            tempTotal /= opValue.GetValue();
            break;
          case Operation.Multiply:
            tempTotal *= opValue.GetValue();
            break;
          default: throw new Exception("Must never match: crash if it does.");
        }
        this.total = tempTotal;
      }
    }

    public void Reset()
    {
      this.lov = new List<OpValueM>() { new OpValueM(0, Operation.Start) };
      this.total = 0;
    }

    public double getTotal()
    {
      this.ComputeTotal();
      return this.total;
    }

    override public string ToString() {
      var r = "";
      foreach (OpValueM ov in lov) {
        r += ov.ToString() + "\n";
      }
      return r;
    }
  }
}

File: Program.cs
Purpose: ...and finally this is an example of how we instantiate and use our calculator engine.
C#:
using System;

namespace Calculator
{
  class MainClass
  {
    public static void Main(string[] args)
    {
      // Mutable
      var calcMutable = new CalculatorM(10);
      calcMutable.AddOpValue(Operation.Multiply, 20);
      calcMutable.AddOpValue(Operation.Add, 30);
      calcMutable.AddOpValue(Operation.Divide, 40);
      Console.WriteLine(calcMutable.ToString());
      Console.WriteLine(calcMutable.getTotal());

      // ------------------------------------------------------------------------------------------------------
      //
      //     Mutable Calculator design does not have the ability for static function unit testing
      //
      // ------------------------------------------------------------------------------------------------------

      // i.e. No separate unit tests are possible with this design
    }
  }
}

Finally the output from this
Code:
OpValueI: [value: 10, operation: Start]
OpValueI: [value: 20, operation: Multiply]
OpValueI: [value: 30, operation: Add]
OpValueI: [value: 40, operation: Divide]

5,75

Conclusion
The only way to test this Mutable and Imperative calculator engine is to instantiate and instance of CalculatorM, and then to execute some AddOpValue method calls and finally validate that against getTotal(). There is based on this design no simple way to test a single part of engine; we essentially can only test the code as a whole.
 
Last edited:
Immutable and bit more Functional : Calculator Engine

File: Operation.cs
Purpose: Defines the operations that our calculator supports. Start is the first operation
C#:
using System;
namespace Calculator
{
  public enum Operation
  {
    Add,
    Subtract,
    Divide,
    Multiply,
    Start
  }
}
This is exactly the same as the mutable and imperative version.


File: OpValueI.cs
Purpose: Defines a type that stores the combination of an Operation and a Value e.g. Add 1
C#:
using System;
using System.Collections.Immutable;
using System.Linq;

namespace Calculator
{
  public sealed class OpValueI
  {
    public readonly double value;
    public readonly Operation operation;

    private OpValueI(double v, Operation o)
    {
      this.value = v;
      this.operation = o;
    }

    public static OpValueI Create(double v, Operation o) {
      return new OpValueI(v, o);
    }

    override public string ToString() {
      return string.Format("OpValueI: [value: {0}, operation: {1}]", value, operation);
    }
  }

  public static class OpValueExtensionMethods {
    public static OpValueI Concat(this OpValueI a, OpValueI e)
    {
      return OpValueI.Create(OpValueI.Create(a.value, e.operation).Execute(e.value), Operation.Start);
    }

    public static double Execute(this OpValueI ov, double b)
    {
      switch (ov.operation) {
        case Operation.Start: return ov.value;
        case Operation.Add: return ov.value + b;
        case Operation.Subtract: return ov.value - b;
        case Operation.Divide: return ov.value / b;
        case Operation.Multiply: return ov.value * b;
        default: throw new Exception("Must never match: crash if it does.");
      }
    }

    public static double Total(this ImmutableList<OpValueI> ilov)
    {
      return ilov.Aggregate(Concat).value;
    }
  }
}

File: CalculatorI.cs
Purpose: This is core of the calculator engine
C#:
using System.Collections.Immutable;
using System.Linq;

namespace Calculator
{
  public sealed class CalculatorI
  {
    ImmutableList<OpValueI> ilov;

    public double total {
      get { return ilov.Total(); }
    }

    private CalculatorI(int initial = 0)
    {
      ilov = ImmutableList.Create(OpValueI.Create(initial, Operation.Start));
    }

    public static CalculatorI Create(int initial = 0)
    {
      return new CalculatorI(initial);
    }


    public void AddOpValue(Operation operation, double value)
    {
      ilov = ilov.Add(OpValueI.Create(value, operation));
    }

    public void Reset()
    {
      this.ilov = ImmutableList.Create(OpValueI.Create(0, Operation.Start));
    }

    override public string ToString() {
      return ilov.Aggregate("", (a, e) => a + e + "\n");
    }
  }
}

File: Program.cs
Purpose: ...and finally this is an example of how we instantiate and use our calculator engine.
C#:
using System;
using System.Collections.Immutable;

namespace Calculator
{
  class MainClass
  {
    public static void Main(string[] args)
    {
      // Immutable
      var calcImmutable = CalculatorI.Create(10);
      calcImmutable.AddOpValue(Operation.Multiply, 20);
      calcImmutable.AddOpValue(Operation.Add, 30);
      calcImmutable.AddOpValue(Operation.Divide, 40);
      Console.WriteLine(calcImmutable.ToString());
      Console.WriteLine(calcImmutable.total);

      // ------------------------------------------------------------------------------------------------------
      //
      //     Immutable Calculator's design allows for very flexible static function unit testing
      //
      // ------------------------------------------------------------------------------------------------------

      // Caters for separate unit tests of each operation
      Console.WriteLine(OpValueI.Create(2, Operation.Start).Execute(3));
      Console.WriteLine(OpValueI.Create(2, Operation.Add).Execute(4));
      Console.WriteLine(OpValueI.Create(2, Operation.Subtract).Execute(5));
      Console.WriteLine(OpValueI.Create(2, Operation.Divide).Execute(6));
      Console.WriteLine(OpValueI.Create(2, Operation.Multiply).Execute(7));

      // Caters for separate unit tests that concatenate two OPValueI
      Console.WriteLine(OpValueI.Create(2, Operation.Start).Concat(OpValueI.Create(3, Operation.Add)));
      Console.WriteLine(OpValueI.Create(2, Operation.Start).Concat(OpValueI.Create(3, Operation.Subtract)));
      Console.WriteLine(OpValueI.Create(2, Operation.Start).Concat(OpValueI.Create(3, Operation.Multiply)));
      Console.WriteLine(OpValueI.Create(2, Operation.Start).Concat(OpValueI.Create(3, Operation.Divide)));

      // Caters for separate unit test of aggregation of a list of OpValueI elements
      var input = ImmutableList.Create(OpValueI.Create(10, Operation.Start),
                                       OpValueI.Create(20, Operation.Multiply),
                                       OpValueI.Create(30, Operation.Add),
                                       OpValueI.Create(40, Operation.Divide));
      Console.WriteLine(OpValueExtensionMethods.Total(input));
    }
  }
}

Finally the output from this
Code:
OpValueI: [value: 10, operation: Start]
OpValueI: [value: 20, operation: Multiply]
OpValueI: [value: 30, operation: Add]
OpValueI: [value: 40, operation: Divide]

5,75
2
6
-3
0,333333333333333
14
OpValueI: [value: 5, operation: Start]
OpValueI: [value: -1, operation: Start]
OpValueI: [value: 6, operation: Start]
OpValueI: [value: 0,666666666666667, operation: Start]
5,75

Conclusion
Our Immutable and a bit more Functional engine has a lot more of the meat of the calculator in the OpValueI.cs file, whereas the CalculatorI.cs file is very small in comparison with its mutable alternative. Secondly you can hopefully see that we have significant more ways to unit test parts of our engine, even down to a single operation without the need to instantiate the calculator.

This is achieved largely by using static methods, which happens to also be implemented as C# extension methods, making them more easier to use in our code.
 
Last edited:
So what's the point
The point if you missed it is that building your codebase using a more Immutable and Functional style approach leads to code that is innately more easier to unit test; and will ultimately lead to less reason for Dependency Injection and Mock test objects in these types of situations.

This again is not to say that there is no place for Dependency Injection and Mocking! There is definitely a need for that but I'd argue that embracing immutability will not only make your code more testable, it will also ensure we only use DI and Mocking where its absolutely necessary. e.g. an obvious situation is with any network communications.
 
Last edited:
Why do these tech explanations inevitably use irrlevant use cases for demonstration. No offence.... but hot dogs?

Ps. You don't have to talk about me in the third person.

Many things in life have dependencies not only code; and hey if hotdogs isn't your thing, then try sushi without fish and/or the rice. :p Point I was trying to express arguably in a more colloquial sense is that some code is wholly dependant in much the same way as a hotdog to the bun and dog; hence the DI pattern tends to be such a focal point in codebases.

Why not use a realistic example that coders can relate to?
Isn't that what the code examples are there for?

Excellent article btw.
Glad you liked it, well sort of. ;)
 
Last edited:
I wasn't specifically talking about you, nor was I assuming that was your own creation, it's just an observation.
Right, I guess I have just always had a hard time with examples that have no real world application in coding.

I have no problem with them, though if they related to the example, it would help put it in perspective.

Sharing info is always appreciated, don't let anyone discourage you from it. I was just pointing out something common to technical tutorials that I find a little frustrating. We're not all propeller heads :D

I've read a few of your informationals here and am suitably impressed with your grasp of the principles. You should really write books. Would be good to see our Unis teaching from locally generated content. Do you lecture perhaps?
No worries...lol.
It is by happenstance my own creation ;) as is the content of these threads, the code and many of the conclusions.

I've never quite been that interested in lecturing; did a bit of it in my earlier years, but gave it up because it cut too much into my free time. I do however on the occasion, privately tutor a few students at varying levels from undergraduate to PHD.

Anyway glad you like the content -- more is planned.
 
Your style of explanation is refreshing and easy to understand (other than hotdogs - maybe I'm just hungry LOL). Maybe not short term goal, but seriously look out for an opportunity to write a book on some or other new tech in future IMO... get in early. You have talent!
hahahaha.... come to think of it... now I'm hungry too.
As for the book; a few of us who fairly frequently participate on the Swift and Rust language projects have as it happens recently been debating the idea of a community driven functional book. It of course will take a lot of effort, and considering many of us are actively balancing work and studies will be a difficult ask to commit the time that's needed for this.

I'll certainly post something about it on MyBB if it ever gets off the ground.
 
I hear you re: the balancing act. It'll probably involve some sacrifices, though you'll have a hard time beating it for resume bling :)
Lol...
I'm long past the need for extra resume bling; 40 years of coding means I've earned that many times over.
 
In the next set of posts; I'll be walking through code for some of the different methods behind "flexible" dependency injection, expect the first post tomorrow and the remainder during the course of the week.

Let me know if you'd like to walk through any methods; I'd appreciate any help.

[)roi(] said:
Method(s)
The following is a summary of the different approaches to work around fixed dependencies in a codebase.
  • Interface / Protocol and Constructor Injection
  • Interface / Protocol and Property Injection
  • Singleton
  • Partial Application: with referential (mutable) types.
  • Paradigm shift: replacing mutable surface with functional purity; including partial application with immutable types.
  • Reader Monad *
  • Free Monad *
* Added for completeness:
As for the Reader Monad and Free Monad, both of these functional approaches will only be briefly explained in this thread so as to not detract from referential (mutable) dependency injection (versus immutability). These anyway as generic algebras deserve a separate thread for a more comprehensive overview.
 
Last edited:
Great posts but geez where do you find the time for this? :oops:
Thanks; glad you like it. :)

Lol... I've always suffered with a bit of insomnia (heredity thing). Which means I'm usually fine to cope with far less sleep than most... other than that I don't spend much time watching either TV / movies or even playing games; rather prefer reading: typically CS and math, and with that writing a lot of code is almost a given.

Plus I find writing blog-like posts are a good way to frame ideas; a few of which we use internally (work) for skills transfer and/or to encourage debate.

Splitting the scope of this thread.
My current thinking is that I should really split off the more strictly functional approaches to DI (partial application / currying, reader monad and free monad) to another thread.

Which basically means I'll curtail the scope of this thread to:
  • Interface / Protocol and Constructor Injection
  • Interface / Protocol and Property Injection
  • Singleton
  • Partial Application: with referential (mutable) types.
That also fits inline with the code I've written for the Github DI solutions in C# and Swift; the functional stuff would have anyway required me to write more code.
 
Thanks; glad you like it. :)

Lol... I've always suffered with a bit of insomnia (heredity thing). Which means I'm usually fine to cope with far less sleep than most... other than that I don't spend much time watching either TV / movies or even playing games; rather prefer reading: typically CS and math, and with that writing a lot of code is almost a given.

Plus I find writing blog-like posts are a good way to frame ideas; a few of which we use internally (work) for skills transfer and/or to encourage debate.
Mostly same here. Sleep very little, don't own a TV. But do have a wife&kids to spend time with and spend time riding my MTB. And yes I agree that writing these posts forces you to organise your thoughts. I also teach youngsters how to code, but these topics are a bit advanced to handle with them at this phase. I rather just show them the right way from the start without using all the terminology etc. I feel that if you teach good habits and tell them a bit of the 'why', half the battle is won.
 
FYI I intend to start posting solutions to the DI challenge tomorrow:
  • Swift code will include solutions for both constructor injection and singleton dependency approaches.
  • C# code will only provide a solution for the singleton dependency approach, because I think both @Spacerat and me have provided & discussed and introduced enough examples of C# constructor injection in other MyBB threads.
As I mentioned I also won't be providing code examples for the more functional approaches to DI i.e. Reader Monad and Free Monad; because I have already covered most of the technique for the Reader Monad in the Temporal Coupling thread; link for that is here:
As for the Free Monad, that is quite a bit more of a complex topic, because Free Monads are a more far reaching / flexible approach for overall architecting of an application around a DSL (domain-specific language) rather than just DI, because its essentially a hybrid of the Monad Algebra and Interpreter Pattern.

Btw for anybody who wants a relatively easy to comprehend introduction to Monoids, Functors, Monads and ultimately their Free alternatives (e.g. Free Monad) -- I suggest you watch this #scaladays presentation:
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X