[Edit]
My original-question was "Why to decide between static and non-static? Both do the same..."
Unfortunately it was edited to a C#-specific question what I really wanted to avoid.
So, let me do some additions:
When I say interface, I don't mean the C#-keyword-interface but what I understand something like a C++-interface: A set of well defined functions to operate with my object. When saying weaken my interface, I mean I have different functions (static/non-static) that do the same thing. My interface is not well defined anymore when there are different functions to do the same thing.
So, as Bob the Janitor posted, I can implement a Validate()-function
Document.Validate(myDocumentObject);
but also
myConcreteDocumentObject.Validate();
To get back to my Copy()-example one could implement Copy() like
myConcreteDocument.Copy(toPath);
but also
Document.Copy(myConcreteDocumentObject, toPath)
or
Document.Copy(fromPath, toPath)
when I think of a folder that contains all the files belonging to my Document (in this case I'm not dependent of a concrete instance - but I'm dependent from other things :)).
In general I'm talking about static methods not static classes (sorry, if I forgot to mension).
But as Anton Gogolev said I think my Document class is not a good example and not well designed so I think I will have to have a look at the Single Responsibility Principle.
I could also implement some kind of ManagerClass that operates with my DocumentClass:
For example:
myDocumentManagerObject.Copy(myConcreteDocumentObject, toPath);
or
myDocumentManagerObject.Copy(myConcreteDocumentObject, toPath);
but if I refer to approach 1) I would tend to create objects that perform their tasks by themself rather than other objects (DocumentManager) that do something with my DocumentObject.
(I hope this will not take the direction of a religious discussion about OOP ;).)
[/EDIT]
At first this seems to be a very basic question like "when to use static methods and when not" but this is something I'm confronted every now and then (and I have difficulties to describe what the real problem is; perhaps it's just to get reasons why (not) to use 1) or why (not) to use 2)).
(Although I'm using C#-Syntax this is not a C#-restricted problem)
In OOP there are two approaches (amongst others) of working with objects:
1) If I want my object to do something, I just tell him to do so:
myConcreteObject.DoSomething();
It's just like talking to an object.
2) Or if you're a fan of static methods:
ObjectClass.JustDoIt();
In some way I think static functions just "feel" better. So I tend to use static methods very often (to be independent from a concrete instance - independency is always good thing).
So, when designing a class I often have to decide if I take approach 1) or approach 2):
Imagine you have a class "Document" which should stand for a document that should be saved into a database:
A Document
Now I'm confrontated with several ways to create this class:
//----- 1) non static approach/talking to objects -----
Document newDocument = new Document();
// Copy document to x (another database, for example)
newDocument.Copy(toPath);
I like this: I tell the document to copy itself to database x and the object does so by itself. Nice.
//----- 2) static approach ----------------------------
Document.Copy(myDocumentObject, toPath);
Why not? Also nice, feels very handy...
So, which one to implement? Both? Or putting the static approach to a kind of helper class? Or choose approach 1) and stick with it to not weaken the interface of my Document-class?
When thinking about both approaches I come to the conclusion that (in theory) one could implement any function as a static function:
Class.Function(aConcreteClassObject, parameters);
but also non-static:
aConcreteObject.DoSomething(parameters);
To give a real-world example:
[EDIT(Added parameter fromPath "Sorry, I forgot")]
//----- 2) static approach ----------------------------
File.Copy(fromPath, toPath); // .Net-Framework-like
[/EDIT]
but also:
//----- 1) non static approach ------------------------
ExampeFileClass fileObject = new ExampleFileClass();
fileObject.Copy(toPath);
or even (kind of OOP-Overkill):
//----- 1) non static approach, too -------------------
fileObject.ToPath = @"C:\Test\file.txt"; // property of fileObject
fileObject.Copy(); // copy to toPath
So, why (not) to use 1) or why (not) to use 2)?
(I would not concentrate on the Document class example too much, since it's more a general question about good class design.)
A woman may choose to have a C-section if she has overwhelming anxiety about a vaginal birth, which may affect her experience of delivery. Women who have C-sections are less likely to suffer from urinary incontinence and pelvic organ prolapse compared with women who deliver vaginally.
Emergencies and complications can lead to a C-section, but you might be surprised to hear that some women choose to have a C-section without a medical reason. This is called an elective C-section.
A C-section might be recommended for women with certain health issues, such as a heart or brain condition. There's a blockage. A large fibroid blocking the birth canal, a pelvic fracture or a baby who has a condition that can cause the head to be unusually large (severe hydrocephalus) might be reasons for a C-section.
Which is safer: vaginal birth or C-section? Vaginal birth is much safer than a C-section for most women and babies. Sometimes a C-section is the only safe option, like when the baby is positioned side-to-side in the belly (transverse lie) or the placenta is covering the cervix (placenta previa).
Here we go.
First off:
So I tend to use static methods very often (to be independent from a concrete instance - independency is always good thing).
Quite the contrary: when using static methods you're very dependent on the concrete instance.
As far as your Document
is concerned, I'd go neither way. You've listed all responsibilities of Document
class, which includes aggregation of data, saving itself to the database plus operations on pages and copying.
This is way to much. Per SRP, each "module" (here "module" used as a catch-all term) should have only one reason to change. Your Document
has lots of responsibilities, hence it has a whole slew of reasons to change. This is no good.
With that in mind, I'd move all logic to other classes with strictly defined responsibilities. A more or less accepted criterion of what to move was introduced, I believe, by either Herb Sutter or Andrei Alexandrescu, an is as follows: all operations (think methods) that can be performed with an object through its public contract should be moved outside the object in question.
You cannot use static methods to implement an interface, and you cannot override static methods. So using static methods means that you are simply not doing OOP.
Think about how you would implement the following functionality using only static methods?
interface IDocument
{
void Print(IDevice targetDevice);
}
IDocument instance;
instance = new PdfDocument();
instance.Print(printer);
instance = new WordDocument();
instance.Print(printer);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With