In the current project I've introduced some closure/function definitions: functions, actions. The usual stuff. (for reference look at the Scala API, or the google collections, or the Linq Func, or the functional java).
One problem with the current state of closures in java is that, even though objects are closures, and they can be realized with anonymous classes (that's how scala compiler does it), we still have an interface impedance: my function definitions (interfaces) don't match google one's which don't match scala's, which don't match functional javas. So we'll have to write adapters (scala reduces the adapter overhead).
The other problem is that writing closures with anon-classes is a pain: probably that's why Doug Lea is looking into scala. In my project's context we basically/mostly have operations on collections, a sort of
google collections dsl. The only 'ugly' part is the function definition: how the predicates/transformers are defined.
It remindes me of Scala Query & Formal Language Processing in Scala.
I thought of the idea of creating proxies in order to define a function: e.g.
Funcs.on(A.class).getB().create() will create a proxy, will record the method call, and will create a function, which could be called on A objects. I didn't implement that because it seemed such an overkill to create a proxy in order to have a closure.
But now I see that it has been implemented in lambdaj (query collections), and for jpa in liquidform.
What I've missed is that through dynamic proxies we might provide enough information to build queries a la LINQ. (i.e. the information which the c#/vb.net compiler provides on parsing the query,
could be built, manually, by means of dynamic proxies, in java).
---
Update: Looking at Linq/query for java frameworks:
- one does byte code analysis in order to generate the query expression
- one does dynamic proxy
- one uses APT to generate query expressions from entities (something which people wished for jpa 2.0)
Overall I fear/see that the syntax used to build a query-expression-tree might get rather clunky. Maybe in this area Scala could shine.
Monday, August 17, 2009
Wednesday, August 05, 2009
Rx Framework
A new addition to the .Net platform, the Rx framework, aka 'reactive programming', aka 'linq to events'.
Here is the lang.net presentation, the theoretical discussion/explanation/proof about the relation between the Iterator & Observer pattern, and another very good explanation.
The .Net approach is very elegant and reminded me of Glazed Lists and of F# Reactive Programming.
Other thought associations were to F# async workflows, and ruby gui frameworks: bowline based on Titanium, and MonkeyBars based on swing.
Enjoy!
Here is the lang.net presentation, the theoretical discussion/explanation/proof about the relation between the Iterator & Observer pattern, and another very good explanation.
The .Net approach is very elegant and reminded me of Glazed Lists and of F# Reactive Programming.
Other thought associations were to F# async workflows, and ruby gui frameworks: bowline based on Titanium, and MonkeyBars based on swing.
Enjoy!
Tuesday, August 04, 2009
Variations on the visitor pattern
In the current project I've written so far at least 20 class hierarchies (+ their visitors) representing ADTs.
The common scenario is that we have some data which is created by one module and consumed by others. Since the data is shared by 2+ modules, most operations on it require several services from several modules.
So we're out of luck with the Interpreter Pattern, we use the Visitor Pattern/Double Dispatch:
abstract class Expression {
....static class Number extends Expression {
........public final int n;
........Number(int n) { this.n = n; }
....}
....static class Plus extends Expression {
........// since the data is immutable, there makes no sense to create getters
........public final Expression left;
........ public final Expression right;
........Plus(left, right) { this.left = left; this.right = right; }
....}
....// toString, equals, hashCode are implemented with apache commons-lang, based on reflection up to the Expression class
....}
The classic Visitor pattern says:
interface Visitor {
....void visit(Number n);
....void visit(Plus plus);
}
and
abstract void Expression#accept(Visitor v);
....void Number#accept(Visitor v) { v.visit(this); }
....void Plus#accept(Visitor v) { v.visit(this); }
// noticed the copy-paste !? (imagine doing that 40+ times...)
In this example the visitor is a stateful closure which encapsulates a computation its initial data and its final (accumulated) result.
The problem which might arise is how do we handle adding more data type (i.e. classes) to our hierarchy. See the Expression Problem, Extensible Visitor/book (more on google ;).
The proposed solution is to drill a hole in the type safety, in order to make old code compatible with new code:
interface Visitor {
....void visit(Number n);
....void visit(Plus plus);
....void otherwise(Expression x);
}
Now we want to make the visitor stateless, maybe some visitors could be injectable services, eg: ExpressionPrinter, ExpressionEvaluator etc. In this scenario we want to extract the initial data & the result from the visitor:
interface Visitor[A,R] {
....R visit(Number n, A args);
....R visit(Plus plus, A args);
....R otherwise(Expression x, A args);
}
we also need to change the signature of the Expression#accept
abstract [A,R] R Expression#accept(Visitor v, A args);
....[A,R] R Number#accept(Visitor v, A args) { v.visit(this, args); }
....[A,R] R Plus#accept(Visitor v, A args) { v.visit(this, args); }
// noticed the copy-paste !? (imagine doing that 40+ times...)
In this scenarion we can pass the initial data as args , the Expression will pass that to the visitor, which computes the final result R.
Another variation is when the visitor returns an element of the type which he visited. For that we need to modify the Expression:
interface Expression {
....E accept(Visitor v, A args);
....static class Number implements Expression { ... }
}
In this case we might use the A args in order to accumulate other results than the specified E type (we use the A as an accumulator).
If we want to really keep things clean and separate input from output, we could return on accept a tuple[R, E], but that's not needed in 90% of the cases.
Compare that with pattern matching on case-classes:
* no need for toString, equals, hashCode since they are generated by the compiler
* no need for visitors due to pattern matching
** no issues with statefull visitors
* no need for manual written ctors since they are written by the compiler,
* we get cca 50% less code to maintain.
Now scale that to 20+ class hierarchies...
The common scenario is that we have some data which is created by one module and consumed by others. Since the data is shared by 2+ modules, most operations on it require several services from several modules.
So we're out of luck with the Interpreter Pattern, we use the Visitor Pattern/Double Dispatch:
abstract class Expression {
....static class Number extends Expression {
........public final int n;
........Number(int n) { this.n = n; }
....}
....static class Plus extends Expression {
........// since the data is immutable, there makes no sense to create getters
........public final Expression left;
........ public final Expression right;
........Plus(left, right) { this.left = left; this.right = right; }
....}
....// toString, equals, hashCode are implemented with apache commons-lang, based on reflection up to the Expression class
....}
The classic Visitor pattern says:
interface Visitor {
....void visit(Number n);
....void visit(Plus plus);
}
and
abstract void Expression#accept(Visitor v);
....void Number#accept(Visitor v) { v.visit(this); }
....void Plus#accept(Visitor v) { v.visit(this); }
// noticed the copy-paste !? (imagine doing that 40+ times...)
In this example the visitor is a stateful closure which encapsulates a computation its initial data and its final (accumulated) result.
The problem which might arise is how do we handle adding more data type (i.e. classes) to our hierarchy. See the Expression Problem, Extensible Visitor/book (more on google ;).
The proposed solution is to drill a hole in the type safety, in order to make old code compatible with new code:
interface Visitor {
....void visit(Number n);
....void visit(Plus plus);
....void otherwise(Expression x);
}
Now we want to make the visitor stateless, maybe some visitors could be injectable services, eg: ExpressionPrinter, ExpressionEvaluator etc. In this scenario we want to extract the initial data & the result from the visitor:
interface Visitor[A,R] {
....R visit(Number n, A args);
....R visit(Plus plus, A args);
....R otherwise(Expression x, A args);
}
we also need to change the signature of the Expression#accept
abstract [A,R] R Expression#accept(Visitor v, A args);
....[A,R] R Number#accept(Visitor v, A args) { v.visit(this, args); }
....[A,R] R Plus#accept(Visitor v, A args) { v.visit(this, args); }
// noticed the copy-paste !? (imagine doing that 40+ times...)
In this scenarion we can pass the initial data as args , the Expression will pass that to the visitor, which computes the final result R.
Another variation is when the visitor returns an element of the type which he visited. For that we need to modify the Expression:
interface Expression {
....E accept(Visitor v, A args);
....static class Number implements Expression { ... }
}
In this case we might use the A args in order to accumulate other results than the specified E type (we use the A as an accumulator).
If we want to really keep things clean and separate input from output, we could return on accept a tuple[R, E], but that's not needed in 90% of the cases.
Compare that with pattern matching on case-classes:
* no need for toString, equals, hashCode since they are generated by the compiler
* no need for visitors due to pattern matching
** no issues with statefull visitors
* no need for manual written ctors since they are written by the compiler,
* we get cca 50% less code to maintain.
Now scale that to 20+ class hierarchies...
Monday, July 20, 2009
Why Scala
I wanted to write a post 'Why Scala is such a nice/great language', but after I've seen the Martin Odersky presentations at google, and at FOSDEM 2009, Bonas Joner at QCon 2009 'Pragmatic Real-World Scala)', Evan Weaver with 'Improving Running Components at Twitter' and the James Strachan's (of groovy fame) post, an impressive collection of learning Scala resources, I had the impression that there is nothing more to be said (that hasn't be said before).
There is even an online and offline ScalaTour.
Nevertheless, we could/should mention
Java-Basics:
* seamless java integration
* IDE support, build support (maven, ant, sbt, buildr)
* java code coverage
OO-Basics:
* objects all-way-down (see ScalaOverview) (the Smalltalk way)
** primitives are efficiently wrapped & handled by the compiler
* closures/functions are objects too
* multiple trait inheritance (e.g. utility-belt, logging, ...)
Fun-Stuff:
* extensible pattern matching (i.e. switch on steroids on objects)
* functional idioms allowed
* type inference (Hindley-Milner)
* reified generics
* type classes
* elegant solution to the Expression Problem
There is even an online and offline ScalaTour.
Nevertheless, we could/should mention
Java-Basics:
* seamless java integration
* IDE support, build support (maven, ant, sbt, buildr)
* java code coverage
OO-Basics:
* objects all-way-down (see ScalaOverview) (the Smalltalk way)
** primitives are efficiently wrapped & handled by the compiler
* closures/functions are objects too
* multiple trait inheritance (e.g. utility-belt, logging, ...)
Fun-Stuff:
* extensible pattern matching (i.e. switch on steroids on objects)
* functional idioms allowed
* type inference (Hindley-Milner)
* reified generics
* type classes
* elegant solution to the Expression Problem
Monday, July 13, 2009
Moved Code Snippets to Mercurial
I've just moved the tip of the svn trunk to mercurial.
In order to make a push without a password you'll need to modify the .hgrc (specify your google codeusername, password :
[paths]
thought-tracker = https://username:password@thought-tracker.googlecode.com/hg/
In order to get it:
hg clone https://thought-tracker.googlecode.com/hg local_folder
In order to push/publish it (after a local hg ci -Am"some msg"):
hg push thought-tracker
In order to make a push without a password you'll need to modify the .hgrc (specify your google code
[paths]
thought-tracker = https://
In order to get it:
hg clone https://thought-tracker.googlecode.com/hg
In order to push/publish it (after a local hg ci -Am"some msg"):
hg push thought-tracker
Thursday, July 09, 2009
DVCS(hg) vs SVN workflows
Suppose we work in an international company, remote sites, not so good connection between those sites.
We have the following scenarios:
1. We have to do a rather big refactoring, which will take several weeks.
- With svn: we create a 'feature branch' where we'll do the refactoring. We update daily from trunk, we push to trunk regularly/at the end. The feature branch is allowed to be CI-red. (Due to an svn issue merging back-and-forth became a problem for svn-merge-tracking, and we had to do a tree-diff on 2 local sandboxes)
- With hg: you just create a clone-branch, you work on it, you can merge with<->from trunk regularly,
whithout any merging problems.
- Guerilla tactics: shadow the svn trunk/branch with some hg repositories and to the merges with hg (no tree-diff), at the end push the changes to svn
2. Junior (remote) developer needs help fixing a unit-test.
- With svn: do a branch, svn switch to it, push the code with the broken tests, fix them, merge back to trunk.
- With webex: do a remote session an explain the fix
- With hg: just pull the changes, make a fix, push them back to the remote developer. (hint: hg is more network-friendly then svn)
3. An interface between 2 components is changed radically. Both the user & the implementation must be changed.
- With svn: do a branch, do all the changes, merge to trunk
- With hg: change the interface in a cloned repository, then share this repository between the user & implementer. They can work in parallel, the last one finishing pulls the changes from the other one and does the integration.
4. Junior developer, friday@17.00, before a 3 week holiday, wants to commit his _weekly_ changes. He cannot create a local ci build within 1 hour so he doesn't commit anything.
- He shouldn't integrate friday@17.00. (but he did)
- With svn: create a branch, svn switch, push your changes to the server
- With hg: a colleague could pull the changes an do the integration + push the changes, without the need to go through the server.
5. Always keep the code green.
- With svn: run the CI on the pre-commit hook (TeamCity does it). The code get's in the repository only if the build is green
- With hg: maintain 2 repositories: in the 1st one we push the changes, which are peeked by the CI, validate, and on success pushed to another repository. (or just do a rollback; much easier with hg)
A lot of the hg power comes from the fact that is changeset-based (unlike svn) and merges are really easy. Another big plus point goes to the distributed nature of hg: it enables more flexible workflows; in a centralized vcs all the communication is done through the server.
links: hg, git
We have the following scenarios:
1. We have to do a rather big refactoring, which will take several weeks.
- With svn: we create a 'feature branch' where we'll do the refactoring. We update daily from trunk, we push to trunk regularly/at the end. The feature branch is allowed to be CI-red. (Due to an svn issue merging back-and-forth became a problem for svn-merge-tracking, and we had to do a tree-diff on 2 local sandboxes)
- With hg: you just create a clone-branch, you work on it, you can merge with<->from trunk regularly,
whithout any merging problems.
- Guerilla tactics: shadow the svn trunk/branch with some hg repositories and to the merges with hg (no tree-diff), at the end push the changes to svn
2. Junior (remote) developer needs help fixing a unit-test.
- With svn: do a branch, svn switch to it, push the code with the broken tests, fix them, merge back to trunk.
- With webex: do a remote session an explain the fix
- With hg: just pull the changes, make a fix, push them back to the remote developer. (hint: hg is more network-friendly then svn)
3. An interface between 2 components is changed radically. Both the user & the implementation must be changed.
- With svn: do a branch, do all the changes, merge to trunk
- With hg: change the interface in a cloned repository, then share this repository between the user & implementer. They can work in parallel, the last one finishing pulls the changes from the other one and does the integration.
4. Junior developer, friday@17.00, before a 3 week holiday, wants to commit his _weekly_ changes. He cannot create a local ci build within 1 hour so he doesn't commit anything.
- He shouldn't integrate friday@17.00. (but he did)
- With svn: create a branch, svn switch, push your changes to the server
- With hg: a colleague could pull the changes an do the integration + push the changes, without the need to go through the server.
5. Always keep the code green.
- With svn: run the CI on the pre-commit hook (TeamCity does it). The code get's in the repository only if the build is green
- With hg: maintain 2 repositories: in the 1st one we push the changes, which are peeked by the CI, validate, and on success pushed to another repository. (or just do a rollback; much easier with hg)
A lot of the hg power comes from the fact that is changeset-based (unlike svn) and merges are really easy. Another big plus point goes to the distributed nature of hg: it enables more flexible workflows; in a centralized vcs all the communication is done through the server.
links: hg, git
Thursday, May 07, 2009
Subscribe to:
Posts (Atom)