On Saturday, 16 June 2018 at 19:20:30 UTC, FromAnotherPlanet
wrote:
Hi, I come from a C# background and have been looking at D. How
well does D implement solid principals? I've grown to really
enjoy the SOLID style.
For those unfamiliar, SOLID is an acronym for:
- Single purpose: Meaning every unit of code (whether it's a
function or class) should only
have one reason to change.
- Open/Close principal: Things should be open to extension but
closed to modification. The example I like to use is some sort
of IConverter object. Things can implement IConverter, but if
you need a new way to 'convert' things, you don't extend an
existing object, but instead create a new class that implements
IConverter.
- Liskov substitution principle: Essentially says if I have a
method/function that takes a base class, then the behavior of
that method shouldn't change when passing in derived objects. I
think the term people like to use is whether or not you use a
base/derived class it shouldn't effect the 'correctness' of the
program.
- Interface segregation principal: Essentially breaking the
program up into smaller interfaces. Sometimes only consistent
of one or two methods/properties (can feed into 'S' of SOLID
quite nicely).
- Dependency inversion principle: Things should depend on
abstractions not concretions. Strongly enables dependency
injection.
D seems to have all of the features *required* to make this
happen, but I guess the real question is the last two, and more
specifically the last one.
I am still not a D pro, so some thoughts maybe a bit off...
(intro part)
The "true D" guru's would tell you "in D your typical code would
be mostly ranges(or templates) instead of classes", there is a
good portion truth, but IMHO I find it overly attached.
D uses duck typing for ranges, which means for example very basic
(input) range have this protocol of 3 primitives - popFront(),
front, empty
Ranges heavily used in conjunction with templates, and templates
is static thing, but with clever use of duck typing and that
range protocol usually you don't care about specific type at all
when dealing with ranges. Of course there is polymorphic
interface(as in C#) for ranges too.
Now how it applies to S and O? Ranges is basically an essence of
S principle, they do exactly single thing, and most functions
taking ranges as well.
Just look at this "Sort lines" or some other examples on main
page:
-----------------
stdin
.byLineCopy
.array
.sort!((a, b) => a > b) // descending order
.each!writeln;
--------------
stdin is console input stream, what happens next? all four
functions above operates on ranges, and you can clearly tell what
is their purpose. In this simple example they started operate on
stdin, but in no way limited to it. It can be file, network
stream or whatever else as long it is implements range protocol.
Even though these functions may have different interface this is
still the possibility for open/close principle. (yep, I agree
this isn't the best example)
(sorry, this part is not about SOLID at all)
This is how most of standard library built, sure this isn't C#
BCL and there is so very few things comparing to it, and there is
very few use of polymorthic types in it, but it is highly generic
because of use of templates.
But enough about standard library, you are not forced to do
everything that way, there is of course classes and interfaces,
they work same as in C#, mostly. In own code you can do pretty
much anything you can in C# (not actually sure what you can't)
using classes and interfaces.
I skip the Liskov principle. Classes and interfaces is enough to
cover it, but again D is not limited to them, so you may even
find your own discoveries.
A word about DI in both D and D in SOLID:
This isn't actually limited to just classes, basically it means
that you(client code) provide dependencies(whatever things needed
to be operational) for function/class you use to do the work, so
they don't just 'new' it on their own.
There is even a DI framework[1] (don't mind the names in API, I
think it is heavily inspired by Java's Spring)
Since you are coming from C# background the current state of
tooling may shock you, the standard library is not a swiss knife
and doesn't have all the goodies BCL has, I even pointed out
there is not that much OOP stuff and polymorphism in it. There is
also some language design choices that may surprise(both good and
not so good ways) you.
[1] https://code.dlang.org/packages/aedi