ITDevCon 2014, Call4Papers

Android, DMVCFramework, Design Patterns, Embarcadero, Events, ITDevCon, ITDevCon2014, Programming, Projects, RTTI, bit Time Software, iOS Comments Off

ITDevCon 2014

ITDevCon 2014

Dear potential ITDevCon speaker,

As every year, I’m building the agenda for next ITDevCon that will be held next october 23th, 24th in Milan (Italy), in a new location.

This will be the 6th edition ( we’re getting conference experts J )

The call for papers are officially open right now, so if you want to propose some speeches, I’ll be glad to see it.

As usual, for the Call4Paper I need:

  • Title (for every talk)
  • Abstract (for every talk)
  • Difficulty level (for every talk. Difficulty level is a scale from 1 to 3 with the following mean: introduction, intermediate, advanced)
  • Speaker’s photo
  • Speaker’s profile

I’m looking forward to your proposal. The call4papers ends at Aug 31st, 2014 but if you have *VERY* interesting topic to propose, propose it… I’ll try to arrange the schedule and fit it in the agenda.

Send your proposal to call4paper(at)

Proposals will be evaluated and the speakers will be contacted ASAP.

This year topics will be the following:


  • What’s new in the latest Delphi versions

  • FireMonkey platform

  • MacOSX development

  • Android development

  • iOS development

  • Windows development

  • Mobile development (Android+iOS)

  • Develop UIs for different devices (smartphones, tablets, TV, watch etc)

  • BaaS integrations

  • LiveBindings ®

  • Delphi best practices

  • Design Patterns

  • DataSnap

  • DelphiMVCFramework

  • Arduino e/o Raspberry Pi

  • Web Application with Delphi

  • TDD and Unit Tests

  • Agile methodologies

  • ORM and other data access patterns

  • Using NoSQL databases (even to speed up your VCL software)

  • FireDAC

  • UI, UX, optimization for mobile and desktop


  • Real use cases for extended RTTI, Generics e AnonMethods

  • RESTful interfaces design and development

  • Architectures

Target audience

  • Software architects
  • Software developers
  • Project managers
  • IT managers
  • Trainers

The conference web site is (2014 version is still under construction).

Do you want to see a particular topic or have a suggestion for ITDevCon2014? Let me know

Thanks and see you at ITDevCon 2014.

DelphiMVCFramework is now Open Source!

DMVCFramework, Delphi XE4, Delphi XE5, MVC, RTTI 3 Comments »

DelphiMVCFramework Logo

Yes, just after 1 year of development, and a couple of big projects developed with it, the DelphiMVCFramework has been published as OpenSource.

The project is on google code svn

I’ll talk about it at ITDevCon2013 (

In the trunk there are many samples and I’m planning to put many others.

Main DMVCFramework features

  • RESTful (RMM Level 3) compliant
  • Server side generated pages using eLua (Embedded Lua)
  • Messaging extension using STOMP (tested with Apache Apollo and Apache ActiveMQ)
  • Can be used in load balanced environment using memcached (
  • Fancy URL with parameter mappings
  • Integrated RESTClient
  • Works with XE4 and XE5 (tested, but should works also on XE3 and XE2)
  • Experimental support for IOCP
  • Simple, but very very simple, to use…

It contains also a lot of indipendent code that can be used in other kind of projects.

These are the most notable:

  • Mapper (convert JSON <=> Object, ObjectList <=> JSONArray, ObjectLists <=> DataSets)
  • LuaBinding (integrate Lua script into Delphi native code)
  • LuaTextFilter (convert eLua into plain Lua executable script just like JSP)
Currently DMVCFramework use Embarcadero WebBroker framework, but is not tied to it. I’m working on a version that use IOCP (that is 10 times faster than plain WebBroker) and other web libraries for Delphi.
Code is enough stable and is already used in big production system.
There are a couple of bugs that affect WebBroker and so, DMVCFramework.
In our system, I’ve applied some patches to solve these problems. If you need those patches, ask me (I cannot publish the full code because it is Embarcadero licensed code).
The bugs are:
And another bug that affect also DataSnap and TIdHTTPWebBrokerBridge based projects.
Code is tested on XE4 and XE5 but should works also on XE3 and XE2.

Delphi MVC Web Framework - “Hello World”

Delphi XE, Delphi XE2, Design Patterns, Embarcadero, MVC, RTTI, dorm 6 Comments »

This is the first “Hello World” for my Delphi MVC Web Framework.

program DelphiMVCWebFramework;
  4. uses
  5.   System.SysUtils,
  6.   MVCEngine in 'MVCEngine.pas',
  7.   BaseController in 'BaseController.pas';
  9. var
  10.   mvc: TWebMVCEngine;
  11. begin
  12.   mvc := TWebMVCEngine.Create;
  13.   mvc.AddRoute('/', procedure(Context: TWebContext)
  14.     begin
  15.       Context.Write('Hello World');
  16.     end).Start(8080);
  17.   ReadLn;
  18.   mvc.Free;
  19. end.

Features list (some of them are in the internal roadmap)

  • Completely MVC
  • Addressable with servername/controllername/actionname?par1&par2
  • Addressable with servername/controllername/actionname/par1/par2
  • Can also use anonymous methods as actions for very simple app (in the sample)
  • Really RESTful (Level 3 of the Richardson Maturity Model)
  • Fully integrable into WebBroker and DataSnap
  • Supports multiple resource rapresentations
  • Completely customizable routing using internal formatting or regex
  • Inspired to ASP.NET, Sinatra, Java Spring MVC, Java Restlet
  • Scriptable views support (Pascal, Razor, Lua)
  • Component based
  • Session support
  • ORM support using dorm
  • Classic TDataSet support
  • State server to support real loadbalancing using reverse proxy
  • Can be deployed as standalone (in the example), ISAPI dll and Windows Service
  • Fully support https
  • More to come…
  • This framework is still under development.

    Are you interested in? :-)


    The project is open source and you can fint it here

In the core of LiveBindings expressions of RAD Studio XE2

Delphi XE2, Design Patterns, Events, ITDevCon, ITDevCon2011, RAD Studio XE2, Uncategorized 5 Comments »

WARNING! I’ve been authorized by EMBARCADERO to write about RAD Studio XE2.

RAD Studio XE2 is full of nice and exciting features. One of the most awaited of them is the LiveBindings.

The LiveBindings is available to the VCL and the new FireMonkey framework and allows to connect a property object to another using an expression and a set of observers.
Let’s say Edit1.Text “is binded to” Person1.Name also in a bidirectional way. The “link” between a property (or a group of properties) and another property can also be very complex.

The following is an example of a complex bind expression that return a value:

  1. "This is a full name: " + Trim(ToUpperCase(FirstName)) + ", " + Trim(ToUpperCase(LastName))

I’ve waited LiveBindings for ages and now they are here!

So, let’s look a deep inside to the core of livebindings expression evaluator,
the TBindingExpression.

The TBindingExpression is an abstract class that allows to evaluate an expression. But, what’s an expression? An expression is a string that return, or not return, a value. You could see an expression as a little function or procedure.
To explain the concept, I’ve build a simple expression interpreter using an XE2 beta version.

It is very simple but shows the power of expression engine.
This is the scriptengine while evaluates a simple arithmetic expression.

The expression engine is not only a “static” evaluator. Using the powerful Delphi RTTI introduced in Delphi 2010, you can also allows the expression to “read” and “call” property and method of your Delphi objects!!

So, now, some code is needed.

As you can see, you can “register” some association between a real object and an alias in the expression. So, if my object are declared as the following:

I can use a expression as the following:

Going further, you can call methods in your expression!

So, if you have methods declared as following:

You can use the following expression:

Obviously, when you link a property to another you should not use dialogs in the expressions, but this feature is VERY powerful.
You can create different expression and use them as a custom calculator for specific business rules. The expressions are strings, so you can store them in a file or in a database and use them as needed. The expression engine is not a complete scripting language, but it can be used (and abused) in a very broad range of situations.

For complex business rules, I hate the classic chain

  1. Data->TDataSet->DBAware

so I usually use a DomainModel that use datasets only to read data.

The LiveBinding allows me to use (for complex business rules) the following chain

  1. Data->ORM->DataObjects->Bindings->VisualControls

This is only an introduction to the LiveBingind engine. ASAP I’ll post other articles about it.

I’ll talk about the livebinding engine at the ITDevCon2011 conference. Will be you there?

RAD Studio XE2 will be officially presented all over the world during the “RADStudio XE2 World Tour”.
You can find the list of all launch events in the RADStudio XE2 World Tour page.

I’ll be a presenter at 3 launch events in Italy and United Arab Emitates.
These are the events where I’ll be (click to register):

  • 19th Dubai, United Arab Emirates
  • 21nd Milan, Italy
  • 22nd Rome, Italy

Stay tuned.

Sneak preview about DORM, The Delphi ORM

Design Patterns, Programming, RTTI 25 Comments »

My yesterday post about this busy time, have raised some interest about DORM, the Delphi ORM.

So, also if I still haven’t released any files, wish to expose some internals about DORM.

DORM is an implementation of the DataMapper design pattern written having Hibernate in mind.

It’s completely unit tested and have the following features:

  • External file mapping. (JSON format)
  • Persistence ignorance (every TObject can be persisted)
  • Support for One-One and One-Many relations (still no many-many)
  • Support for LazyLoading (you can enable§/disable lazyloading by file or by code by per-basis needs)
  • Support for IdentityMap
  • Support for custom “finder” (you can still use complex SQL if you want)
  • Complete support for CRUD
  • Transactions
  • Built in logging system to log *EVERY* sql or action performed by the framework
  • Opened to multiple data access strategies (interfaced based, not inheritance based) for use with different database (now I’ve developed the firebird one using DBX)
  • Caching for RTTI (the TSession object have a single TRttiContext holding ALL metadata)

Code is still under heavely development.

Those are 2 test-method to show the use of DORM:

  1. TPerson = class(TObject)
  2. property Phones: TdormCollection…. //implements IList
  3. end;
  5. TPhone = classs(TObject)
  6. end;
  8. //and now the unit tests
  10. procedure TTestDORMHasMany.Setup;
  11. begin
  12.   Session := TSession.Create;
  13.   Session.Configure(TStreamReader.Create('dorm.conf'));
  14. end;
  16. procedure TTestDORMHasMany.TearDown;
  17. begin
  18.   Session.Free;
  19. end;
  21. procedure TTestDORMHasMany.TestHasManyLazyLoad;
  22. var
  23.   p: TPerson;
  24.   t: TPhone;
  25.   guid: string;
  26. begin
  27.   p := TPerson.NewPersona;  //static method. Return a fully populated TPerson object
  28.   try
  29.     t := TPhone.Create;
  30.     p.Phones.Add(t);
  31.     Session.Save(p);
  32.     guid := p.guid;  //GUIDs, or other PK types, are generated automagically by DORM. Obviously there is a specific class loaded to do this specified in the dorm.conf file)
  33.   finally
  34.     Session.Commit;
  35.   end;
  36.   Session.StartTransaction;
  38.   // Test with lazy load ON
  39.   Session.SetLazyLoadFor(TypeInfo(TPerson), 'Phones', true);
  40.   p := Session.Load(TypeInfo(TPerson), guid) as TPerson;
  41.   try
  42.     CheckEquals(0, p.Phones.Count);
  43.   finally
  44.     Session.Commit;
  45.   end;
  47.   Session.StartTransaction;
  48.   // Test with lazy load OFF
  49.   Session.SetLazyLoadFor(TypeInfo(TPerson), 'Phones', false);
  50.   p := Session.Load(TypeInfo(TPerson), guid) as TPerson; // Without commit, AV becouse IdentityMap doesn't work properly
  51.   try
  52.     CheckEquals(1, p.Phones.Count); // Child objects are loaded
  53.   finally
  54.     Session.Commit;
  55.   end;
  56. end;
  58. procedure TTestDORMHasMany.TestLoadHasMany;
  59. var
  60.   list: IList;
  61.   t, t1: TPhone;
  62.   p: TPerson;
  63.   guid: string;
  64. begin
  65.   p := TPerson.NewPersona;  //static method. Return a fully populated TPerson object
  66.   try
  67.     t := TPhone.Create;
  68.     t.Numero := '555-7765123';
  69.     t.Kind := 'Casa';
  70.     p.Phones.Add(t);
  72.     t1 := TPhone.Create;
  73.     t1.Number := '555-7765123';
  74.     t1.Kind := 'Casa';
  75.     p.Phones.Add(t1);
  76.     Session.Save(p); // save Person and Phones
  77.     guid := p.guid;
  78.   finally
  79.     Session.Commit;
  80.   end;
  82.   Session.StartTransaction;
  83.   p := Session.Load(TypeInfo(TPerson), guid) as TPerson;
  84.   try
  85.     CheckEquals(2, p.Phones.Count);
  86.   finally
  87.     Session.Commit;
  88.   end;
  89. end;

Mapping, contained in a file called “dorm.conf”, is similar to the following:

  1. {
  2.   "persistence": {
  3.     "database_adapter": "dorm.adapter.Firebird.TFirebirdPersistStrategy",
  4.     "database_connection_string":"\\MyProjects\\DORM\\experiments\\dorm.fdb",
  5.     "username": "sysdba",
  6.     "password":"masterkey"
  7.     },
  8.   "config": {
  9.     "package": "",
  10.     "logger_class_name": "dorm.loggers.FileLog.TdormFileLog"
  11.   },      
  12.   "mapping":
  13.     {      
  14.       "TPerson":
  15.       {
  16.         "table": "people",
  17.         "id": {"name":"guid", "field":"guid", "field_type":"string", "size": 100, "default_value": ""},
  18.         "fields":[
  19.           {"name":"firstname", "field":"first_name", "field_type":"string", "size": 100},
  20.           {"name":"lastname", "field":"last_name", "field_type":"string", "size": 100},
  21.           {"name":"age", "field":"age", "field_type":"integer"},
  22.           {"name":"borndate", "field":"born_date", "field_type":"date"}
  23.           ],
  24.         "has_many":[{
  25.           "name": "Phones",
  26.           "class_name":"TPhone",
  27.           "child_field_name":"guid_person",
  28.           "lazy_load": false
  29.         }],
  30.         "has_one": {
  31.           "name": "car",
  32.           "class_name":"TCar",
  33.           "child_field_name":"guid_person"
  34.         }
  35.       },
  36.       "TPhone":
  37.       {
  38.         "table": "phones",
  39.         "id": {"name":"guid", "field":"guid", "field_type":"string", "size": 100, "default_value": ""},
  40.         "fields":[
  41.           {"name":"number", "field":"number", "field_type":"string", "size": 100},
  42.           {"name":"kind", "field":"kind", "field_type":"string", "size": 100},
  43.           {"name":"guid_person", "field":"guid_person", "field_type":"string", "size": 100}
  44.           ]
  45.       }
  46.     }
  47. }

The PODO (Plain Old Delphi Objects) can be binded to the VCL controls with a set of MediatingView (Model-GUI-Mediator Pattern) with an Observer mechanism to mantain things in synch.

Any comments? Someone interested?

A Simple start with MVP in Delphi for Win32, Part 2

Delphi 2010, Delphi Dependency Injection, Design Patterns, MVC, MVP, Uncategorized 4 Comments »

Some month ago I wrote a simple article about an MVP variant called PassiveView.
That example was very simple. Now I’ll present a more “advanced” version of that example.

The main problem with first example was the following method:

  1. procedure TfrmCalculatorView.FormCreate(Sender: TObject);
  2. begin
  3.   //Link controls with related interface
  4.   IFirstOperand := TGUIEdit.Create(EditFirstOp);
  5.   ISecondOperand := TGUIEdit.Create(EditSecondOp);
  6.   ICalcResult := TGUIEdit.Create(EditResult);
  7.   IOperators := TGUISelectableList.Create(ComboOperators);
  8.   IError := TGUIEdit.Create(EditError);
  10.   //link view and presenter
  11.   FPresenter := TCalculatorPresenter.Create(Self); //<<– THIS IS THE BAD LINE
  12. end;

The “BAD” line links the View with the Presenter but it’s in the view code, so this is meaning that View KNOWS the presenter… and this is not a good thing becouse the view is not so “passive”.

In a more advanced (and complex) version the View should be completely ignorant about the class that implement the presenter and the service.

In the main dpr file now the code now looks like the following.

  1. var
  2.   MainPresenter: ICalculatorPresenter;
  3.   CalculatorView: TForm;
  4. begin
  5.   Application.Initialize;
  6.   Application.MainFormOnTaskbar := True;
  8.   Application.CreateForm(TfrmCalculatorView, CalculatorView);  
  10.   MainPresenter := TCalculatorPresenter.Create(CalculatorView as ICalculatorView, TCalculatorService.Create);
  11.   //LETS START!
  12.   Application.Run;
  13. end.

Now the presenter take care about all links between the MVP triad.

  1. constructor TCalculatorPresenter.Create(CalculatorView: ICalculatorView;
  2.   CalculatorService: ICalculatorService);
  3. begin
  4.   inherited Create;
  5.   FCalculatorService := CalculatorService;
  6.   FCalculatorView := CalculatorView;
  7.   FCalculatorView.SetPresenter(self);
  8.   InitView;  //does the links
  9. end;

There is another addition to the previous example. Now there is only one constructor in the presenter, and using dependency injection take 2 interface for the view and the service.

  1.     constructor Create(CalculatorView: ICalculatorView; CalculatorService: ICalculatorService);

Another plus is the possibility to open the same form a number of times without change the code for create it.

This is the GUI for this simple application.

3 instance of the same view with different presenter and service

3 instance of the same view with different presenter and service

As bonus, unit tests and mock object arent changed.

As usual the source code is here.

A simple Dependency Injection Container for Delphi

Delphi 2010, Delphi Dependency Injection, Design Patterns 10 Comments »

As wikipedia says:

“Dependency injection (DI) in computer programming refers to the process of supplying an external dependency to a software component. It is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency. The term was first coined by Martin Fowler to describe the mechanism more clearly.

Many of us have already read this historical article from Martin Fowler about dependency injection pattern, but actually there isn’t a real framework for implement dependency injection in Delphi.

There are already the following implementation for DI in Delphi

  • Emballo (work with pre-D2010 too, but the implementation require changes in the service classes. I really hate it)
  • Delphi Spring Framework (very nice, but still not realeased)

So, I decided to write my own simple DI framework.

You can find the code at google code project here:

This is the first public version and come with sample, documentation and unit tests.

Folow some sample code.

  1. program Test01;
  4. uses
  5.   SysUtils,
  6.   DIContainer in '..\..\src\DIContainer.pas',
  7.   ServiceTestObjectsU in '..\..\UnitTest\ServiceTestObjectsU.pas';
  9. var
  10.   DIContainer: TDIContainer;
  11.   s1: TService1;
  12.   s2: TService2;
  13.   s3: TService3;
  14.   s6: TService6;
  15.   s7: TService7;
  16. begin
  17.   try
  18.     DIContainer := TDIContainer.Create;
  19.     try
  20.       // AddComponent with TClass with and   InitType = Singleton
  21.       DIContainer.AddComponent(TService1, TDIContainerInitType.Singleton);
  22.       // AddComponent with QualifiedName and InitType = Singleton
  23.       DIContainer.AddComponent('ServiceTestObjectsU.TService2',
  24.         TDIContainerInitType.Singleton);
  25.       // AddComponent with QualifiedName and InitType = CreateNewInstance
  26.       DIContainer.AddComponent('ServiceTestObjectsU.TService3',
  27.         TDIContainerInitType.CreateNewInstance);
  29.       // GetComponent with QualifiedName
  30.       s1 := DIContainer.GetComponent('ServiceTestObjectsU.TService1')
  31.         as TService1;
  32.       s1.Message := 'I''m the first message';
  33.       WriteLn(s1.Message);
  35.       // GetComponent with TClass
  36.       s2 := DIContainer.GetComponent(TService2) as TService2;
  37.       s2.Message := 'I''m the second message';
  38.       WriteLn(s2.Message);
  40.       // GetComponent with a dependent service (TService3 depends upon TService1 and TService2)
  41.       s3 := DIContainer.GetComponent('ServiceTestObjectsU.TService3')
  42.         as TService3;
  43.       WriteLn(s3.GetCompoundMessage);
  44.       // s3 is not created as Singleton, so after use it I must free it
  45.       s3.Free;
  47.       // AddComponent with QualifiedClassName, a custom initializer, an alias.
  48.       // Component will be created as singleton (single instance managed by Container)
  50.       DIContainer.AddComponent(DIContainerUtils.GetQualifiedClassName
  51.           (TService6),
  52.           function: TObject
  53.           begin
  54.             Result := TService6.Create(DIContainer.Get(TService1) as TService1,DIContainer.Get(TService1) as TService1);
  55.           end,
  56.           'srv6',
  57.         TDIContainerInitType.Singleton);
  59.       s6 := DIContainer.Get('srv6') as TService6;
  60.       WriteLn(s6.ToString);
  61.       s6 := DIContainer.Get('srv6') as TService6;
  62.       WriteLn(s6.ToString);
  64.       // AddComponent with QualifiedClassName, a custom initializer, an alias.
  65.       // Component will be created as singleton (single instance managed by Container)
  66.       DIContainer.AddComponent(DIContainerUtils.GetQualifiedClassName
  67.           (TService7),
  68.             function: TObject
  69.             begin
  70.               Result := TService7.Create(DIContainer.Get(TService1) as TService1,DIContainer.Get(TService1) as TService1);
  71.             end,
  72.             'srv7intf',
  73.           TDIContainerInitType.Singleton);
  75.       s7 := DIContainer.Get('srv7intf') as TService7;
  76.       WriteLn(s7.ToString);
  77.     finally
  78.       DIContainer.Free;
  79.     end;
  80.   except
  81.     on E: Exception do
  82.       WriteLn(E.ClassName, E.Message);
  83.   end;
  84.   readln;
  85. end.

DelphiDIContainer also handle constructor injection with automatic dependency resolution for service.

Enjoy and stay tuned.

My AMQP Delphi wrapper is in the standard 0MQ distribution

Delphi for Win32, Design Patterns, Message Oriented Middleware, Programming 9 Comments »

Yes, this is a nice news!
My AMQP Delphi wrapper for 0MQ is officially included into the distribution of 0MQ.
Now sources are managed into the main svn trunk.
You can read the news in the project’s main page.
You can see the code here.

In the upcoming greatest Delphi conference ITDevCon, I’ll have a talk about MoM (Message oriented middleware) and I’ll talk about ZeroMQ too.

Using AMQP from Delphi with ZeroMQ

Delphi for Win32, Design Patterns, Programming, Uncategorized 8 Comments »

The Advanced Message Queuing Protocol (AMQP) is an open standard application layer protocol for Message Oriented Middleware (MoM).

The defining features of AMQP are message orientation, queuing, routing (including point-to-point and publish-and-subscribe), reliability and security.

The good news about AMQP is that AMQP mandates the behaviour of the messaging provider and client to the extent that implementations from different vendors are truly interoperable, in the same way as SMTP, HTTP, FTP, etc. have created interoperable systems.

In a so “Open” market, live an interesting project called ZeroMQ.

In a my recent Delphi project, I must choice a thin and fast messaging system, ZeroMQ has been the choice.

However, ZeroMQ has not the Delphi client for talking with the broker, so I decided to write my own.

ZeroMQ is very fast but doesn’t support some enteprise features like users management and message persistence, but is very simple to use and to intergate in a legacy system.

For example, with my wrapper, a simple “sender” is like following:

  1. zmq := TZeroMQ.Create;
  2. try
  3. zmq.Open('localhost');
  4. ex := zmq.CreateLocalExchange('MyExchange', zmqStyleDataDistribution);
  5. zmq.Bind('MyExchange', 'GlobalQueue');
  6. zmq.Send(ex, 'Hello World From Delphi');
  7. finally
  8. zmq.Free;
  9. end;

And a simple receiver is simple as follow:

  1. zmq := TZeroMQ.Create;
  2. try
  3. zmq.Open('localhost');
  4. ex := zmq.CreateLocalQueue('LocalQueue');
  5. zmq.Bind('GlobalExchange', 'LocalQueue');
  6. zmq.Receive(msg, msgtype, msgsize, zmqBlocking);
  7. WriteLn(msg);  //we are in a console application
  8. finally
  9. zmq.Free;
  10. end;

In the distribution there are a complete set of examples including a simple “Chat” application.

ZeroMQ is primarily intended to power stock trading business, this is the reason becouse is very fast.

To use ZeroMQ you need the ZeroMQ server downloadable from where you can find additional info about Exchange and Queue configuration and binding.

Wrapper (beta) can be downloaded from the ZeroMQ section.

Comments and fix for the wrapper are very apreciated.

Have fun and happy messaging :-)

My speech at “PHPCon Italia 2009″

Delphi for PHP, Design Patterns, Programming, Uncategorized, bit Time Software 3 Comments »

I will talk at the italian PHPCon in Rome on March 18-20 2009.

I will talk about “Data Access Design Patterns” showing many PHP examples.

PHPCon Italia 2009
Holiday Inn Eur Parco dei Medici
Viale Castello Della Magliana 65
ROME, 00148
Web Site

Click here for discount on ticket (italian web site)

And this is the “Speaker Button”

My Speaker Button

My Speaker Button

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in