Monday, March 31, 2008
Thoughts on Validation Patterns
The use case is: you have a view with several fields, you need to validate them all, collect all the error messages and focus on the 1st erroneous file.
Since the View represents of a view (projection) over the Domain (Model) the right thing to do is to put the validation in the Model.
The problem arises from the fact the in an ActiveController-PassiveView (aka Model-View-Presenter)
neither the Model nor the View have access to each other:
PassiveView <-- Presenter --> Model.
The latest frameworks use annotations/validators & reflection to map validations ViewField <->
ModelField. (it gets hairier if you need to validate accross several fields, or several objects).
Project X was a .Net project, and .Net 2.0 has a nice feature: implicit type inference for delegates.
Let me explain: if you define an delegate
public delegate R Func<R, A1>(A1 arg1);
and a method
void DoSomething<R,A1>(Func<R,A1> converter) {
... }
then you can pass *any* method which matches the signature of the delegate to the
DoSomething(...) method.
public R MyConverter<R,A1>(A1 arg);
...
DoSomething(MyConverter) // this is valid
Basically, starting with .Net 2.0, closures/functions are 1st class citizens in C#, like any other 'normal' objects. (closures are objects, afterall), with some remarks:
- .Net/C# properties are not methods and cannot be used as such
- in java you have to write a *lot* of anonymous classes, making more difficult to see any benefit. (that's also why an Enumerating component is not appealing in java, in C# the compiler writes the anon. classes for you)
Having said that, we can do a 'manual' binding in Presenter:
ValidationService.bind(PassiveView.GetField(), Model.ValidateField, PassiveView.SetErrorOnField)
the function signature of bind would be
bind<T>(T candidate, Func<bool, T> validate, Action signalError) {
if (! validate(field)) signalError();
}
We can do some more variations on the thema, where the ValidateField will also give us a message saying what was wrong with the candidate.
Variation within variation: message in several languages, should the model be responsible for that, maybe should provide the id to an message which will be translate...
One smell is that, after we have validated the field, by the Model, we pass again the value back to
the model in order to update/create some objects/fields.
Another discussion we had is that a constructor/factory using exceptions for validating arguments is expensive and it fails too fast, since we want to collect all error messages.
So we could replace that with a 2-step process:
maybeValidArgs = factory.Validate(args);
factory.create(maybeValidArgs);
but this is too 'manual'.
Some static typing functional languages have a construct to explicitely define a nullable value. In a c#/java would be:
interface Option<T> {
boolean HasValue();
T GetValue();
}
class Some<T> {
boolean HasValue() -> always true;
T GetValue() -> always the value;
}
class None<T> {
boolean HasValue() -> always false;
T GetValue() -> always throws an exception;
}
Note: In java we have type erasure, so for None<?> we can use a Singleton object.
Now for validation use case we might:
interface Option<T> {
boolean HasValue();
T GetValue();
IEnumerable<String> Errors();// Danger in using Strings !!! String is a 'primitive/sealed' type, which you cannot extend.
}
class Some<T> {
boolean HasValue() -> always true;
T GetValue() -> always the value;
IEnumerable<String> Errors() -> always Empty;
}
class None<T> {
boolean HasValue() -> always false;
T GetValue() -> always throw;
IEnumerable<String> Errors() -> always the errors;
}
Basically HasValue() has the same semantic with IsEmpty(Errors()).
We could change the pull - with a push:
instead of IEnumerable<String> Errors() (pull errors)
we push the errors in a handler
DoWithErrors(Action<IEnumerable<String>> errorHandler) -> Some will call the the action, None will do not
so we could use it like this:
Option<T> maybe = factory.TryCreate(args);
if (maybe.HasValue()) { ... do something with it }
else {
maybe.doWithErrors(View.DisplayErrors);
}
It is not difficult to associate an extra validation action for each arg/candidate field.
We just add optional args to TryCreate(args, params IAction[] actions) which we'll define as
mapping arg1 -> action1, arg2 -> action2. (if we have more args then actions, we don't call any action for them)
eg.
Option<Address> maybe = addressFactory.TryCreate(street_candidate, number_candidate, city_name_candidate, view.SignalErrorStreetName, view.SignalErrorValidateNumberCandidate, view.SignalValidateCityName)
...probably this will evolve to a 'framework', but at least a safe-type one, not string/reflection-based... And probably the annotation/reflection based are more AOP/crosscutting then this will be.
Thursday, March 27, 2008
I don't get Spring
I mean what is the whole idea of wiring by xml? To decouple the wiring from the model.
But if you put the wiring.xml in the jar, so that it lands in the maven repository, to be used by others then it's not really decoupled.
Suppose I have 2 services, with their corresponding interfaces
class Producer implements IProducer { ... }
class Consumer implements IConsumer {
____Consumer(IProducer producer) { ... }
____...
}
what do we put in the xml file ? Basically we repeat the code-lines.
[bean id="..." class="Producer][/bean]
[bean id="..." class="Consumer"]
____[constructor-arg ref="..." index="0"/]
[/bean]
So not only we write again the required dependency, but we do it in xml so that we don't get
the benefit of refactoring (any changes due to renaming are lost).
I've intentionally left the ids unspecified. What should we put in there? The name of the class or the name of the interface?
- If we put the name of the class, then the Consumer-owner must know which class implements the IProducer interface, so a large part of the benefit of using interfaces is lost.
- If we put the name of the interface, in a declarative way, 'I am an IConsumer and I need an IProducer' then we have really duplicated the constructor line and the class declaration line in XML.
And now what about setter-injection. When I look at a class, I look at the interface it implements and what services it needs (in the constructor) to fulfill that contract. But Spring favors 'Setter Injection'.
The Spring team generally advocates the usage of setter injection, since a large number of constructor arguments can get unwieldy, especially when some properties are optional. The presence of setter methods also makes objects of that class amenable to being re-configured (or re-injected) at some later time (for management via JMX MBeans is a particularly compelling use case).
Constructor-injection is favored by some purists though (and with good reason). Supplying all of an object's dependencies means that that object is never returned to client (calling) code in a less than totally initialized state. The flip side is that the object becomes less amenable to re-configuration (or re-injection).
There is no hard and fast rule here. Use whatever type of DI makes the most sense for a particular class; sometimes, when dealing with third party classes to which you do not have the source, the choice will already have been made for you - a legacy class may not expose any setter methods, and so constructor injection will be the only type of DI available to you.
What does it mean for me, as a maintainer: I have to visually scan the file for the setters, wrap each of the private fields in a getter, and put in the getter a check for != null.
What about the argument that a class has too many args in constructor? Isn't that a smell which you should do something about it? (Well actually there are 2 smells: TwoMany-Parameters and ExpensiveSetUp)
What about the argument about 'optional arguments'. Isn't that a NullObject pattern?
So what was the Spring-solution? Autowiring? No, that came later. The Spring-developers said: we need an IDE to manage all that xml. WTF? Instead of getting rid of all that shit, you get a bigger shovel in order to dig deeper?
Now, the world is a little better. Now we have annotations and auto-wiring. But where are these annotations? Probably, declaratively, in a small component, so that other IoC containers could use these annotations for wiring? ... No, they are in the spring-core !!! (the logic is that if you were that smart/stupid to choose spring, then for sure you don't want to change your mind. And if you change your mind, than you should take every file and manually change the annotation and its import).
I really don't get the "significant benefits for many projects, increasing development productivity and runtime performance while improving test coverage and application quality".ps. I had an argument about 'writing boiler-plate code isn't really that bad, since there are tools/IDEs to help you to write that'. I still strongly disagree: if 80% of the life of a software project is spend in maintenance, that means that we read/bug-fix code much more often then we write it. We must strive to READ LESS USELESS CODE.
pps. 'getter/setter methods are evil'
ppps. 'xml wiring is for girls'
ppps. from 'python is not java' : 'XML is not the answer. It is not even the question. To paraphrase Jamie Zawinski on regular expressions, "Some people, when confronted with a problem, think "I know, I'll use XML." Now they have two problems."'
ppps. A more detailed criticism on Spring.
Wednesday, March 26, 2008
blog marketing
There are good tips in there but I'm not sure I want to go aggressive in 'active marketing':
- it is more important that my readers say 'hey this is a cool guy with a good blog' that I say 'I am the greatest'
- more time on marketing means less time on something else (this is probably weak, since I'm not a very effective blogger, but I compensate that by being an avid reader)
- I would prioritize 'more, better content' higher than 'more aggressive marketing'. (I should really write more)
- On the other side is really important to reach people and bring them something. An architect said that the real important think to do is to spread knowledge. Know imagine: instead of sitting here and doing a bad copy of bile-blog, without being even funny, winning about how java is crap, C# is crap, (btw. C# is better than java, sic!), I could/should put some interesting stuff in here and move at least a hand of developers to a better programming world. So if I can reach/teach at least 3 people, and every 'student' will reach at most 3 people and so on, maybe we can reach the critical mass, and move something.... (...or maybe this was just a naive rant)
Tuesday, March 18, 2008
Memoization in Java
IMHO, Mr. White is trying to use big guns (dynamic proxy, reflection) on a small problem: function composition.
If we use/declare an interface:
public interface IFunc1
____R apply(A1 arg1);
}
then we can do implement Memoize1 (on 1 argument) as: (I use the Scala notation for generics [,] since blogger cuts out the xml devil quotes \<,\>)
public class Memoize1[A1, R] implements IFunc1[A1, R] {
____private final IFunc1[A1, R] func;
____private final Map[A1, R] cache;
____public Memoize1(IFunc1[A1, R] func) {
________this(func,new HashMap[A1, R]());
____}
____public Memoize1(IFunc1
________this.func = func;
________this.cache = cache;
}
public R apply(A1 arg1) {
____R result = cache.get(arg1);
____if (result == null) {
________result = func.apply(arg1);
____cache.put(arg1, result);
____}
____return result;
____}
}
That's it. Generic. Composable. Reusable. No schnick-schnack.
Similar memoizer could be provide for IFunc2, IFunc3...
Notice that the Memoize has the same signature as the function it encapsulates.
ps. here is the F# version.