Friday, January 27, 2006
.c( whytheluckystiff )o. -- Seeing Metaclasses Clearly
This is a useful tutorial on metaclasses by Why.
I wanted to do it all alone, but I will try to resist and see what is already available for me to build on.
Monday, January 23, 2006
Online Community Building Tools
A friend recently called me up asking my help to enhance the ties of some activist groups he is touch with, by using the web.
I have been reading a bit about the web2.0, I had a quick brush with Ning and I mused on philosophical issues.
Now, it is the right time to act.I am pretty certain that what I want to do is to not start some kind of website project from scratch.
The group already has a small website, acting as a web frontend for the organization, but I would rather go for existing services or a mush-up rather then trying to run the infrastructure on our own.The other point is that, while I am very willing to spend time to create new stuff and put ideas together, I am not willing to put much effort into the maintenance.
I also believe this is a chore that the community itself should take care of, learning how to live their own spaces and take care of them.I can see that on the web there are plenty of web2.0 apps, but what I see missing is some kind of glue to put together what I need into a single mushup.
The lack of a single sign-on is particularly critical.
We could go around this, by gathering user subscription requests through the main site and then automate subscriptions to all the different sites of the mush-up, making sure the usernames and passwords are unique.
However this is both labour intensive and it raises some doubts from a privacy point of view. What I am doing now is to look for a all-in-one community container.
Something that provides single sign on to a number of basic services, which allows html customization and enhancements, and that allows easy administration of the system.
These are some promising links that I have found:
Friday, January 20, 2006
Software Roadmap
I have started a number of small projects, both to explore ruby's capabilities and to play with some concepts that I found hard to express in other languages. These projects are still in their infancy, so I haven't put them on rubyforge yet, but I plan to work on releasing them soon.
The projects are:
Agave
a small set of metaprogramming utilities
this is used as an helper to generate code for metaprogramming purposes.
Jazzgarden
smart operations on objects - spreading commands over collections, taking 'slices' from object collections
easy creation of Value Objects
existential quantification
collective action using several alias forms
object slicing
and random picking... I will just give a prozed example here:
SmartStores
implicit mapping of directory and file structures to object aggregates. mapping of file types to classes
Clay
all my intents for Clay are very poor. I'll describe it another time.
what it does is to let you improvise the creation of objects and their attributes without needing to declare any class for them.
Highrise
a small financial framework
The other stuff is a bit more articulate and I'll leave it for another post :-)
The projects are:
- Intent: this one has been released. It provides BDD-like statements on code, as an alternative to regular testing.
- Proze: it translates code - and intents in particular - to readable text. It has been embedded in Intent.
- Agave: a small set of metaprogramming utilities
- Jazzgarden: 'smart' operations on objects - spreading commands over collections, taking 'slices' from object collections
- SmartStores: implicit mapping of directory and file structures to object aggregates. mapping of file types to classes.
- Clay: a nooclay substratum able to provide lots of shorthands and syntactic sugar, including object instantiation without the new method.
- Avocado: support for Concepts and Relationships representations
- Highrise: a small financial framework; yield curves, NPV, etc..
- Gammaray: an easy access to an opengl subset to represent graph relationships in 3d
- Marubatsu: an Intent-first implementation of tic-tac-toe, to be used as an Intent showcase
- Trickle: an Avocado and Gammaray based application that helps you design brainstorming sessions on a number of topics: plots, characters, ideas, etc..
Agave
a small set of metaprogramming utilities
intent of "Generating text from a line of text and variations"
"Dear <title> <person>"
substitute
"<title>" => ["Mr", "Dr", "Mrs"],
"<person>" => ["Smith", "Black", "Grey"],
separator => ", "
should be "Dear Mr Smith, Dear Dr Black, Dear Mrs Grey"
this is used as an helper to generate code for metaprogramming purposes.
Jazzgarden
smart operations on objects - spreading commands over collections, taking 'slices' from object collections
easy creation of Value Objects
class Person
defined by name, surname, age
end
intent of "Reading attributes of an object using 'defined by'"
a person = Person new "Winnie","Pooh",70
a person name should be "Winnie"
a person surname should be "Pooh"
a person age should be 70
existential quantification
intent of "Verifying if exist any"
expect [1, 6, 10] exist any? |n| n>5
dont_expect [1, 6, 10] exist any? |n| n>15
intent of "Verifying at least one element is true"
expect [true, true, false] any true?
dont_expect [false, false, false] all true?
collective action using several alias forms
people = [
"john",
"mike",
"Sam"
]
story "Turning people names to uppercase"
people to upcase should be ["JOHN","MIKE","SAM"]
intent of "Using shortcut form for collective action"
people / reverse
should be ["nhoj","ekim","maS"]
people all reverse everyone capitalize
should be ["Nhoj","Ekim","Mas"]
object slicing
intents "Object Slicing - sorting by property"
people sort by name every name
should be [
"bill","john","mike","paul","sam"
]
and random picking... I will just give a prozed example here:
people = [ "john", "sam", "mike", "frank"]
people pick one
people pick two
people pick two different
SmartStores
implicit mapping of directory and file structures to object aggregates. mapping of file types to classes
def sample smart store
SmartStore new ("intent-files/data")
end
story "Opening up an order"
repository = sample smart store
repository map! [child, of "orders"] => Order
an order = repository
order milan["20050906"]
retrieve
expect an order,
to be Order new
"Chairs" => 18,
"Laptops" => 10,
"Desks" => 7
Clay
all my intents for Clay are very poor. I'll describe it another time.
what it does is to let you improvise the creation of objects and their attributes without needing to declare any class for them.
Highrise
a small financial framework
story "Using Cashflows"
Let's now deal with cashflows
with Conventional discount =
continuously compounded yield
we expect about 271.67748, as the
present value of
Cashflow [
100 at 1 year ,
100 at 2 years ,
100 at 3 years
],
with interest rate at 5 percent
The other stuff is a bit more articulate and I'll leave it for another post :-)
Thursday, January 12, 2006
RSpec as a DSL
I just saw Steven Baker's code from RSpec when pointed there by Victor Cosby. It looks a lot like my Intent framework.
I'll need to do some code reading here
Modern Languages
Tuesday, January 03, 2006
Let the Code DRY - later on..
I finished writing the first draft of the SnapshotEngine code that I wrote about in the previous post. I produced it by copying and modifying snippets of code from the FactEngine, rather than subclassing it.
The result is much much clearer code.
True, there is some duplication, but I am now in a better position to decide what can be abstracted. I have detected a few common methods and I might put them into a common superclass or into a mixin utility module. I might even decide to not abstract it. The two classes could still develop in quite different ways and I may not want to tie them together yet.
Monday, January 02, 2006
Let code DRY on its own: Duplicate, Scan, Refactor, Abstract
Tonight I spent several hours trying to get a piece of code of the Intent framework working. As usual these mistakes tend to be due to the wrong kind of laziness and to a false perception of coding economies.
I had this set of classes handling 'facts' - a recording of certain chosen outputs of a piece of code - and I wanted to add a new feature called 'snapshots'.
When you create a snapshot all the outputs of your program that would go to stdout are implicitly redirected to a file where they are stored and later used for a pretty raw form of regression testing. Snapshots looked to me like a specialized form of Facts, so what I did was to inherit from my FactsEngine class a SnapshotsEngine class, and I started building on that.
However as I was halfway through my top-down implementation (can I test first a test first framework? :-) I started realizing that the workflows of the two engines were not as similar as they seemed to me from an initial high level view. There were a few annoying details that kept getting in the way. Some state that should have been initialized, some step that was skipped, some more steps that needed to be added.
Soon enough the SnapshotsEngine had become an unreadable patch of the FactsEngine, that also had to be 'abstracted' to allow hooks for the SnapshotsEngine. By the way, nothing worked anymore and I started downloading Komodo so that I could use a debugger.
As I am writing I start feeling that resorting to debugging is like an admission of failure. I tried to don't repeat myself by going for inheritance, but I did it a bit too early.
DRY - Don't repeat yourself - should be interpreted in a teleological sense. The code should drift to a DRY state. Starting out DRY is not always the best way to get it right, as it is far too easy to fall into upfront design and believe that you really know things that you don't know only because you are able to generate early abstractions.
I find that the following sequence works well to produce DRY code:
- Duplicate - start out by creating your code by copy and paste. Yes, I mean it. Get the bits that work and produce something working.
- Scan - perform an eye scan of the original code and the duplicated modified code. Spot points of genuine semantic similarity and see if you can make the code more expressive by abstracting them out.
- Refactor - apply a set of refactorings and Scans to extract the pieces of common code.
- Abstract - look for opportunities of abstracting together the common pieces that you extracted as a superclass or as an aggregate/utility class. Look for overall architectural and design patterns of composition and inheritance.
What I found out is that a DRY, but bad abstraction is much much worst than duplicate code. Duplicate code can still be abstracted in a clean way, and it can also be pretty easy on the eye even if it is quite verbose and repetitive. Code that has been badly abstracted is obfuscated and hidden behind ad hoc abstractions and technical tricks that make it unreadable.
So, don't DRY your code. Apply the DuScRAb sequence and let the code DRY on its own.