DCI in C#

44 views
Skip to first unread message

Rune Lund-Søltoft

unread,
Feb 7, 2024, 2:52:47 PMFeb 7
to object-co...@googlegroups.com
I've been playing around with support for DCI in C# lately. I'm by no means done yet but I've reached a point where I'm certain it can be done.

[Context]
public record TestContext(IAccount source, IAccount sink) {
    [Role]
    private abstract class SourceRole : IAccount {
        public IAccount Withdraw(decimal amount){
            this.Balance -= amount;
            return this;
        }
        public abstract decimal Balance {get;set;}
        public abstract string Name{get;init;}
    }
    [RolePlayer(nameof(source))]
    SourceRole Source{get;set;}
    [RolePlayer(nameof(sink))]
    SinkRole Sink{get;set;}
    [Role]
    private abstract class SinkRole : IAccount  {
        public IAccount Deposit(decimal amount){
            this.Balance += amount;
            return this;
        }
       
        public abstract decimal Balance {get;set;}
        public abstract string Name{get;init;}
    }

    public (IAccount source, IAccount sink) Transfer(decimal amount){
        return (Source.Withdraw(amount),Sink.Deposit(amount));
    }
}

The above code is a slightly verbose version of the MoneyTransfer example. Verbose in the sense that I would like to trim away some of the boilerplate. The trick for "injection" is the same as I've used in Marvin and maroon and object identity is preserved. The magic happens in a post-compile step where the il is being rewritten (to something very close to what Marvin would have produced). There's still some way to go. E.g. if you call a role method from within a role method it wouldn't work. There are certain assumptions about the role that are not tested and if broken would result in undefined behaviour. So still work to be done before this small tool can be used to actually support production-ready DCI in C# :-) Still, I feel confident enough about the approach to invite comments and suggestions. 

-Rune

Matthew Browne

unread,
Feb 7, 2024, 10:47:39 PMFeb 7
to object-co...@googlegroups.com

This is great news, congrats on the progress Rune! When you say, "trim away some of the boilerplate", does that include removing all the 'abstract' modifiers?

--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/object-composition/CAF1P%2By%3Dc4NCxEPrqD0hNqdn07g2p__r8mqNicVjpW675qy7PnA%40mail.gmail.com.

Lund Soltoft

unread,
Feb 7, 2024, 11:56:15 PMFeb 7
to object-co...@googlegroups.com
Yes I would very much like to get rid of them. They are in the specific case rather easy to get rid of. Just use a concrete type for the role player rather than an interface. That however is a requirement for the role player I would prefer to avoid. An interface supports runtime duck-typing, so any object capable of playing a role can be allowed to. If I used a concrete type, that would no longer be the case


Mvh
Rune

Den 8. feb. 2024 kl. 04.47 skrev Matthew Browne <mbro...@gmail.com>:



James O Coplien

unread,
Feb 7, 2024, 11:58:35 PMFeb 7
to noreply-spamdigest via object-composition
What in the hell are you folks doing up at this time of morning? ;-)

Samuel Abiassi

unread,
Apr 18, 2024, 8:16:18 AMApr 18
to object-composition
You use IAccount in your exemple, which is, if I assume correctly an interface (excuse my lack of C# knowledge)?

As far as I can remember, one of the things that make DCI interesting is that you should keep everything related to a Context in a single file, improving the mental headspace needed to reason about it.

So here is my question: is it "ok" to declare such an interface elsewhere, and is it even something to look for? It could create abstraction as easily as condensation depending on the reader's insight on the subject matter.

Lund Soltoft

unread,
Apr 21, 2024, 4:20:31 AMApr 21
to object-co...@googlegroups.com
In this example The IAccount is The rolecontract. So its The way The context communicate to the outside world what’s expected of the player. That particular contract is a requirement but not as such part of the implemented logic. If the logic was simply a + b. The the contract could simple be that the player is “numeric”. Depending on the language how you express those contracts vary. C# does allow for a lot of ways to do it. F# has more options other language still even more option and some like JS and python has essentially none

Mvh
Rune

Den 18. apr. 2024 kl. 14.16 skrev Samuel Abiassi <samuel....@gmail.com>:


--
You received this message because you are subscribed to the Google Groups "object-composition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to object-composit...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages