2012, Sunday May 20
By A.Bouchez on 2012, Sunday May 20, 09:47 - Pascal Programing
In a Stack Overflow
question, someone asked about some nested procedure call he found out. That
is, a procedure inside another procedure.
He found out this coding style to be messy, which sounds like a reasonable
opinion. But his alternative proposal of putting the internal procedure outside
the main one, i.e. making it global, is IMHO even worse.
In some case, a private class, or even record
or object with methods is an handy and maintainable implementation
pattern.
Continue reading...
2012, Thursday May 3
By A.Bouchez on 2012, Thursday May 3, 17:16 - mORMot Framework
By default, during interface-based service call,
any record parameter or function result will be serialized with
our proprietary binary (and optimized layout) - i.e. RecordLoad
and RecordSave functions - then encoded in Base-64, to be
stored as plain text within the JSON stream.
But custom record JSON serialization can be defined, as with any
class - see this article - or
dynamic array - see this
article.
Continue reading...
2012, Wednesday April 25
By A.Bouchez on 2012, Wednesday April 25, 06:27 - mORMot Framework
In a discussion with Henrick
Hellström, in Embarcadero forums, I wrote some high-level information about
mORMot.
It was clear to me that our little mORMot is now far away from
a simple Client-Server solution.
The Henrick point was that with Real Thin Client (RTC), you are able
to write any Client-Server solution, even a RESTful / JSON based one.
He is of course right, but it made clear to me all the work done in
mORMot since its beginning.
From a Client-Server ORM, it is now a complete SOA framework, ready to serve
Domain-Driven-Design solutions.
Continue reading...
2012, Friday April 20
By A.Bouchez on 2012, Friday April 20, 23:05 - mORMot Framework
Our latest mORMot feature is interface-based service
implementation.
How does it compare with the reference of SOA implementation (at least in
the Windows world) - aka WCF?
"Comparaison n'est pas raison", as we use to say in France.
But we will also speak about Event Sourcing, and why it is now on our
official road
map.
Comparing our implementation with WCF is the opportunity to make our framework
always better.
Continue reading...
2012, Thursday April 19
By A.Bouchez on 2012, Thursday April 19, 06:23 - Pascal Programing
Did you hear from the great Smart project?
It is an IDE and some source runtime able to develop and compile an
Object-Pascal project into a HTML 5 / CSS 3 / JavaScript embedded
application.
It does target AJAX Mobile application creation (i.e. Android and
iPhone/iPad apps running Web-Kit).
You'll get an unique .html file containing the whole client-side
application: it won't need any server side implementation. Using a third-party
tool like PhoneGap, you'd be able to supply your customers with true
native applications, running without any network, and accessing the full power
of any modern Smart Phone.
Smart is a great candidate for implementing rich client-side AJAX
applications, to work with our client-server mORMot framework.
In order to interface Smart code with mORMot, we started
implementing some low-level code to work with our RESTful
authentication scheme.
So we'll need to implement some Smart dedicated Open Source code
implementing crc32 and SHA-256 hashing.
Continue reading...
2012, Friday April 13
By A.Bouchez on 2012, Friday April 13, 12:07 - mORMot Framework
By default, our mORMot framework is able to serialize any class
into a true JSON object.
All published properties will be written as JSON object
members.
In some cases, it may be handy to have a custom serialization, for instance
if you want to manage some third-party classes, or to adapt the serialization
scheme to a particular purpose, at runtime.
Continue reading...
2012, Thursday April 12
By A.Bouchez on 2012, Thursday April 12, 20:33 - mORMot Framework
One nice feature of the TDynArray wrapper and its associated
methods, as defined and used in our framework, is the ability to serialize
any dynamic array as JSON content.
By default, only "standard" dynamic arrays (like
TIntegerDynArray) are serialized as true JSON array: other not
known kind of arrays are serialized as binary content, within a Base64
encoding.
This is a very efficient solution for a pure Delphi application, since it
will be fast and always works, but won't be easy to deal with from an AJAX
client.
Applications can now supply a custom JSON serialization for any other
dynamic array, via the TTextWriter.RegisterCustomJSONSerializer()
class method.
Two callbacks are to be supplied for a dynamic array type information, in order
to handle proper serialization and un-serialization of the JSON array.
Continue reading...
2012, Tuesday April 10
By A.Bouchez on 2012, Tuesday April 10, 11:53 - Pascal Programing
One potential issue with Delphi coding, is about how the result of a
functions are implemented.
If you forget to set a result value to a function, you'll
get a compiler warning.
Never underestimate such warning: IMHO this is not a warning, but an error.
And you should better be aware of the handling of reference-counted types
(e.g. string) in a function results: those are passed the stack as
var parameters, so the result of a function may be set
even if an exception is raised during function execution!
Continue reading...
2012, Wednesday March 28
By A.Bouchez on 2012, Wednesday March 28, 12:55 - mORMot Framework
As stated by this
previous article, the default answer format is a valid JSON object.
In some cases, it may be useful to have a service operation (i.e. an
interface method) returning any content, e.g. some plain TEXT, HTML or binary
data (like a picture).
Continue reading...
2012, Wednesday March 7
By A.Bouchez on 2012, Wednesday March 7, 23:58 - mORMot Framework
In addition to the other related blog articles, you can find in the
"
SQLite3/Samples/14
- Interface based services" folder of the supplied source code
distribution, a dedicated sample about this feature.
Purpose of this code is to show how to create a client-server service, using
interfaces, over named pipe communication.
Continue reading...
By A.Bouchez on 2012, Wednesday March 7, 23:36 - mORMot Framework
You will find out in SQLite3Commons.pas all classes
implementing this interface communication.
There are two levels of implementation:
- A services catalog, available in TSQLRest.Services
property, declared as TServiceContainer (with two
inherited versions, for each side);
- A service factory for each interface, declared as
TServiceFactory (also with two inherited versions,
for each side).
In fact, TServiceFactory.Create constructor will retrieve all
needed RTTI information of the given interface, i.e. GUID, name and all methods
(with their arguments). It will compute the low-level stack memory layout
needed at execution. And the corresponding "contract" will be computed, to
validate that both client and server expect the exact same
interface.
On the server side, TServiceFactoryServer.ExecuteMethod method
(and then a nested TServiceMethod.InternalExecute call) is used to
prepare a valid call to the implementation class code from a remote JSON
request.
On the client side, a TInterfacedObjectFake class will be
created, and will emulate a regular Delphi interface call using some on-the-fly
asm code generated in the TServiceFactoryClient.Create
constructor.
Continue reading...
By A.Bouchez on 2012, Wednesday March 7, 23:27 - mORMot Framework
Once the service is registered on the server side, it is very easy to use it
in your code.
In a complex Service Oriented Architecture, it is pretty common to
have services calling each other. Code re-usability is a key here. So you'll
have to consume services on the server side. According to the SOLID design principles, you'd
better rely on abstraction in your code, i.e. not call the service
implementation, but the service abstract interface.
You can use the following method of your TSQLRest.Services
instance (note that this method is available on both client and server sides,
so is the right access point to all services):
function TServiceFactory.Get(out Obj): Boolean;
Continue reading...
By A.Bouchez on 2012, Wednesday March 7, 23:22 - mORMot Framework
In order to have an operating service, you'll need to implement a Delphi
class which matches the expected interface.
Continue reading...
By A.Bouchez on 2012, Wednesday March 7, 23:18 - mORMot Framework
In a Service Oriented Architecture, services tend to create a huge
list of operations.
In order to facilitate implementation and maintenance, operations shall be
grouped within common services.
The data contract is to be defined as a plain Delphi interface
type.
In fact, the sample type as stated in a previous blog article can be
used directly:
type
ICalculator = interface(IInvokable)
['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
/// add two signed 32 bit integers
function Add(n1,n2: integer): integer;
end;
This ICalculator.Add method will define one "Add"
operation, under the "ICalculator" service (which will be named
internally 'Calculator' by convention).
This operation will expect two numbers as input, and then return the sum of
those numbers.
Continue reading...
By A.Bouchez on 2012, Wednesday March 7, 23:12 - mORMot Framework
The
Client-Server services via methods implementation (our DataSnap-like
feature) gives full access to the lowest-level of the mORMot's core,
so it has some advantages:
- It can be tuned to fit any purpose (such as retrieving or returning some HTML
or binary data, or modifying the HTTP headers on the fly);
- It is integrated into the RESTful URI model, so it can be related to any
table/class of our ORM framework (like DataAsHex service above),
or it can handle any remote query (e.g. any AJAX or SOAP requests);
- It has a very low performance overhead, so can be used to reduce server
workload for some common tasks.
But this implementation pattern has some drawbacks:
- Most content marshaling is to be done by hand, so may introduce
implementation issues;
- Client and server side code does not have the same implementation pattern, so
you will have to code explicitly data marshaling twice, for both client and
server;
- The services do not have any hierarchy, and are listed as a plain list, which
is not very convenient;
- It is difficult to synchronize several service calls within a single context,
e.g. when a workflow is to be handled during the application process (you have
to code some kind of state machine on both sides);
- Security is handled globally for the user, or should be checked by hand in
the implementation method (using the aParams.Context values).
You can get rid of those limitations with the interface-based service
implementation of mORMot. For a detailed introduction and best
practice guide to SOA, you can consult this
"classic" article.
According to this document, all expected SOA features are now available in
the current implementation of the mORMot framework (including service
catalog aka "broker").
Continue reading...
2012, Wednesday February 29
By A.Bouchez on 2012, Wednesday February 29, 23:45 - Pascal Programing
No, interface(-book) is not another social network, sorry.
In Delphi OOP model, an interface defines a type that comprises
abstract virtual methods.
The short, easy definition is that an interface is a declaration of
functionality without an implementation of that functionality. It defines
"what" is available, not "how" it is made available. This is the so called
"abstraction" benefit of interfaces (there are another benefits, like
orthogonality of interfaces to classes, but we'll see it later).
In its upcoming 1.16 revision, our mORMot framework is able to use interface
for its service definition.
So we'll discuss and introduce this gem available in all modern languages -
including Delphi: interfaces.
Continue reading...
2012, Tuesday February 14
By A.Bouchez on 2012, Tuesday February 14, 21:39 - mORMot Framework
Here is the definition of "cache", as stated by Wikipedia:
In computer engineering, a cache is a component that transparently
stores data so that future requests for that data can be served faster. The
data that is stored within a cache might be values that have been computed
earlier or duplicates of original values that are stored elsewhere. If
requested data is contained in the cache (cache hit), this request can be
served by simply reading the cache, which is comparatively faster. Otherwise
(cache miss), the data has to be recomputed or fetched from its original
storage location, which is comparatively slower. Hence, the greater the number
of requests that can be served from the cache, the faster the overall system
performance becomes.
To be cost efficient and to enable an efficient use of data, caches are
relatively small. Nevertheless, caches have proven themselves in many areas of
computing because access patterns in typical computer applications have
locality of reference. References exhibit temporal locality if data is
requested again that has been recently requested already. References exhibit
spatial locality if data is requested that is physically stored close to data
that has been requested already.
In our ORM framework, since performance was one goal since the beginning,
cache has been implemented at four levels:
- Statement cache for reuse of SQL prepared statements, and bound parameters
on the fly - note that this cache is available not only for the
SQlite3 database engine, but also for any external engine;
- Global JSON result cache at the database level, which is flushed globally
on any
INSERT / UPDATE;
- Tuned record cache at the CRUD/RESTful level for specified tables or
records on the server side;
- Tuned record cache at the CRUD/RESTful level for specified tables or
records on the client side.
Continue reading...
2012, Thursday February 9
By A.Bouchez on 2012, Thursday February 9, 10:54 - Pascal Programing
Some Delphi users even do not know the existence of the
SetString function.
As stated by the official
documentation:
procedure SetString(var S: String; Buffer: PChar; Length: Integer);
For a long string variable, SetString sets S to reference a newly allocated
string of the given length. If the Buffer parameter is not nil, SetString then
copies Len characters from Buffer into the string; otherwise, the content of
the new string is left uninitialized. If there is not enough memory available
to create the string, an EOutOfMemory exception is raised. Following a call to
SetString, S is guaranteed to reference a unique string (a string with a
reference count of one).
Some have
noticed that in our libraries, I sometimes use SetString
instead of SetLength.
When the string is already allocated, it could be faster to use
SetString, if you are sure that you will overwrite the string
content.
Continue reading...
2012, Monday February 6
By A.Bouchez on 2012, Monday February 6, 22:05 - mORMot Framework
In order to implement some RESTful Services, a
callback has to be defined on the server side.
The prototype of these methods has been modified one more time, to supply an
unique parameter:
This is a CODE BREAK change and you shall refresh ALL your server-side
code to match the new signature.
This unique parameter will let the signature remain untouched in your code
implementation, even if the framework evolves (like adding a new
parameter).
Continue reading...
2012, Sunday January 29
By A.Bouchez on 2012, Sunday January 29, 14:30 - mORMot Framework
For our native connection to any DB, we developed a set of
classes and several units.
We implemented at first
OleDB, then native Oracle
direct access and SQlite3 static
engine.
Now, Microsoft is officially deprecating OleDB, and urge
all developers to switch to the open and cross-platform ODBC
API for native connection.
Continue reading...