Can Services in a domain-driven design be implemented as C# static class? What are the drawbacks of this choice? Can it be implemented as a non-singleton non-static class?
C# DDD – Drawbacks of Implementing DDD Service as Static Class
cdomain-driven-designstatic-access
Related Solutions
Stateless services don't track information from call to call. This means they can't have instance variables that are set as a result of calling a method. They can have instance variables that the service needs, such as a logger or properties required to operate.
A customer service would not track any information about a customer from call to call. Any information needed to track the customer would be saved externally and retrieved as needed. Usually a database is used for persistence, but in some cases web services may use cookies or other client side mechanisms.
Your class appears to be stateful, although the state is not useful. However, additional methods could make your instance variables publicly accessible. A change as simple as running a generator in an IDE could do that. The following rewrite is stateless. Note that the logger variable, would hold a reference to the a logger and would not contain class state. Initialization and use of the logger has been omitted.
Class DataToCsvFileGenerator{ Static Logger logger; public String createCsv(ResultSet data){ String filePath = createLocalFile(); this.loadDataIntoFile(filePath, data); return filePath; } private String createLocalFile(){ string filePath=//... logic to create file return filePath; } private void loadDataIntoFile(String filePath, ResultSet data){ //function uses filePath to load data } }
Why shouldn't a static class have an internal state?
Because, in the context you're linking to, not having internal state is the DEFINITION of a static class.
Here static class doesn't mean static class
. It means java.lang.Math
. That's a final class full of static methods.
Now that our vocabulary is clear...
@Doval Why shouldn't it? – Aviv Cohn Apr 10 '14 at 14:02
Well...
@Prog Because you're just using global variables in disguise. All parts of your application that make any calls to the static class are now invisibly dependent on each other, and any parts of your application that are dependent on those parts are now indirectly dependent as well, and so on. Mutable state is already a bad idea if you can avoid it. Global mutable state is just a bad idea. – Doval Apr 10 '14 at 14:05
So why
Favor the singleton approach over the static one
Because Murphy was an optimist. You say you only have one DB resource now but suppose that changes?
Designing around the idea that there will only ever be one of anything is forgetting why we solve some problems with keyboards, not soldering irons.
I favor the immutable instance approach (I can't bring myself to say singleton because the GoF singleton pattern is so so so not optimal) because shared mutable state is the real sin.
Give me a way to get an immutable instance that points to the DB resource you want me to talk to and I'll talk to it. Whether it talks to your 1st or 2nd DB resource is none of my business.
That's dependency injection. Counting the number of of DB resources is now a problem pushed out into construction. From there you could push it out to configuration if you wish.
Now I'll admit I'm biased. You don't have to use DI. You can use singleton. Here's a well considered article a comparing Singleton vs Dependency Injection.
I'll jump to the summery:
- If a dependency is ambient, meaning that it is used by many classes and/or multiple layers, use Singleton.
- Otherwise, inject it to the dependent classes using the Dependency Injection pattern.
Which I love because it lets me simply say this: don't write code that puts your DB in case 1.
Best Answer
As far as I can see, making a service class static does not affect its DDD'ness.
There are however other issues with static classes, primarily testability. It becomes difficult to unit test the class, and even more difficult to test classes that have dependencies to your static class.
Therefore I would always create the class as an instance class, and define an interface for it. This allows me to replace the class by test doubles when testing other classes that have a dependency to this class.
But it doesn't make it more DDD, it just makes it more TDD :)