Thursday, 9th September 2010.

Posted on Sunday, 30th November 2008 by charpi

Your company wants to make money as fast as possible. To make money,
it needs strong and competitive teams. Your team is competitive,
someone (probably some manager who don’t know you) asks it to perform
more tasks and – normally – gives you complementary means called in
another world people or resources.

Well, now that you have more men, how can you give to your boss what
he wants: more productivity ? How can you keep the competitiveness of
your team with all those “newbies” on your project ?

In the ancient age, your ancesters had a solution to integrate new
employes in teams. The first thing that the employe had to do – of
course after having filled out all administrative stuff to have access to
the car park, an e-mail account and other important things like that -
was to convert him-self to the project religion. All precepts of
this religion was wroten in holy papers that everybody called
documentation. After, and only after that the newbie known entirely
the documentation, the project chief (leader isn’t the right term)
assigns him a technical feature to test his capabilities. The feature
has to be not too risky otherwise the entire project might been
imperiled.

In the ancient age, employes spent weeks, sometimes monthes before to
give value to his boss. Due to moderns economics constraints with situation isn’t suitable anymore.

Try to think about an agile world where all companies will be
eXtreme companies. To produces money, they know that the most
important thing in the process is MEN. People make you
win or loose money. To be sure to win money, you must ensure to build
sort of team spirit where everyone is
optimized for the process. In the new world, the question
became how to optimize the way my teams work together ?

In an agile team, documentation is almost only oral so the first
step of the traditional integration will be very short. As a
replacement, we can imagine a special meeting where the whole
team could present the project (features, design) to the
newbie. This kind of meetings are great, but not essential to make
people productive for the day after.

Some agile teams use PairProgramming. Integrating the
newbie in a pair rotation, he’ll be able to talk to each other member
of the team, to share things with them. This point is the answer to
the human integration, but we was talking about money. His
productivity will increase as fast as pairs switch. At each task, he
will discover a new part of the application and his technical skills
will be improved. With a better knowledge of the system, he will be
confident enough to be active in the team life (estimation, design
discussion).

Tags: , ,
Posted in Uncategorized | Comments (1)

Posted on Saturday, 29th November 2008 by charpi

Looking for some emacs hacks, I re-discovered Sacha Chua’s blog.
This blog contains some nice emacs hacks (like how to blog
from emacs) but also a lot of posts about GenY and social networking.
I let you learn more about her and her job by reading her blog but
one of her talk (Networking 2.0, blogging your way out of a job and into a career)
lets me realize that I’m not blogging enough.
More precisely that I don’t pay enough attention to my social
network. Even if I know that it is important, I didn’t made the
effort to expand it and give it a real value.
In consequence my first decision is to really use this blog to share my thoughts and
my skills. The first expected velocity is at least one article/post per week.
I hope the GTD method will help me to succeed to keep the rythm.

Tags:
Posted in Uncategorized | Comments (2)

Posted on Sunday, 19th October 2008 by charpi

I worked on erl_mock in order to publish my spike around mocks in
erlang. When I was almost ready to make the package, something interesting happened: my tests failed.

More precisely, they failed when run by the ‘future’ version of extremeforge.
After the first surprise, I find the reason. Extremeforge use 2 nodes,
the first one will find, order tests then send all code on the second
node in order to be run. Like this, extremeforge keeps the first node
totally safe if for some reasons a test module (or applicative module)
gets wrong.

As my library intends to load, unload dynamically modules the test
node is lost because it can’t find the beam files.

Conclusion: Don’t use mock, :-)

Anyway I’ll publish my library soon

Tags: , ,
Posted in Uncategorized | Comments (0)

Posted on Thursday, 9th October 2008 by charpi

In my previous post, I described a way to mock module by replacing
them. Today, I’ll post a version closer to other mock
library. Basically, I create on mock module on the fly and forward all
calls to a process. You can tell to this process how to answer for
each calls.
Here is the test :

%%% Copyright (c) 2008 Nicolas Charpentier
%%% All rights reserved.
-module(mock_test).

-export([test /0]).

test () ->
    lazy_way () ,
    dynamic_way (),
    ok.

lazy_way () ->
    "i'm the production code" = my_module: who(),
    mock: replace_module (my_module, my_mock_module),
    "I'm the mocked code" = my_module: who (),
    mock: uninstall (my_module),
    "i'm the production code" = my_module: who (),
    ok.

dynamic_way () ->
    "i'm the production code" = my_module: who (),
    {pong,host} = my_module: ping (host),

    mock: start (),
    mock: add_module(my_module),
    mock: set_answer (my_module, who, "I'm the mocked code"),
    "I'm the mocked code" = my_module: who (),
    mock: set_answer (my_module, who, "Oops did it wrong"),
    "Oops did it wrong" = my_module: who (),

    [{my_module, who, []}, {my_module, who, []}] =  mock: calls (),
    [] =  mock: calls (),

    case catch my_module: ping(host) of
        error_no_response -> ok;
        Other -> exit({unexepected_mock_response, Other})
    end,

    mock: set_answer (my_module, ping, {pang, mock_host}),
    {pang, mock_host} = my_module: ping(last_host),

    [{my_module, ping, [host]},
     {my_module, ping, [last_host]}] =  mock: calls (),

    mock: uninstall (my_module),
    "i'm the production code" = my_module: who (),
    {pong,host} = my_module: ping (host),
    ok.

and the implementation

%%% Copyright (c) 2008 Nicolas Charpentier
%%% All rights reserved.
-module(mock).

-export([replace_module /2]).
-export([uninstall /1]).

-export([start /0]).
-export([add_module /1]).
-export([set_answer /3]).
-export([calls /0]).

replace_module (Module, Mock_module) ->
    uninstall (Module),
    {ok, Binary} = file: read_file (code: which (Mock_module)),
    File_name = atom_to_list (Module) ++ ".erl",
    code: load_binary(Module, File_name, Binary),
    ok.

uninstall (Module) ->
    code: purge (Module),
    code: delete (Module).

start () ->
    Pid = spawn_link (fun () -> mocker ([],[]) end),
    register(mocker, Pid),
    ok.

add_module (Module) ->
    Forms = forms (Module),
    uninstall (Module),
    {ok, _, Binary} = compile: forms(Forms, [report]),
    code: load_binary (Module, "foo.erl", Binary),
    ok.

set_answer (Module, Function, Answer) ->
    mocker ! {set_answer, Module, Function, Answer},
    ok.

calls () ->
    mocker ! {self(), calls},
    receive
        {calls, Calls} ->
            Calls
    end.

forms (Module) ->
    Exported_functions = find_exported_functions (Module),
    Fun = fun (F) -> function_to_form (Module, F) end,
    Functions_forms = [Fun(F) || F <- Exported_functions],
    [{attribute,1,module,Module},
     {attribute,3,export,Exported_functions}] ++
        Functions_forms  ++
        [ {function,16,wait_response,0,
           [{clause,16,[],[],
             [{'receive',20,
               [{clause,20,
                 [{tuple,20,[{atom,20,response},{atom, 20, undefined}]}],
                 [],
                 [{call,20,
                   {atom,20,throw},
                   [{atom,20,error_no_response}]}]},
                {clause,20,
                 [{tuple,20,[{atom,20,response},{var,20,'Response'}]}],
                 [],
                 [{var,19,'Response'}]}
                ]}]}]},
          {eof,23}].

function_to_form (Module, {Function, Arity}) ->
    Parameters = parameters (Arity),
    Parameters_cons = parameters_cons (Arity),
    {function,5,Function,Arity,
     [{clause,5,Parameters,[],
       [{op,6,'!',
         {atom,6,mocker},
         {tuple,6,
          [{call,6,{atom,6,self},[]},
           {atom,6,forward},
           {atom,6,Module},
           {atom,6,Function},
           Parameters_cons]}},
        {call,8,{atom,8,wait_response},[]}
       ]}]}.

parameters (0) ->
    [];
parameters (N) ->
    Seq = lists: seq (1,N),
    F = fun (I) ->
                String = lists:flatten (io_lib: format ("Var~p",[I])),
                list_to_atom(String)
        end,
    [{var, 6, F(I)} || I <- Seq].

parameters_cons (N) ->
    parameter_list_form (parameters (N)).

put_parameter_in_call (Parameters) ->
    list_to_tuple (transform_list_to_cons (Parameters)).

transform_list_to_cons ([]) ->
    [nil, 6];
transform_list_to_cons ([H|T]) ->
    [cons, 6, H, put_parameter_in_call (T)].

parameter_list_form ([]) ->
    {nil,6};
parameter_list_form (Variable_forms) ->
    put_parameter_in_call (Variable_forms).

find_exported_functions (Module) ->
    Module_info = Module: module_info (),
    All_exported = proplists: get_value (exports, Module_info),
    lists: filter (fun ({module_info,_}) ->
                           false;
                       (_) ->
                           true
                   end, All_exported).

mocker (Modules, Calls) ->
    receive
        {From, calls} ->
            From ! {calls,lists: reverse (Calls)},
            mocker (Modules, []);
        {set_answer, Module, Function, Answer} ->
            New_modules = proplists: delete ({Module, Function}, Modules),
            mocker ([{{Module, Function}, Answer}|New_modules], Calls);
        {From, forward, Module, Function, Args} ->
            Response = proplists: get_value ({Module,Function}, Modules),
            From ! {response, Response},
            mocker (Modules, [{Module, Function, Args}|Calls])
    end.

Tags: ,
Posted in Uncategorized | Comments (7)

Posted on Wednesday, 8th October 2008 by charpi

In my previous post, I wrote a test to specify a lazy
mock. In my mind, a lazy mock consists to replace the implementation
of one module by another one at runtime.

Here is the implementation of the lazy mock test

-module(mock).

-export([replace_module /2]).

replace_module (Module, Mock_module) ->
    uninstall (Module),
    {ok, Binary} = file: read_file (code: which (Mock_module)),
    File_name = atom_to_list (Module) ++ ".erl",
    code: load_binary(Module, File_name, Binary),
    ok.

uninstall (Module) ->
    code: purge (Module),
    code: delete (Module).

The tricky thing is that your mock module must not be a valid
erlang beam file. The code_loader use the beam file name to locate the
code load but the VM expected that the module declaration in the file
got the same name than the file.
In order to use my implementation of the lazy mock your mock
module must have the same module declaration than the real
implementation.
Here is the content of the source file my_mock_module.erl:

-module(my_module).

-export([who /0]).

who () ->
    "I'm the mocked code".

Tags: ,
Posted in Uncategorized | Comments (0)

About me Downloads