Wednesday, January 28, 2009
pet project idea
Tuesday, January 27, 2009
Failure
"The only failure is the failure to learn from failure" -- Kevin Everett FitzMaurice
A friend of mine notice that in a big company, which recently decided to embrace agile and use Scrum, the Scrum practices are applied in a mechanical way. Actually he called it a 'theater', and he said that the 'agile principles' are important. A colleague had a similar observation, that Scrum is applied in an american-indian-ceremony kind-of way, expecting that the results will fall out of the sky.
Maybe this is related to the 'Shu Ha Ri' training cycle, which:
TheThreeExtremos lately seem to be recommending a ShuHaRi approach to XP: First, follow all the practices. Then, realize TheyreJustRules, and change them (i.e. break some of the original rules). Finally, you don't need to think about the rules anymore. -- GeorgePaci
But in day-to-day business, it is just sloppiness. People don't understand that they are on a learning journey, they don't understand why are they following the practices/rules. Some don't want to learn, they just one to get the job done and go home. Many people are just happy with Ship-It. We've done, it, we are happy, let's go home. No retrospection, no how-can-we-do-it-better-next-time, no 5-whys. There is no striving towards elegance, to do things better. No passion, no motivation. Probably that's why retrospective are the first to be dropped/disregarded.
Does this mean that Agile/(Scrum?) is a culture-thing? How can we change a 'not-my-problem' culture? How can we stop sinking in a pool of problems? How can we start carrying?
ps. via rangawald's delicious, I found Taming Perfectionism.
Friday, January 16, 2009
The Membrane
A: B, A1, A2
B: C, B1, B2, B3
C: D, C1, C2
D: D1, D2, D3
Usually within a certain area/component, we don't need all that object tree, but just a projection/subset of it: eg. IView { A1, B1, C1, D1. }
In practice, the problem is that most of the people will use/scatter these properties all over their code, leading to maintenance monsters:
- navigation is all over the place, violating the 'Law of Demeter'.
- Testing is getting a lot more difficult: in order to test a user of IView you need to instatiate A, B, C, D, these might have good constructors which force you to instatiate other X objects, etc.
- The amount of code using chained objects/train wrecks will crush future refactorings: if you'll want to reverse the navigation from B.C to C.B, you'll have to change all the usage points, the same goes for changing a data type.
Possible solutions:
a. Define the projection as required by that component/use case, eg IView { A1, B1, C1, D1 } (properties, or getter/setter, etc.)
- Define a repository service IRepository.get(...) -> IView
- Work against your abstraction IRepository/IView
The IView/IRepository could build through:
- DTOs mapping (a la dozer & co.)
- wrap & lazy fetch:
View {
ctor(A a) { _a = a; }
A1 { _a.A1 }
B1 { _a.B.B1}
C1 { _a.B.C.C1 }
D1 { _a.B.C.D1 }
}
(a pretty slick solution might be build with LINQ expressions)
In this way we have isolated our component from external changes, we are depending only on our IRepository/IView, future refactorings will afect only that area.
The IRepository/IView abstractions represent the membrane to the external world. (Ralf refers to the pattern as 'external adapter', probably refering to Alistair Cockburn's 'Hexagonal Architecture' paper, I prefer the Alan Kay's metaphor).
b. Instead of defining the projection IView we could add the required operations on A. This has the benefit of aggregating/reusing common operations on A (usually a root entity).
In some cases it might lead to the polution of A: all the properties/operations beneath the A will emerge into A, transforming the tree into a list. Class A will become too big, containing its data, and n+ operations (C# has region-folding, smalltalk has protocols for organizing big classes)
Final thoughts:
- it is not about DDD/Tell don't Ask vs EJB/DTOs vs XXX, but is about isolation/visibility.
- (Unit) Testing asap helps a lot identifying architecture/design smells.
Friday, January 09, 2009
toString or not toString
abstract class Id
T _raw;
Id(T raw) { _raw = raw; }
@Overrride void toString() { return _raw.toString(); }
}
And the Object#toString() documentation says:
/**
* Returns a string representation of the object. In general, the
* #toString method returns a string that
* "textually represents" this object. The result should
* be a concise but informative representation that is easy for a
* person to read.
* It is recommended that all subclasses override this method.
*
* The #toString method for class Object
* returns a string consisting of the name of the class of which the
* object is an instance, the at-sign character `@', and
* the unsigned hexadecimal representation of the hash code of the
* object. In other words, this method returns a string equal to the
* value of:
* getClass().getName() + '@' + Integer.toHexString(hashCode())
**/
What is the problem?
* we heavily use these Ids in a *lot* of places
* id.toString() is used both for Id -> String conversion, as a part of our design and as textual representation for debugging/logging
* to subclasses AID
* if we enrich the Id with more data (eg. a timestamp, or entity version, etc.) we can no longer not add this extra data to its textual representation (eg. logging), since toString() is also used for conversion
** it is very hard to find all the usages of the toString method, since every IDE (and the compiler too) considers this method belonging to the Object and not to the abstraction Id (that's why the @Override is there)
*** if we would have worked in a TDD kind-of way, we probably would have started with an interface, IUniqueId, to which we probably would have added a method asString()
concluding advice: when you model your own domain language/design, be careful what you override.
Thursday, November 27, 2008
Pragmatic Compromise
are not the guys who are going to maintain that code? Have you noticed that these guys bully you into delivering features fast, and later they come complaining ' Why is the quality so poor? '.
Even if quality is not seen as corporate asset, make it a part of your professional ethics.
Tuesday, November 11, 2008
DynamicQuery
(post inspired by AutoBoundary proxymatic)
Apparently yes: check-out the LiquidForm.
There are some other alternatives, but java is not there yet.
Monday, November 10, 2008
Scrum Log
It's amazing how much clarity you get at the end of an iteration: the retrospective.
Monday, November 03, 2008
Dark Syntax Highlight
Brackets: 128,255,0
Keywords: 217,167,15
Comments: 0,185,0
Tasks,ToDos: 0,255,0
Thursday, October 23, 2008
API Usability
The first feedback we get from (unit-)tests. Unfortunately a lot of people don't do that.
Another point is that the tests (partially) lie about how the component is used: they represent how the author assumes the component will be used. Feedback from customers and refactorings should follow...
Wednesday, October 22, 2008
Filter support for PropertyConfigurator
Filters are chained to an appender in a specified order. However, the runtime representation of a .properties files is basically a hashtable, and there is no ordering defined on the keys of a plain hashmap. Any implicit ordering of the lines in the properties file is lost when it is parsed. To overcome this, filters are identified by unique IDs, and filters are added to the appender in the lexicographic order of the IDs.
Keeping the notations used by the log4j source code, filters are configured as follows:
log4j.appender.appenderName.filter.ID=fully.qualified.name.of.filter.class
log4j.appender.appenderName.filter.ID.option1=value1
...
log4j.appender.appenderName.filter.ID.optionN=valueN
You can download the patch directly from the log4j bug tracker. It can be applied to the current HEAD of the 1.2 branch, more exactly to 1.2.15.
Friday, October 10, 2008
Coder
Maybe we should call developers 'anti-coders'.
Tuesday, August 19, 2008
Option/Maybe monad is a generic NullObject
ps. Thought's on Validation: Scala/liftweb has an nice Can.
Monday, August 11, 2008
Scala Marketing Challenge
This is a tough sell. If we look at the Change Function:
ChangeFunction = F(PerceivedCrisis/PerceivedPainOfAdoption).
(btw. read Erik Meijer's paper: 'Confessions of a Used Programming Language Salesman', it's really, really good.)
So we'll have to ask ourselves what problem is Scala trying to solve, and how much it'll cost. IMHO, Scala is trying to make programming easier. It partially addresses the concurrency problem, but it is not its main-focus, I would say is the ScalaActors are a good side-effect of Scala's good (language + library) design.
What we'll have to pay in order to make the 'switch': the syntax is slightly different. Functions are 1st level citizens. (but functions/closure are scary). Operator overload is also scary (funny enough, method overload is not scary: we are afraid of symbols but we are not afraid of words). Then we have for a good generic support we have 'Generics of a Higher Type', type covariance/contra-variance. Pretty scary... booh! Did I say that IDE support is not yet at java's level?
On the other side we have a huge number of java developers. They are satisfied. Not really happy, not really sad. Ok, java is not that great, but it has been like this for years, why change? To be more effective? Probably to sell that to a manager you'll need 5 independent studies to show that scala is better then java and you'll need at least one big company to push the language. ('if they use it, we could use it too')
Regarding concurrency: a lot of java developers have problems to right correct code, so probably concurrency is the least of their problems. Other developers we'll say 'we have java.util.concurrency'.
If you look at the package you'll see they offer concurrency primitives, and to write shared-state concurrent programs is very hard. You'll have to think a lot more about object isolation and the threading context.
In conclusion:
- UserPerceivedCrisis: small
- PerceivePainOfAdoption: big
ChangeFunction -tends-to-> small.
sorry, scala...
Friday, August 08, 2008
Thursday, July 31, 2008
hg vs git, pull+merge vs rebase
GIT encourages rebasing, which leads to rebasing of your public and other people's
code. This is bad.
Mercurial, which hashes a changeset's place in history as well as it's
content, discourages rebasing. Rebasing happens in private with mq patch queues.
Public trees are merged. This is good.
Either style is possible with both tools. The difference is the default emphasis.
Defaults matter.
Linus Torvalds on rebasing:
* http://kerneltrap.org/Linux/Git_Management
* http://lwn.net/Articles/291302/
* http://lwn.net/Articles/291303/
* http://lwn.net/Articles/291304/
Matt Mackall on synchronizing (pull + merge, don't push, don't rebase):
* http://www.selenic.com/pipermail/mercurial/2008-July/020116.html
* http://www.selenic.com/pipermail/mercurial/2008-July/020131.html
Wednesday, July 30, 2008
Thursday, July 24, 2008
Scala Exercises
Anyway some observations:
- it felt like doing the 'Little Schemer' in Scala.
- after doing 3-4 exercises, you feel the need to use/implement fold_left/fold_right.
- maximum is buggy: what's the maximum on an empty list? (the maximum found must be contained in the list;reasoning related to 'Noumenal Null'). I believe that this exercise is a 'tricky question' and instead of throwing an exception, or returning Nothing or Int.NaN, probably the signature should be changed to : maximum(x: List[Int]) : Option[Int]
- In the List's implementation of map/filter/... they use instead of pattern matching if x.isEmpty ... else ( do_something(x.head, x.tail). Probably it's faster than pattern decomposition.
Thursday, June 12, 2008
Lack of Fit
In the early part of his book "Notes on the Synthesis of Form", Alexander describes the concept of "fit". He makes the point that, as humans, we find it very hard to detect "fit", but are well-adapted to detecting "lack of fit". Think of trying to decide if the edge of a piece of wood is straight: the natural thing to do is to put it against a straight surface and see if any gaps show in between. As we try to improve things by reducing the misfit factors, we soon discover that these factors tend to be interrelated: fixing one may exacerbate another, so there is a continuous process of compromise between a number of less than ideal solutions. Intuitively, the less interrelated the misfit items are, the easier it will be to reach a state of acceptable fit. This means that our only hope of reducing misfit factors is if these factors occur in clusters such that the connections between clusters are relatively loose. In application development, this works best if the infrastructure software components also define boundaries between misfit factors.
maybe that's why I'm so critical....
btw. I've started reading J. Paul Morrison's book. I like it, I recommend it.
Thursday, May 22, 2008
LanguageFear
Martin didn't quite specified why we need a DSL:
- Is it for business people to specify their requirements?
- Is it just 'readable' code, for programmers ?
I assume that in both cases we are trying to solve a customer's problem, by building an easy to maintain.
Let's say we use XML. Well that is a bad idea, and Martin knows it: XML is not the answer. It is not even the question. And to write XML is a difficult thing to sell, to a business-man.
Let's say that we go the ANTLR way. Which means from all the languages which are out there, none fits our needs, so we have to build our own. Ok, let's say we've build one. But now we need for our users an editor. We might need good error messages, syntax highlight, the possibility to reuse blocks of code from our programming language. Later we will need to extend our language, without hurting the users. And on the other side, the code generated will be difficult to maintain or to build abstractions on it. That's because code generation is just a raw, automatic, copy-paste machine: it doesn't build any higher-order abstractions. And the direction seems to be wrong: instead of helping our customer, we are baby-sitting our language/editor/infrastructure.
Or we go with embedded DSLs: some languages are better then others. And some languages can be easily integrated with others. Some have heavier syntax making more difficult to create a clean DSL, some are more lightweight, making a perfect match for DSLs.
Or we can go with a 'building material', a 'programmable programming language', or something similar.
Why do people fear of learning of a new language, but they invest uncountable hours in building sand-castles. Even Martin agrees: be a polyglot.
Friday, May 02, 2008
Validation Combinators, a F# prototype
Some strings can be validated as 'standalone' some need to be validate against each other. This validation doesn't belong to the domain for several reasons.
Regrettably, the existing frameworks don't suite our needs.
Trying to decompose the problem, we need:
- a way to get object out of the bag, by name
- a validation method/function which can validate one or more objects
- if the validation fails, we want to collect a 'failed validation message'
- we want to compose these validations: and, or, not, xor, etc...
Let's put that in code:

1 #light
2 open System
3 open System.Collections.Generic
4 open System.Text
5
6 type get_by_name = String -> String
7 type accumulate_message = String -> unit
8 type validator = get_by_name -> accumulate_message -> bool

10 let _and_ (x : validator) (y : validator) = (fun (get_value_from_bag : get_by_name) (accumulate_validation_message : accumulate_message) ->
11 let ok_x = lazy x get_value_from_bag accumulate_validation_message
12 let ok_y = lazy y get_value_from_bag accumulate_validation_message
13 Lazy.force ok_x && Lazy.force ok_y)
14
15 let _or_ (x : validator) (y : validator) = (fun (get_value_from_bag : get_by_name) (accumulate_validation_message : accumulate_message) ->
16 let ok_x = lazy x get_value_from_bag accumulate_validation_message
17 let ok_y = lazy y get_value_from_bag accumulate_validation_message
18 Lazy.force ok_x || Lazy.force ok_y)
19
20 let _not_ (x : validator) = (fun (get_value_from_bag : get_by_name) (accumulate_validation_message : accumulate_message) ->
21 let ok_x = x get_value_from_bag accumulate_validation_message
22 not ok_x)
23
24 let _xor_ (x : validator) (y : validator) = ((_not_ x) |> _and_ y ) |> _or_ (y |> _and_ (_not_ x) )
a lazy value: the value is computed only once, delayed, on demand. In the xor combinator we have used another DSL-friendly feature: partial-function application: ie. if we have a function f(x, y) -> z we could write this as: y |> f x.
Ok, let's see how it works. We define a validator:

27 let is_starting_with (start : String) (name : String) = (fun (get_value_from_bag : get_by_name) (accumulate_validation_message : accumulate_message) ->
28 let value = get_value_from_bag name
29 let ok = value.StartsWith(start)
30 if not ok then
31 let msg = string.Format("{0} '{1}' doesn't start with {2}", name, value, start)
32 accumulate_validation_message msg
33 ok)
Lets define a map of name -> values, and a message accumulator:

36 let map = new Dictionary
37 map.Add("customer","ali")
38 map.Add("buyer", "baba")
39 map.Add("vendor", "nono")
40
41 let get_value (key : String) : String = map.Item(key)
42
43 let acc = new StringBuilder()
44 let accumulate (msg: String) : unit = acc.AppendLine(msg) |> ignore
Lets create a more complex validator:

46 let x = ("customer" |> is_starting_with "a") |> _and_ ("buyer" |> is_starting_with "b") |> _and_ ("vendor" |> is_starting_with "v")
And we can evaluate it:

48 printfn "evaluation: %b messages: %s" (x get_value accumulate) (acc.ToString())
49
50 System.Console.ReadKey()
ps. Look at a better example in a Good Video: "Composing Contracts: An Adventure in Financial Engineering".
pps. here is the code.