<div dir="ltr">thanks Oliver,<div><br></div><div>I know about is-a and has-a but in this case I just want do what I can do in 2 seconds with MFC just setting a property.</div><div>I've already spent so much time, so the faster solution is the best solution for a so simple problem.</div>
<div>going for validator inheritance.</div><div><br></div><div>pm</div><div> </div><div><br></div></div><div class="gmail_extra"><br><br><div class="gmail_quote">2014-08-08 20:14 GMT+02:00 Till Oliver Knoll <span dir="ltr"><<a href="mailto:till.oliver.knoll@gmail.com" target="_blank">till.oliver.knoll@gmail.com</a>></span>:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Am 08.08.14 18:08, schrieb pmqt71:<br>
> ...<br>
<div class="">> @Oliver:<br>
> yes my problem is that QLineEdit can have only 1 validator. I think<br>
> inherithance should be easier than implementin a ChainValidator, am I right?<br>
<br>
</div>We could now fill pages of discussions about "Inheritance being evil",<br>
"is-a" vs "has-a" vs "uses-a" relations etc., and we'd end up having at<br>
least 10 times more opinions than possible ways of implementing the<br>
solution ;)<br>
<br>
(Just start by asking Google with "Inheritance is Evil" - and you get<br>
the idea ;))<br>
<br>
Here is just a starter link:<br>
<br>
  <a href="http://en.wikipedia.org/wiki/Composition_over_inheritance" target="_blank">http://en.wikipedia.org/wiki/Composition_over_inheritance</a><br>
<br>
<br>
Personally I try to question inheritance as much as possible. The<br>
classic question is "Is a Square also a Rectangle"?<br>
<br>
The best practical explanation - and design question you should ask<br>
yourself whenever you have inheritance in mind - I ever read is: would<br>
an instance of a derived class pass all (possible and sensible) unit<br>
tests of a base class?<br>
<br>
Let's continue with the "Shall I derive my Square class from the<br>
Rectangle class?"-example (which is really a classic, but as such<br>
probably also of "academic value") and let us further assume there was a<br>
unit test which would verify the "area" method.<br>
<br>
So the test would look something like:<br>
<br>
  int width = 3;<br>
  int height = 5;<br>
  Rectangle rect;<br>
<br>
  // setup<br>
  rect->setWidth(width);<br>
  rect->setHeight(height);<br>
<br>
  // exercise<br>
  int area = rect.area();<br>
<br>
  // verify<br>
  assert(area, width * height);<br>
<br>
<br>
Now if you ran the same test, but with an instance of Square, that test<br>
would fail! Why? Because our expectation is that whenever you modify<br>
either width or height, the implementation of a Square would implicitly<br>
set the height or width respective to the same value (otherwise the<br>
instance would not be a square!).<br>
<br>
So after setting the height to 5, the width in above example would also<br>
become 5 and the area would be 25 != 15. Fail.<br>
<br>
<br>
Now would e.g. a UPPERCaseValidator inherited from a<br>
LettersOnlyValidator also falsify unit tests in the same way? Most likely.<br>
<br>
<br>
<br>
There is another reason why particularly in this example I would<br>
definitively opt for the "ChainValidator" (-> composition): it is way<br>
more flexible!<br>
<br>
Let's assume you had 3 validators A, B and C and an additional<br>
"UPPERCaseValidator" (4 classes in total). If you wanted to have for<br>
each A, B, C Validator a combination, you'd have to come up with another<br>
3 classes (deriving each time from A, B and C respective)! So that would<br>
be 7 classes in total to maintain (and if you need to fix something in<br>
your UPPERCaseValidator implementation, you'd need to fix it 3 times in<br>
the worst case - you could share parts of the implementation, but still...).<br>
<br>
<br>
With a composition pattern you'd only need one extra class - a<br>
"ChainValidator" - and you could combine either A, B or C with your<br>
UPPERCaseValidator. Only one additional class, total 5 classes.<br>
<br>
"Well, 5 or 7 classes", what's the big deal anyway!<br>
<br>
Well, here is the deal: just add one more validator D, and your number<br>
of classes grows linearily (and so are the number of implementations to<br>
maintain): not only do you have another class D, but also a new derived<br>
class from D - total 9 classes! For every "base validator" class that<br>
you'd add you would have to implement yet another derived class<br>
(assuming off course that this would make sense to have an<br>
UPPERCaseValidator also validate the output of all A, B, C and D classes).<br>
<br>
<br>
But here's an even bigger deal: Let's assume your boss now tells you<br>
that you need to validate A, B - AND C! Or any combination thereof<br>
(boss: "Oh and yes, off course, don't forget about our new shiny<br>
UPPERCaseValidator class, add that to the mix, too! And the new<br>
validator D that we just purchased yesterday...").<br>
<br>
So would you want to come up with classes such as ABCUpperCaseValidator,<br>
CBAUpperCaseValidator, AUpperCaseValidator, BUpperCaseValidator,<br>
CUpperCaseValidator, ... (the names reflect the "inheritance chain")?<br>
Hopefully not! A combinatorial explosion of possible inheritance<br>
permutations!<br>
<br>
<br>
With the "ChainValidator" however you would simply assemble the<br>
validators like so (pseudo-syntax - you get the idea):<br>
<br>
  AValidator a;<br>
  BValidator b;<br>
  CValidator c;<br>
  UPPERCaseValidator d;<br>
  ChainValidator ca;<br>
<br>
<br>
  // validates a and d<br>
  ca.add(a);<br>
  ca.add(d);<br>
  state = ca.validate(theString, pos);<br>
<br>
  ca.clear();<br>
<br>
  // validats a, c and d<br>
  ca.add(a);<br>
  ca.add(c);<br>
  ca.add(d);<br>
  ca.validate(theOtherString, pos);<br>
<br>
<br>
No need to come up with new classes! And just one single<br>
UPPERCaseValidator implementation!<br>
<br>
(Again, whether the above actually works when it comes to validation, I<br>
don't know - clearly there would be combinations which would not make<br>
sense at all, but in the worst case you'd probably just get an Invalid<br>
state with /any/ input).<br>
<br>
<br>
<br>
Now all that said: the above might be complete "over-engineering" in<br>
your particular case! If you have 2 or 3 very specific cases to validate<br>
"in just that particular dialog" and "I will never ever have the need to<br>
ever re-use those inhertited validation classes anywhere - I swear!"<br>
then go for inheritance - it is not "per se evil" ;) Just know the<br>
consequences.<br>
<br>
<br>
Cheers, Oliver<br>
<div class=""><br>
_______________________________________________<br>
Interest mailing list<br>
<a href="mailto:Interest@qt-project.org">Interest@qt-project.org</a><br>
</div><a href="http://lists.qt-project.org/mailman/listinfo/interest" target="_blank">http://lists.qt-project.org/mailman/listinfo/interest</a><br>
</blockquote></div><br></div>