SlideShare a Scribd company logo
1 of 74
Download to read offline
Software Architecture & Design
ī‚¨ Architecture
ī‚¤ From n-Tier to SOA
ī‚¤ From SOAP to REST
ī‚¤ Technical Debt
ī‚¨ Design
ī‚¤ From SQL to ORM, NoSQL and ODM
ī‚¤ From RAD to MVC
ī‚¤ SOLID principles
ī‚¤ Domain Driven Design (DDD)
Applying patterns on Delphi code using mORMot
Software Architecture & Design
From Interfaces to SOLID
From Interfaces to SOLID
ī‚¨ Delphi and interfaces
ī‚¨ SOLID design principles
ī‚¨ Dependency Injection, stubs and mocks
ī‚¨ Using mORMot features
ī‚¨ Delphi and Weak pointers
From Interfaces to SOLID
Delphi and interfaces
ī‚¨ In Delphi OOP model
ī‚¤ An interface defines a type
that comprises abstract virtual methods
ī‚¤ It is a declaration of functionality
without an implementation of that functionality
ī‚¤ It defines "what" is available,
not "how" it is made available
From Interfaces to SOLID
Delphi and interfaces
ī‚¨ Declaring an interface
īŽ Naming convention: ICalculator
īŽ No visibility attribute: all published
īŽ No fields, just methods and properties
īŽ Unique identifier by GUID (Ctrl Shift G)
From Interfaces to SOLID
type
ICalculator = interface(IInvokable)
['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}']
/// add two signed 32 bit integers
function Add(n1,n2: integer): integer;
end;
Delphi and interfaces
ī‚¨ Implementing an interface
īŽ ICalculator added to the “inheritance chain”
īŽ TCalculator implements a behavior
From Interfaces to SOLID
type
TServiceCalculator = class(TInterfacedObject, ICalculator)
protected
fBulk: string;
public
function Add(n1,n2: integer): integer;
procedure SetBulk(const aValue: string);
end;
function TServiceCalculator.Add(n1, n2: integer): integer;
begin
result := n1+n2;
end;
procedure TServiceCalculator.SetBulk(const aValue: string);
begin
fBulk := aValue;
end;
Delphi and interfaces
ī‚¨ Using an interface
īŽ Strong typing
īŽ The variable defines a behavior (contract)
īŽ Path to abstraction
From Interfaces to SOLID
function MyAdd(a,b: integer): integer;
var Calculator: ICalculator;
begin
Calculator := TServiceCalculator.Create;
result := Calculator.Add(a,b);
end;
Delphi and interfaces
ī‚¨ Using an interface
īŽ Strong typing
īŽ The variable defines a behavior (contract)
īŽ Path to abstraction
īŽ Automatic try..finally
From Interfaces to SOLID
function MyAdd(a,b: integer): integer;
var Calculator: TServiceCalculator;
begin
Calculator := TServiceCalculator.Create;
try
result := Calculator.Add(a,b);
finally
Calculator.Free;
end;
end;
function MyAdd(a,b: integer): integer;
var Calculator: ICalculator;
begin
Calculator := TServiceCalculator.Create;
result := Calculator.Add(a,b);
end;
Delphi and interfaces
ī‚¨ Automatic try..finally
ī‚¤ Compiler generates
some hidden codeâ€Ļ
īŽ Behavior inherited from TInterfacedObject
īŽ Similar to COM / ActiveX
From Interfaces to SOLID
function MyAdd(a,b: integer): integer;
var Calculator: ICalculator;
begin
Calculator := TServiceCalculator.Create;
result := Calculator.Add(a,b);
end;
function MyAdd(a,b: integer): integer;
var Calculator: TServiceCalculator;
begin
Calculator := nil;
Calculator := TServiceCalculator.Create;
try
Calculator.FRefCount := 1;
result := Calculator.Add(a,b);
finally
dec(Calculator.FRefCount);
if Calculator.FRefCount=0 then
Calculator.Free;
end;
end;
Delphi and interfaces
ī‚¨ Interfaces are orthogonal to implementation
ī‚¤ There is more than one way to do it
From Interfaces to SOLID
type
TOtherServiceCalculator = class(TInterfacedObject, ICalculator)
protected
function Add(n1,n2: integer): integer;
end;
function TOtherServiceCalculator.Add(n1, n2: integer): integer;
begin
result := n2+n1;
end;
function MyOtherAdd(a,b: integer): integer;
var Calculator: ICalculator;
begin
ICalculator := TOtherServiceCalculator.Create;
result := Calculator.Add(a,b);
end;
SOLID design principles
ī‚¨ Single responsibility principle
ī‚¨ Open/closed principle
ī‚¨ Liskov substitution principle (design by contract)
ī‚¨ Interface segregation principle
ī‚¨ Dependency inversion principle
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single responsibility
ī‚¤ Object should have only a single responsibility
ī‚¨ Open/closed
ī‚¤ Entities should be open for extension,
but closed for modification
ī‚¨ Liskov substitution (design by contract)
ī‚¤ Objects should be replaceable with instances of their
subtypes without altering the correctness of that program
ī‚¨ Interface segregation
ī‚¤ Many specific interfaces are better than one
ī‚¨ Dependency inversion
ī‚¤ Depend upon abstractions, not depend upon concretions
From Interfaces to SOLID
SOLID design principles
ī‚¨ Help to fight well-known weaknesses
ī‚¤ Rigidity
īŽ Hard to change something because every change
affects too many other parts of the system
ī‚¤ Fragility
īŽ When you make a change, unexpected parts of the
system break
ī‚¤ Immobility
īŽ Hard to reuse in another application because it cannot
be disentangled from the current application
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ When you define a class, it shall be designed to
implement only one feature
ī‚¤ The so-called feature can be seen as
an "axis of change" or a "a reason for change"
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ One class shall have only one reason
that justifies changing its implementation
ī‚¤ Classes shall have few dependencies
on other classes
ī‚¤ Classes shall be abstracted
from the particular layer they are running
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Splitting classes
īŽ Imagine a TBarCodeScanner class
to handle a serial bar-code scanner
īŽ Later on, we want to implement USB support
īŽ First idea may be to inherit
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Splitting classes
īŽ Imagine a TBarCodeScanner class
to handle a serial bar-code scanner
īŽ Later on, we want to implement USB support
īŽ But we would rather split the class hierarchy
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Splitting classes
īŽ Later on, the manufacturer updates its protocol
To add new features, e.g. 3D scanning or coffee making
īŽ How do we implement this?
īŽ We have two “axis of change”
so we would define two classes
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Splitting classes
īŽ Later on, the manufacturer updates its protocol
To add new features, e.g. 3D scanning or coffee making
īŽ We defined two classes, which will be joined/composed
in actual barcode scanner classes
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Splitting classes
TAbstractBarcodeScanner = class(TComponent)
protected
fProtocol: TAbstractBarcodeProtocol;
fConnection: AbstractBarcodeConnection;
...
constructor TSerialBarCodeScanner.Create(
const aComPort: string; aBitRate: integer);
begin
fConnection := TSerialBarcodeConnection(aComPort,aBitRate);
fProtocol := TBCP1BarcodeProtocol.Create(fConnection);
end;
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Another example
from SynDB class definitions:
īŽ TSQLDBConnectionProperties
īŽ TSQLDBConnection
īŽ TSQLDBStatement
ī‚¤ Each class has its own purpose,
and axis of change
īŽ And could be implemented via ODBC, OleDB,
direct client accessâ€Ļ
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Do not mix GUI and logic
ī‚¤ Do not mix logic and database
ī‚¤ Do not couple your code to an OS
īŽ Check your uses statement
īŽ There should be no reference to the UI
(e.g. Dialogs) in your business class
īŽ No dependency to DB libraries (this is a hard one)
īŽ No reference to WinAPI.Windows
From Interfaces to SOLID
SOLID design principles
ī‚¨ Single Responsibility
ī‚¤ Code smells
īŽ When abusing of:
FreeAndNil()
{$ifdef} â€Ļ {$endif}
uses unit1, unit2, unit3, â€Ļ unit1000;
īŽ When you can’t find the right method in a class
īŽ (mORMot may need some refactoring here) īŠ
īŽ When unitary tests are hard to write
From Interfaces to SOLID
SOLID design principles
ī‚¨ Open / Close principle
ī‚¤ When you define a class or an interface
īŽ it shall be open for extension
īŽ but closed for modification
From Interfaces to SOLID
SOLID design principles
ī‚¨ Open / Closed principle
ī‚¤ Open for extension
īŽ Abstract class is overridden by implementations
īŽ No singleton nor global variable – ever
īŽ Rely on abstraction
īŽ if aObject is aClass then â€Ļ it stinks!
ī‚¤ Closed for modification
īŽ E.g. via explicitly protected or private members
īŽ RTTI is dangerous: it may open the closed door
From Interfaces to SOLID
SOLID design principles
ī‚¨ Open / Closed principle
ī‚¤ In practice
īŽ Define meaningful interface types
īŽ Following the Design By Contract principle
īŽ Define Value objects (DTOs) to transfer the data
īŽ With almost no methods, but for initialization
īŽ With public members, to access the value
īŽ Define Process objects to modify the data
īŽ With public methods, abstracted in the interface
īŽ With mostly private members
From Interfaces to SOLID
SOLID design principles
ī‚¨ Open / Close principle
type
TAbstractBarcodeScanner = class(TComponent)
protected
fProtocol: TAbstractBarcodeProtocol;
fConnection: AbstractBarcodeConnection;
public
property Protocol: TAbstractBarcodeProtocol read fProtocol;
property Connection: AbstractBarcodeConnection read fConnection;
...
īŽ Protocol and Connection are read/only
īŽ They are injected by the overridden class constructor
īŽ So it will be Open for extension
From Interfaces to SOLID
SOLID design principles
ī‚¨ Open / Close principle
type
TAbstractBarcodeScanner = class(TComponent)
protected
fProtocol: TAbstractBarcodeProtocol;
fConnection: AbstractBarcodeConnection;
public
property Protocol: TAbstractBarcodeProtocol read fProtocol;
property Connection: AbstractBarcodeConnection read fConnection;
...
īŽ Protocol and Connection are read/only
īŽ You could not change the behavior of a class
īŽ It is Closed for modification
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution principle
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution principle
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution principle
ī‚¤ If TChild is a subtype of TParent
īŽ then objects of type TParent
may be replaced with objects of type TChild
īŽ without altering any of the desirable properties
of that program (correctness, task performed, etc.)
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution principle
ī‚¤ Tied to the Open / Closed principle
īŽ If you define a child, you should not modify the parent
ī‚¤ Code-reusability of the parent implementation
ī‚¤ You will be able
to stub or mock an interface or a class
īŽ Allow correct testing of a whole system:
even if all single unit tests did pass,
real system may not work if this principle was broken
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution patterns
ī‚¤ Design by contract
īŽ Meyer's (Eiffel language) rule:
“when redefining a routine [in a derivative],
you may only replace its precondition by a weaker
one, and its postcondition by a stronger one”
īŽ Define assertions at method level:
īŽ What does it expect, guarantee, and maintain?
īŽ About input/output values or types, side effects,
invariants, errors/exceptions, performanceâ€Ļ
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution patterns
ī‚¤ Write your code using abstract variables
īŽ Rely on parents methods and properties
īŽ Use interface variables
instead of class implementation
īŽ Uncouple dependencies via class composition
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution patterns
ī‚¤ Factory pattern
īŽ In strongly typed languages (Java, C#, Delphi),
the factory is the class/object type and its constructor
ī‚¤ Repository pattern
īŽ Allow persistence agnosticism (e.g. via ORM)
ī‚¤ Service locator pattern
īŽ Get a class instance implementing a given interface
īŽ According to the given context (no global/singleton)
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution patterns
ī‚¤ Practical, not dogmatic LSP
īŽ “Parent” and “Child” are not absolute
īŽ Depending on the context, you may define a given level
as the “highest” LSP abstract class
īŽ e.g. if you work on server side, you may need some
server-only properties and methods
īŽ LSP idea is to be consistent,
once the abstraction level is defined
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution patterns
ī‚¤ Practical, not dogmatic LSP
īŽ “Parent” and “Child” are not absolute
īŽ Inheritance is often used as code sharing among classes,
not as an abstraction contract
īŽ In this context, LSP may not apply at class level:
be pragmatic, and write efficient code
īŽ But LSP may apply at interface level,
for a set of methods implemented by the class
From Interfaces to SOLID
SOLID design principles
ī‚¨ Liskov substitution code smells
if aObject is aClass then â€Ļ
case aObject.EnumeratedType of â€Ļ
function â€Ļ abstract;
without further override;
unit parent;
uses child1,child2,child3;
From Interfaces to SOLID
SOLID design principles
ī‚¨ Interface segregation principle
ī‚¤ Once an interface has become too 'fat'
it shall be split into smaller
and more specific interfaces
so that any clients of the interface will only know
about the methods that pertain to them
ī‚¤ In a nutshell, no client should be forced
to depend on methods it does not use
From Interfaces to SOLID
SOLID design principles
ī‚¨ Interface segregation principle
ī‚¤ Smaller dedicated classes should be preferred
īŽ Single Responsibility Principle
īŽ Favor composition over inheritance
ī‚¤ Smaller dedicated interfaces
īŽ Gather operations/methods per context
īŽ Meaningful naming and conventions
īŽ So that the contract would be easier to understand
From Interfaces to SOLID
SOLID design principles
ī‚¨ Interface segregation principle
ī‚¤ Perfectly fits the SOA uncoupling pattern
īŽ Stateless MicroServices for horizontal scaling
ī‚¤ Allows to release memory and resources ASAP
īŽ Smaller objects have more bounded dependencies
ī‚¤ Ease unit testing
īŽ Less coverage
īŽ Less coupling
From Interfaces to SOLID
SOLID design principles
ī‚¨ Interface segregation principle
ī‚¤ Excludes RAD
īŽ Logic implemented in TForm TDataModule
where methods are procedural code in disguise
īŽ Put your logic behind interfaces
and call them from your UI (over VCL and FMX)
ī‚¤ Favors DDD
īŽ Segregation avoid domain leaking
īŽ Dedicated interfaces, e.g. for third party consumption
From Interfaces to SOLID
SOLID design principles
ī‚¨ Dependency Inversion
ī‚¤ High-level modules
should not depend on low-level modules
īŽ Both should depend on abstractions
īŽ Following other SOLI principles
ī‚¤ Abstractions should not depend upon details
īŽ Details should depend upon abstractions
īŽ Business Logic should not depend on database
īŽ Application Layer should not depend on client UI techno
From Interfaces to SOLID
SOLID design principles
ī‚¨ Dependency Inversion
ī‚¤ In most conventional programming style:
īŽ You write low-level components (e.g. DB tables)
īŽ Then you integrate them with high-level components
ī‚¤ But this limits the re-use of high-level code
īŽ In fact, it breaks the Liskov substitution principle
īŽ It reduces the testing abilities (e.g. need of a real DB)
From Interfaces to SOLID
SOLID design principles
ī‚¨ Dependency Inversion may be implemented
ī‚¤ Via a plug-in system
īŽ e.g. external libraries (for embedded applications)
ī‚¤ Using a service locator
īŽ e.g. SOA catalog (SaaS/cloud)
īŽ class resolution from an interface type
From Interfaces to SOLID
SOLID design principles
ī‚¨ Dependency Inversion may be implemented
ī‚¤ Via Dependency Injection
īŽ Concretions are injected to the objects using them
īŽ Only abstractions are known at design/coding time
īŽ Uncoupled implementation injected at runtime
īŽ Modular coding
īŽ Perfect for bigger/complex projects, with a set of teams
īŽ Ease testing, via stub/mock dependencies injection
īŽ e.g. a fake database, defined as a Repository service
īŽ Scaling abilities
From Interfaces to SOLID
SOLID design principles
ī‚¨ Dependency Inversion may be implemented
ī‚¤ Via Dependency Injection
īŽ A class will define its dependencies as read-only
interface members
īŽ Implementation will be injected at constructor level
īŽ via explicit constructor parameters
īŽ via automated resolution via RTTI
īŽ via service locator/resolver
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Thanks to SOLID design principles
ī‚¤ All your code logic will now be abstracted
to the implementation underneath
ī‚¤ But you need to inject the implementation
īŽ This is Dependency Injection purpose
ī‚¤ You can also create fake instances to implement
a given interface, and enhance testing
īŽ Introducing Stubs and Mocks
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Define external dependencies as interface
īŽ as (private / protected) read-only members
ī‚¤ To set the implementation instance:
īŽ Either inject the interfaces as constructor parameters
īŽ Or use a Factory / Service locator
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Purpose is to test the following class:
From Interfaces to SOLID
TLoginController = class(TInterfacedObject,ILoginController)
protected
fUserRepository: IUserRepository;
fSmsSender: ISmsSender;
public
constructor Create(const aUserRepository: IUserRepository;
const aSmsSender: ISmsSender);
procedure ForgotMyPassword(const UserName: RawUTF8);
end;
constructor TLoginController.Create(const aUserRepository: IUserRepository;
const aSmsSender: ISmsSender);
begin
fUserRepository := aUserRepository;
fSmsSender := aSmsSender;
end;
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Dependencies are defined as
īŽ Two small, uncoupled, SOLID task-specific interfaces
From Interfaces to SOLID
IUserRepository = interface(IInvokable)
['{B21E5B21-28F4-4874-8446-BD0B06DAA07F}']
function GetUserByName(const Name: RawUTF8): TUser;
procedure Save(const User: TUser);
end;
ISmsSender = interface(IInvokable)
['{8F87CB56-5E2F-437E-B2E6-B3020835DC61}']
function Send(const Text, Number: RawUTF8): boolean;
end;
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Using a dedicated Data Transfer Object (DTO)
īŽ No dependency against storage, nor other classes
From Interfaces to SOLID
IUserRepository = interface(IInvokable)
['{B21E5B21-28F4-4874-8446-BD0B06DAA07F}']
function GetUserByName(const Name: RawUTF8): TUser;
procedure Save(const User: TUser);
end;
TUser = record
Name: RawUTF8;
Password: RawUTF8;
MobilePhoneNumber: RawUTF8;
ID: Integer;
end;
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ The high-level method to be tested:
īŽ Open/Closed, Liskov and mainly Dependency
Inversion principles are followed
īŽ Will we need a full database and to send a SMS?
From Interfaces to SOLID
procedure TLoginController.ForgotMyPassword(const UserName: RawUTF8);
var U: TUser;
begin
U := fUserRepository.GetUserByName(UserName);
U.Password := Int32ToUtf8(Random(MaxInt));
if fSmsSender.Send('Your new password is '+U.Password,U.MobilePhoneNumber) then
fUserRepository.Save(U);
end;
DI, Stubs and Mocks
ī‚¨ "The Art of Unit Testing" (Osherove, Roy - 2009)
ī‚¤ Stubs are fake objects
implementing a given contract
and returning pre-arranged responses
īŽ They just let the test pass
īŽ They “emulate” some behavior (e.g. a database)
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ "The Art of Unit Testing" (Osherove, Roy - 2009)
ī‚¤ Mocks are fake objects like stubs
which will verify if an interaction occurred or not
īŽ They help decide if a test failed or passed
īŽ There should be only one mock per test
From Interfaces to SOLID
DI, Stubs and Mocks
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Expect – Run – Verify pattern
From Interfaces to SOLID
procedure TMyTest.ForgotMyPassword;
var SmsSender: ISmsSender;
UserRepository: IUserRepository;
begin
TInterfaceStub.Create(ISmsSender,SmsSender).
Returns('Send',[true]);
TInterfaceMock.Create(IUserRepository,UserRepository,self).
ExpectsCount('Save',qoEqualTo,1);
with TLoginController.Create(UserRepository,SmsSender) do
try
ForgotMyPassword('toto');
finally
Free;
end;
end;
DI, Stubs and Mocks
ī‚¨ Expect – Run – Verify pattern
īŽ TInterfaceStub / TInterfaceMock constructors
are in fact Factories for any interface
īŽ Clear distinction between stub and mock
īŽ Mock is linked to its test case (self: TMyTest)
From Interfaces to SOLID
procedure TMyTest.ForgotMyPassword;
var SmsSender: ISmsSender;
UserRepository: IUserRepository;
begin
TInterfaceStub.Create(ISmsSender,SmsSender).
Returns('Send',[true]);
TInterfaceMock.Create(IUserRepository,UserRepository,self).
ExpectsCount('Save',qoEqualTo,1);
DI, Stubs and Mocks
ī‚¨ Expect – Run – Verify pattern
īŽ Execution code itself sounds like real-life code
īŽ But all dependencies have been injected
īŽ Stubs will emulate real behavior
īŽ Mock will verify that all expectations are fulfilled
From Interfaces to SOLID
with TLoginController.Create(UserRepository,SmsSender) do
try
ForgotMyPassword('toto');
finally
Free;
end;
end;
DI, Stubs and Mocks
ī‚¨ Expect – Run – Verify pattern
From Interfaces to SOLID
procedure TMyTest.ForgotMyPassword;
var SmsSender: ISmsSender;
UserRepository: IUserRepository;
begin
TInterfaceStub.Create(ISmsSender,SmsSender).
Returns('Send',[true]);
TInterfaceMock.Create(IUserRepository,UserRepository,self).
ExpectsCount('Save',qoEqualTo,1);
with TLoginController.Create(UserRepository,SmsSender) do
try
ForgotMyPassword('toto');
finally
Free;
end;
end;
DI, Stubs and Mocks
ī‚¨ Run – Verify (aka “Test spy”) pattern
From Interfaces to SOLID
procedure TMyTest.ForgotMyPassword;
var SmsSender: ISmsSender;
UserRepository: IUserRepository;
Spy: TInterfaceMockSpy;
begin
TInterfaceStub.Create(ISmsSender,SmsSender).
Returns('Send',[true]);
Spy := TInterfaceMockSpy.Create(IUserRepository,UserRepository,self);
with TLoginController.Create(UserRepository,SmsSender) do
try
ForgotMyPassword('toto');
finally
Free;
end;
Spy.Verify('Save');
end;
DI, Stubs and Mocks
ī‚¨ Another features:
ī‚¤ Return complex values (e.g. a DTO)
ī‚¤ Use a delegate to create a stub/mock
īŽ Using named or indexed variant parameters
īŽ Using JSON array of values
ī‚¤ Access the test case when mocking
ī‚¤ Trace and verify the calls
īŽ With a fluent interface
īŽ Log all calls (as JSON)
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Inheriting from TInjectableObject
type
TServiceToBeTested = class(TInjectableObject,IServiceToBeTested)
protected
fService: IInjectedService;
published
property Service: IInjectedService read fService;
end;
ī‚¤ Will auto-inject interface published properties
īŽ At instance creation
īŽ Handled by TSQLRest.Services
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Inheriting from TInjectableObject
var Test: IServiceToBeTested;
begin
Test := TServiceToBeTested.CreateInjected(
[ICalculator],
[TInterfaceMock.Create(IPersistence,self).
ExpectsCount('SaveItem',qoEqualTo,1),
RestInstance.Services],
[AnyInterfacedObject]);
...
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Inheriting from TInjectableObject
procedure TServiceToBeTested.AnyProcessMethod;
var Service: IInjectedService;
begin
Resolve(IInjectedService,Service);
Service.DoSomething;
end;
From Interfaces to SOLID
DI, Stubs and Mocks
ī‚¨ Dependency Injection
ī‚¤ Inheriting from TInjectableAutoCreateFields
type
TServiceToBeTested = class(TInjectableObjectAutoCreateFields,
IServiceToBeTested)
protected
fService: IInjectedService;
fNestedObject: TSynPersistentValue;
published
property Service: IInjectedService read fService;
property NestedObject: TSynPersistentValue read fNestedObject;
end;
ī‚¤ Will auto-define published properties
īŽ Resolve interface services
īŽ Create TPersistent TSynPersistent TAutoCreateField
From Interfaces to SOLID
Weak references
ī‚¨ Delphi type reference model
ī‚¤ class
īŽ as weak references (plain pointer) and explicit Free
īŽ with TComponent ownership for the VCL/FMX
ī‚¤ integer Int64 currency double record
widestring variant
īŽ with explicit copy
ī‚¤ string or any dynamic array
īŽ via copy-on-write (COW) with reference counting
ī‚¤ interface
īŽ as strong reference with reference counting
From Interfaces to SOLID
Weak references
ī‚¨ Strong reference-counted types (OLE/ COM)
ī‚¤ Will increase the count at assignment
ī‚¤ And decrease the count at owner’s release
ī‚¤ When the count reaches 0, release the instance
ī‚¨ Issue comes when there are
ī‚¤ Circular references
ī‚¤ External list(s) of references
From Interfaces to SOLID
Weak references
ī‚¨ Managed languages (C# or Java)
ī‚¤ Will let the Garbage Collector handle
interface variable life time
ī‚¤ This is complex and resource consuming
ī‚¤ But easy to work with
ī‚¨ Unmanaged languages (Delphi or ObjectiveC)
ī‚¤ Need explicit weak reference behavior
ī‚¤ mORMot features zeroing weak pointers
īŽ Like Apple’s ARC model
From Interfaces to SOLID
Weak references
ī‚¨ Zeroing weak pointers
From Interfaces to SOLID
IParent = interface
procedure SetChild(const Value: IChild);
function GetChild: IChild;
function HasChild: boolean;
property Child: IChild read GetChild write SetChild;
end;
IChild = interface
procedure SetParent(const Value: IParent);
function GetParent: IParent;
property Parent: IParent read GetParent write SetParent;
end;
Weak references
ī‚¨ Zeroing weak pointers
This code will leak memory
From Interfaces to SOLID
IParent = interface
procedure SetChild(const Value: IChild);
function GetChild: IChild;
function HasChild: boolean;
property Child: IChild read GetChild write SetChild;
end;
IChild = interface
procedure SetParent(const Value: IParent);
function GetParent: IParent;
property Parent: IParent read GetParent write SetParent;
end;
procedure TParent.SetChild(const Value: IChild);
begin
FChild := Value;
end;
procedure TChild.SetParent(const Value: IParent);
begin
FParent := Value;
end;
Weak references
ī‚¨ Zeroing weak pointers
This code won’t leak memory
FChild and FParent will be set to nil
when the stored instance will be freed
From Interfaces to SOLID
IParent = interface
procedure SetChild(const Value: IChild);
function GetChild: IChild;
function HasChild: boolean;
property Child: IChild read GetChild write SetChild;
end;
IChild = interface
procedure SetParent(const Value: IParent);
function GetParent: IParent;
property Parent: IParent read GetParent write SetParent;
end;
procedure TParent.SetChild(const Value: IChild);
begin
SetWeakZero(self,@FChild,Value);
end;
procedure TChild.SetParent(const Value: IParent);
begin
SetWeakZero(self,@FParent,Value);
end;
Weak references
ī‚¨ Delphi NextGen memory model
ī‚¤ Uses ARC for every TObject instance
īŽ This is transparent for TComponent / FMX
īŽ No try â€Ļ finally Free block needed
īŽ But breaks the proven weak reference model
and a lot of existing code
ī‚¤ Only UTF-16 string type
īŽ Direct 8 bit string type disabled īŒ
īŽ UTF8String RawByteString back in 10.1 Berlin īŠ
From Interfaces to SOLID
From Interfaces to SOLID

More Related Content

What's hot

Api and Fluency
Api and FluencyApi and Fluency
Api and FluencyStefano Fago
 
Visual Studio.NET
Visual Studio.NETVisual Studio.NET
Visual Studio.NETsalonityagi
 
Entity Framework 4 In Microsoft Visual Studio 2010 - ericnel
Entity Framework 4 In Microsoft Visual Studio 2010 - ericnelEntity Framework 4 In Microsoft Visual Studio 2010 - ericnel
Entity Framework 4 In Microsoft Visual Studio 2010 - ericnelukdpe
 
Presentation On Com Dcom
Presentation On Com DcomPresentation On Com Dcom
Presentation On Com DcomBharat Kumar Katur
 
Corba model ppt
Corba model pptCorba model ppt
Corba model pptSaransh Garg
 
Lecture4 corba
Lecture4   corbaLecture4   corba
Lecture4 corbapoovi117
 
Corba and-java
Corba and-javaCorba and-java
Corba and-javaafreen58
 
Distributed Objects: CORBA/Java RMI
Distributed Objects: CORBA/Java RMIDistributed Objects: CORBA/Java RMI
Distributed Objects: CORBA/Java RMIelliando dias
 
Common Object Request Broker Architecture - CORBA
Common Object Request Broker Architecture - CORBACommon Object Request Broker Architecture - CORBA
Common Object Request Broker Architecture - CORBAPeter R. Egli
 
Towards Semantic Modeling of Network Physical Devices
Towards Semantic Modeling of Network Physical DevicesTowards Semantic Modeling of Network Physical Devices
Towards Semantic Modeling of Network Physical DevicesTobias Walter
 
Web-Dev Portfolio
Web-Dev PortfolioWeb-Dev Portfolio
Web-Dev Portfolionwbgh
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The EnterpriseDaniel Egan
 

What's hot (20)

Chapter2
Chapter2Chapter2
Chapter2
 
C O R B A Unit 4
C O R B A    Unit 4C O R B A    Unit 4
C O R B A Unit 4
 
Api and Fluency
Api and FluencyApi and Fluency
Api and Fluency
 
dot NET Framework
dot NET Frameworkdot NET Framework
dot NET Framework
 
VB.net
VB.netVB.net
VB.net
 
Visual Studio.NET
Visual Studio.NETVisual Studio.NET
Visual Studio.NET
 
Wwf
WwfWwf
Wwf
 
Entity Framework 4 In Microsoft Visual Studio 2010 - ericnel
Entity Framework 4 In Microsoft Visual Studio 2010 - ericnelEntity Framework 4 In Microsoft Visual Studio 2010 - ericnel
Entity Framework 4 In Microsoft Visual Studio 2010 - ericnel
 
Presentation On Com Dcom
Presentation On Com DcomPresentation On Com Dcom
Presentation On Com Dcom
 
Corba model ppt
Corba model pptCorba model ppt
Corba model ppt
 
Corba by Example
Corba by ExampleCorba by Example
Corba by Example
 
Lecture4 corba
Lecture4   corbaLecture4   corba
Lecture4 corba
 
Corba and-java
Corba and-javaCorba and-java
Corba and-java
 
CORBA & RMI in java
CORBA & RMI in javaCORBA & RMI in java
CORBA & RMI in java
 
Distributed Objects: CORBA/Java RMI
Distributed Objects: CORBA/Java RMIDistributed Objects: CORBA/Java RMI
Distributed Objects: CORBA/Java RMI
 
Common Object Request Broker Architecture - CORBA
Common Object Request Broker Architecture - CORBACommon Object Request Broker Architecture - CORBA
Common Object Request Broker Architecture - CORBA
 
Objc
ObjcObjc
Objc
 
Towards Semantic Modeling of Network Physical Devices
Towards Semantic Modeling of Network Physical DevicesTowards Semantic Modeling of Network Physical Devices
Towards Semantic Modeling of Network Physical Devices
 
Web-Dev Portfolio
Web-Dev PortfolioWeb-Dev Portfolio
Web-Dev Portfolio
 
Linq To The Enterprise
Linq To The EnterpriseLinq To The Enterprise
Linq To The Enterprise
 

Viewers also liked

Ekon20 mORMot WorkShop Delphi
Ekon20 mORMot WorkShop DelphiEkon20 mORMot WorkShop Delphi
Ekon20 mORMot WorkShop DelphiArnaud Bouchez
 
Ekon20 mORMot Legacy Code Technical Debt Delphi Conference
Ekon20 mORMot Legacy Code Technical Debt Delphi Conference Ekon20 mORMot Legacy Code Technical Debt Delphi Conference
Ekon20 mORMot Legacy Code Technical Debt Delphi Conference Arnaud Bouchez
 
A2 from soap to rest
A2 from soap to restA2 from soap to rest
A2 from soap to restArnaud Bouchez
 
A Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 Languages
A Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 LanguagesA Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 Languages
A Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 Languagesijpla
 
Delphi ORM SOA MVC SQL NoSQL JSON REST mORMot
Delphi ORM SOA MVC SQL NoSQL JSON REST mORMotDelphi ORM SOA MVC SQL NoSQL JSON REST mORMot
Delphi ORM SOA MVC SQL NoSQL JSON REST mORMotArnaud Bouchez
 

Viewers also liked (6)

Ekon20 mORMot WorkShop Delphi
Ekon20 mORMot WorkShop DelphiEkon20 mORMot WorkShop Delphi
Ekon20 mORMot WorkShop Delphi
 
2016 mORMot
2016 mORMot2016 mORMot
2016 mORMot
 
Ekon20 mORMot Legacy Code Technical Debt Delphi Conference
Ekon20 mORMot Legacy Code Technical Debt Delphi Conference Ekon20 mORMot Legacy Code Technical Debt Delphi Conference
Ekon20 mORMot Legacy Code Technical Debt Delphi Conference
 
A2 from soap to rest
A2 from soap to restA2 from soap to rest
A2 from soap to rest
 
A Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 Languages
A Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 LanguagesA Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 Languages
A Performance Comparison Of C# 2013, Delphi Xe6, And Python 3.4 Languages
 
Delphi ORM SOA MVC SQL NoSQL JSON REST mORMot
Delphi ORM SOA MVC SQL NoSQL JSON REST mORMotDelphi ORM SOA MVC SQL NoSQL JSON REST mORMot
Delphi ORM SOA MVC SQL NoSQL JSON REST mORMot
 

Similar to D1 from interfaces to solid

Ekon21 Microservices - SOLID Meets SOA
Ekon21 Microservices - SOLID Meets SOAEkon21 Microservices - SOLID Meets SOA
Ekon21 Microservices - SOLID Meets SOAArnaud Bouchez
 
Framework Design Guidelines For Brussels Users Group
Framework Design Guidelines For Brussels Users GroupFramework Design Guidelines For Brussels Users Group
Framework Design Guidelines For Brussels Users Groupbrada
 
OpenDaylight and YANG
OpenDaylight and YANGOpenDaylight and YANG
OpenDaylight and YANGCoreStack
 
C#3.0 & Vb 9.0 New Features
C#3.0 & Vb 9.0 New FeaturesC#3.0 & Vb 9.0 New Features
C#3.0 & Vb 9.0 New Featurestechfreak
 
Using advanced C# features in Sharepoint development
Using advanced C# features in Sharepoint developmentUsing advanced C# features in Sharepoint development
Using advanced C# features in Sharepoint developmentsadomovalex
 
Framework engineering JCO 2011
Framework engineering JCO 2011Framework engineering JCO 2011
Framework engineering JCO 2011YoungSu Son
 
Java and android 6 weeks Training in Noida
Java and android 6 weeks Training in NoidaJava and android 6 weeks Training in Noida
Java and android 6 weeks Training in NoidaAditya Kaushik
 
1.Philosophy of .NET
1.Philosophy of .NET1.Philosophy of .NET
1.Philosophy of .NETsnandagopalan2
 
An Introduction to the SOLID Principles
An Introduction to the SOLID PrinciplesAn Introduction to the SOLID Principles
An Introduction to the SOLID PrinciplesAttila BertÃŗk
 
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2Hammad Rajjoub
 
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2Hammad Rajjoub
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignRiccardo Cardin
 
Object Oriented Concepts and Principles
Object Oriented Concepts and PrinciplesObject Oriented Concepts and Principles
Object Oriented Concepts and Principlesdeonpmeyer
 
16 implementation techniques
16 implementation techniques16 implementation techniques
16 implementation techniquesMajong DevJfu
 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An OverviewIndrajit Das
 
Code Analysis and Refactoring with CDT
Code Analysis and Refactoring with CDTCode Analysis and Refactoring with CDT
Code Analysis and Refactoring with CDTdschaefer
 

Similar to D1 from interfaces to solid (20)

Ekon21 Microservices - SOLID Meets SOA
Ekon21 Microservices - SOLID Meets SOAEkon21 Microservices - SOLID Meets SOA
Ekon21 Microservices - SOLID Meets SOA
 
C# Unit 1 notes
C# Unit 1 notesC# Unit 1 notes
C# Unit 1 notes
 
Framework Design Guidelines For Brussels Users Group
Framework Design Guidelines For Brussels Users GroupFramework Design Guidelines For Brussels Users Group
Framework Design Guidelines For Brussels Users Group
 
OpenDaylight and YANG
OpenDaylight and YANGOpenDaylight and YANG
OpenDaylight and YANG
 
C#3.0 & Vb 9.0 New Features
C#3.0 & Vb 9.0 New FeaturesC#3.0 & Vb 9.0 New Features
C#3.0 & Vb 9.0 New Features
 
Using advanced C# features in Sharepoint development
Using advanced C# features in Sharepoint developmentUsing advanced C# features in Sharepoint development
Using advanced C# features in Sharepoint development
 
Framework engineering JCO 2011
Framework engineering JCO 2011Framework engineering JCO 2011
Framework engineering JCO 2011
 
Verilog
VerilogVerilog
Verilog
 
COM Introduction
COM IntroductionCOM Introduction
COM Introduction
 
Java and android 6 weeks Training in Noida
Java and android 6 weeks Training in NoidaJava and android 6 weeks Training in Noida
Java and android 6 weeks Training in Noida
 
1.Philosophy of .NET
1.Philosophy of .NET1.Philosophy of .NET
1.Philosophy of .NET
 
An Introduction to the SOLID Principles
An Introduction to the SOLID PrinciplesAn Introduction to the SOLID Principles
An Introduction to the SOLID Principles
 
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2
 
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2
 
S6 cad5
S6 cad5S6 cad5
S6 cad5
 
SOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented DesignSOLID - Principles of Object Oriented Design
SOLID - Principles of Object Oriented Design
 
Object Oriented Concepts and Principles
Object Oriented Concepts and PrinciplesObject Oriented Concepts and Principles
Object Oriented Concepts and Principles
 
16 implementation techniques
16 implementation techniques16 implementation techniques
16 implementation techniques
 
Java 8 - An Overview
Java 8 - An OverviewJava 8 - An Overview
Java 8 - An Overview
 
Code Analysis and Refactoring with CDT
Code Analysis and Refactoring with CDTCode Analysis and Refactoring with CDT
Code Analysis and Refactoring with CDT
 

More from Arnaud Bouchez

EKON27-FrameworksTuning.pdf
EKON27-FrameworksTuning.pdfEKON27-FrameworksTuning.pdf
EKON27-FrameworksTuning.pdfArnaud Bouchez
 
EKON27-FrameworksExpressiveness.pdf
EKON27-FrameworksExpressiveness.pdfEKON27-FrameworksExpressiveness.pdf
EKON27-FrameworksExpressiveness.pdfArnaud Bouchez
 
Ekon25 mORMot 2 Server-Side Notifications
Ekon25 mORMot 2 Server-Side NotificationsEkon25 mORMot 2 Server-Side Notifications
Ekon25 mORMot 2 Server-Side NotificationsArnaud Bouchez
 
Ekon25 mORMot 2 Cryptography
Ekon25 mORMot 2 CryptographyEkon25 mORMot 2 Cryptography
Ekon25 mORMot 2 CryptographyArnaud Bouchez
 
Ekon24 from Delphi to AVX2
Ekon24 from Delphi to AVX2Ekon24 from Delphi to AVX2
Ekon24 from Delphi to AVX2Arnaud Bouchez
 
Ekon23 (2) Kingdom-Driven-Design applied to Social Media with mORMot
Ekon23 (2) Kingdom-Driven-Design applied to Social Media with mORMotEkon23 (2) Kingdom-Driven-Design applied to Social Media with mORMot
Ekon23 (2) Kingdom-Driven-Design applied to Social Media with mORMotArnaud Bouchez
 
Ekon23 (1) Kingdom-Driven-Design
Ekon23 (1) Kingdom-Driven-DesignEkon23 (1) Kingdom-Driven-Design
Ekon23 (1) Kingdom-Driven-DesignArnaud Bouchez
 
High Performance Object Pascal Code on Servers (at EKON 22)
High Performance Object Pascal Code on Servers (at EKON 22)High Performance Object Pascal Code on Servers (at EKON 22)
High Performance Object Pascal Code on Servers (at EKON 22)Arnaud Bouchez
 
Object Pascal Clean Code Guidelines Proposal (at EKON 22)
Object Pascal Clean Code Guidelines Proposal (at EKON 22)Object Pascal Clean Code Guidelines Proposal (at EKON 22)
Object Pascal Clean Code Guidelines Proposal (at EKON 22)Arnaud Bouchez
 
Ekon21 Microservices - Event Driven Design
Ekon21 Microservices - Event Driven DesignEkon21 Microservices - Event Driven Design
Ekon21 Microservices - Event Driven DesignArnaud Bouchez
 

More from Arnaud Bouchez (11)

EKON27-FrameworksTuning.pdf
EKON27-FrameworksTuning.pdfEKON27-FrameworksTuning.pdf
EKON27-FrameworksTuning.pdf
 
EKON27-FrameworksExpressiveness.pdf
EKON27-FrameworksExpressiveness.pdfEKON27-FrameworksExpressiveness.pdf
EKON27-FrameworksExpressiveness.pdf
 
Ekon25 mORMot 2 Server-Side Notifications
Ekon25 mORMot 2 Server-Side NotificationsEkon25 mORMot 2 Server-Side Notifications
Ekon25 mORMot 2 Server-Side Notifications
 
Ekon25 mORMot 2 Cryptography
Ekon25 mORMot 2 CryptographyEkon25 mORMot 2 Cryptography
Ekon25 mORMot 2 Cryptography
 
Ekon24 from Delphi to AVX2
Ekon24 from Delphi to AVX2Ekon24 from Delphi to AVX2
Ekon24 from Delphi to AVX2
 
Ekon24 mORMot 2
Ekon24 mORMot 2Ekon24 mORMot 2
Ekon24 mORMot 2
 
Ekon23 (2) Kingdom-Driven-Design applied to Social Media with mORMot
Ekon23 (2) Kingdom-Driven-Design applied to Social Media with mORMotEkon23 (2) Kingdom-Driven-Design applied to Social Media with mORMot
Ekon23 (2) Kingdom-Driven-Design applied to Social Media with mORMot
 
Ekon23 (1) Kingdom-Driven-Design
Ekon23 (1) Kingdom-Driven-DesignEkon23 (1) Kingdom-Driven-Design
Ekon23 (1) Kingdom-Driven-Design
 
High Performance Object Pascal Code on Servers (at EKON 22)
High Performance Object Pascal Code on Servers (at EKON 22)High Performance Object Pascal Code on Servers (at EKON 22)
High Performance Object Pascal Code on Servers (at EKON 22)
 
Object Pascal Clean Code Guidelines Proposal (at EKON 22)
Object Pascal Clean Code Guidelines Proposal (at EKON 22)Object Pascal Clean Code Guidelines Proposal (at EKON 22)
Object Pascal Clean Code Guidelines Proposal (at EKON 22)
 
Ekon21 Microservices - Event Driven Design
Ekon21 Microservices - Event Driven DesignEkon21 Microservices - Event Driven Design
Ekon21 Microservices - Event Driven Design
 

Recently uploaded

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....ShaimaaMohamedGalal
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸
call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸
call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸Delhi Call girls
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfWilly Marroquin (WillyDevNET)
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...harshavardhanraghave
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 

Recently uploaded (20)

Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
Clustering techniques data mining book ....
Clustering techniques data mining book ....Clustering techniques data mining book ....
Clustering techniques data mining book ....
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸
call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸
call girls in Vaishali (Ghaziabad) 🔝 >āŧ’8448380779 🔝 genuine Escort Service 🔝✔ī¸âœ”ī¸
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
Vip Call Girls Noida ➡ī¸ Delhi ➡ī¸ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡ī¸ Delhi ➡ī¸ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡ī¸ Delhi ➡ī¸ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡ī¸ Delhi ➡ī¸ 9999965857 No Advance 24HRS Live
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
Reassessing the Bedrock of Clinical Function Models: An Examination of Large ...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi đŸĢĻ HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi đŸĢĻ HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi đŸĢĻ HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi đŸĢĻ HOT AND SEXY VVIP 🍎 SE...
 

D1 from interfaces to solid

  • 1. Software Architecture & Design ī‚¨ Architecture ī‚¤ From n-Tier to SOA ī‚¤ From SOAP to REST ī‚¤ Technical Debt ī‚¨ Design ī‚¤ From SQL to ORM, NoSQL and ODM ī‚¤ From RAD to MVC ī‚¤ SOLID principles ī‚¤ Domain Driven Design (DDD) Applying patterns on Delphi code using mORMot Software Architecture & Design
  • 3. From Interfaces to SOLID ī‚¨ Delphi and interfaces ī‚¨ SOLID design principles ī‚¨ Dependency Injection, stubs and mocks ī‚¨ Using mORMot features ī‚¨ Delphi and Weak pointers From Interfaces to SOLID
  • 4. Delphi and interfaces ī‚¨ In Delphi OOP model ī‚¤ An interface defines a type that comprises abstract virtual methods ī‚¤ It is a declaration of functionality without an implementation of that functionality ī‚¤ It defines "what" is available, not "how" it is made available From Interfaces to SOLID
  • 5. Delphi and interfaces ī‚¨ Declaring an interface īŽ Naming convention: ICalculator īŽ No visibility attribute: all published īŽ No fields, just methods and properties īŽ Unique identifier by GUID (Ctrl Shift G) From Interfaces to SOLID type ICalculator = interface(IInvokable) ['{9A60C8ED-CEB2-4E09-87D4-4A16F496E5FE}'] /// add two signed 32 bit integers function Add(n1,n2: integer): integer; end;
  • 6. Delphi and interfaces ī‚¨ Implementing an interface īŽ ICalculator added to the “inheritance chain” īŽ TCalculator implements a behavior From Interfaces to SOLID type TServiceCalculator = class(TInterfacedObject, ICalculator) protected fBulk: string; public function Add(n1,n2: integer): integer; procedure SetBulk(const aValue: string); end; function TServiceCalculator.Add(n1, n2: integer): integer; begin result := n1+n2; end; procedure TServiceCalculator.SetBulk(const aValue: string); begin fBulk := aValue; end;
  • 7. Delphi and interfaces ī‚¨ Using an interface īŽ Strong typing īŽ The variable defines a behavior (contract) īŽ Path to abstraction From Interfaces to SOLID function MyAdd(a,b: integer): integer; var Calculator: ICalculator; begin Calculator := TServiceCalculator.Create; result := Calculator.Add(a,b); end;
  • 8. Delphi and interfaces ī‚¨ Using an interface īŽ Strong typing īŽ The variable defines a behavior (contract) īŽ Path to abstraction īŽ Automatic try..finally From Interfaces to SOLID function MyAdd(a,b: integer): integer; var Calculator: TServiceCalculator; begin Calculator := TServiceCalculator.Create; try result := Calculator.Add(a,b); finally Calculator.Free; end; end; function MyAdd(a,b: integer): integer; var Calculator: ICalculator; begin Calculator := TServiceCalculator.Create; result := Calculator.Add(a,b); end;
  • 9. Delphi and interfaces ī‚¨ Automatic try..finally ī‚¤ Compiler generates some hidden codeâ€Ļ īŽ Behavior inherited from TInterfacedObject īŽ Similar to COM / ActiveX From Interfaces to SOLID function MyAdd(a,b: integer): integer; var Calculator: ICalculator; begin Calculator := TServiceCalculator.Create; result := Calculator.Add(a,b); end; function MyAdd(a,b: integer): integer; var Calculator: TServiceCalculator; begin Calculator := nil; Calculator := TServiceCalculator.Create; try Calculator.FRefCount := 1; result := Calculator.Add(a,b); finally dec(Calculator.FRefCount); if Calculator.FRefCount=0 then Calculator.Free; end; end;
  • 10. Delphi and interfaces ī‚¨ Interfaces are orthogonal to implementation ī‚¤ There is more than one way to do it From Interfaces to SOLID type TOtherServiceCalculator = class(TInterfacedObject, ICalculator) protected function Add(n1,n2: integer): integer; end; function TOtherServiceCalculator.Add(n1, n2: integer): integer; begin result := n2+n1; end; function MyOtherAdd(a,b: integer): integer; var Calculator: ICalculator; begin ICalculator := TOtherServiceCalculator.Create; result := Calculator.Add(a,b); end;
  • 11. SOLID design principles ī‚¨ Single responsibility principle ī‚¨ Open/closed principle ī‚¨ Liskov substitution principle (design by contract) ī‚¨ Interface segregation principle ī‚¨ Dependency inversion principle From Interfaces to SOLID
  • 12. SOLID design principles ī‚¨ Single responsibility ī‚¤ Object should have only a single responsibility ī‚¨ Open/closed ī‚¤ Entities should be open for extension, but closed for modification ī‚¨ Liskov substitution (design by contract) ī‚¤ Objects should be replaceable with instances of their subtypes without altering the correctness of that program ī‚¨ Interface segregation ī‚¤ Many specific interfaces are better than one ī‚¨ Dependency inversion ī‚¤ Depend upon abstractions, not depend upon concretions From Interfaces to SOLID
  • 13. SOLID design principles ī‚¨ Help to fight well-known weaknesses ī‚¤ Rigidity īŽ Hard to change something because every change affects too many other parts of the system ī‚¤ Fragility īŽ When you make a change, unexpected parts of the system break ī‚¤ Immobility īŽ Hard to reuse in another application because it cannot be disentangled from the current application From Interfaces to SOLID
  • 14. SOLID design principles ī‚¨ Single Responsibility ī‚¤ When you define a class, it shall be designed to implement only one feature ī‚¤ The so-called feature can be seen as an "axis of change" or a "a reason for change" From Interfaces to SOLID
  • 15. SOLID design principles ī‚¨ Single Responsibility ī‚¤ One class shall have only one reason that justifies changing its implementation ī‚¤ Classes shall have few dependencies on other classes ī‚¤ Classes shall be abstracted from the particular layer they are running From Interfaces to SOLID
  • 16. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Splitting classes īŽ Imagine a TBarCodeScanner class to handle a serial bar-code scanner īŽ Later on, we want to implement USB support īŽ First idea may be to inherit From Interfaces to SOLID
  • 17. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Splitting classes īŽ Imagine a TBarCodeScanner class to handle a serial bar-code scanner īŽ Later on, we want to implement USB support īŽ But we would rather split the class hierarchy From Interfaces to SOLID
  • 18. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Splitting classes īŽ Later on, the manufacturer updates its protocol To add new features, e.g. 3D scanning or coffee making īŽ How do we implement this? īŽ We have two “axis of change” so we would define two classes From Interfaces to SOLID
  • 19. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Splitting classes īŽ Later on, the manufacturer updates its protocol To add new features, e.g. 3D scanning or coffee making īŽ We defined two classes, which will be joined/composed in actual barcode scanner classes From Interfaces to SOLID
  • 20. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Splitting classes TAbstractBarcodeScanner = class(TComponent) protected fProtocol: TAbstractBarcodeProtocol; fConnection: AbstractBarcodeConnection; ... constructor TSerialBarCodeScanner.Create( const aComPort: string; aBitRate: integer); begin fConnection := TSerialBarcodeConnection(aComPort,aBitRate); fProtocol := TBCP1BarcodeProtocol.Create(fConnection); end; From Interfaces to SOLID
  • 21. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Another example from SynDB class definitions: īŽ TSQLDBConnectionProperties īŽ TSQLDBConnection īŽ TSQLDBStatement ī‚¤ Each class has its own purpose, and axis of change īŽ And could be implemented via ODBC, OleDB, direct client accessâ€Ļ From Interfaces to SOLID
  • 22. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Do not mix GUI and logic ī‚¤ Do not mix logic and database ī‚¤ Do not couple your code to an OS īŽ Check your uses statement īŽ There should be no reference to the UI (e.g. Dialogs) in your business class īŽ No dependency to DB libraries (this is a hard one) īŽ No reference to WinAPI.Windows From Interfaces to SOLID
  • 23. SOLID design principles ī‚¨ Single Responsibility ī‚¤ Code smells īŽ When abusing of: FreeAndNil() {$ifdef} â€Ļ {$endif} uses unit1, unit2, unit3, â€Ļ unit1000; īŽ When you can’t find the right method in a class īŽ (mORMot may need some refactoring here) īŠ īŽ When unitary tests are hard to write From Interfaces to SOLID
  • 24. SOLID design principles ī‚¨ Open / Close principle ī‚¤ When you define a class or an interface īŽ it shall be open for extension īŽ but closed for modification From Interfaces to SOLID
  • 25. SOLID design principles ī‚¨ Open / Closed principle ī‚¤ Open for extension īŽ Abstract class is overridden by implementations īŽ No singleton nor global variable – ever īŽ Rely on abstraction īŽ if aObject is aClass then â€Ļ it stinks! ī‚¤ Closed for modification īŽ E.g. via explicitly protected or private members īŽ RTTI is dangerous: it may open the closed door From Interfaces to SOLID
  • 26. SOLID design principles ī‚¨ Open / Closed principle ī‚¤ In practice īŽ Define meaningful interface types īŽ Following the Design By Contract principle īŽ Define Value objects (DTOs) to transfer the data īŽ With almost no methods, but for initialization īŽ With public members, to access the value īŽ Define Process objects to modify the data īŽ With public methods, abstracted in the interface īŽ With mostly private members From Interfaces to SOLID
  • 27. SOLID design principles ī‚¨ Open / Close principle type TAbstractBarcodeScanner = class(TComponent) protected fProtocol: TAbstractBarcodeProtocol; fConnection: AbstractBarcodeConnection; public property Protocol: TAbstractBarcodeProtocol read fProtocol; property Connection: AbstractBarcodeConnection read fConnection; ... īŽ Protocol and Connection are read/only īŽ They are injected by the overridden class constructor īŽ So it will be Open for extension From Interfaces to SOLID
  • 28. SOLID design principles ī‚¨ Open / Close principle type TAbstractBarcodeScanner = class(TComponent) protected fProtocol: TAbstractBarcodeProtocol; fConnection: AbstractBarcodeConnection; public property Protocol: TAbstractBarcodeProtocol read fProtocol; property Connection: AbstractBarcodeConnection read fConnection; ... īŽ Protocol and Connection are read/only īŽ You could not change the behavior of a class īŽ It is Closed for modification From Interfaces to SOLID
  • 29. SOLID design principles ī‚¨ Liskov substitution principle From Interfaces to SOLID
  • 30. SOLID design principles ī‚¨ Liskov substitution principle From Interfaces to SOLID
  • 31. SOLID design principles ī‚¨ Liskov substitution principle ī‚¤ If TChild is a subtype of TParent īŽ then objects of type TParent may be replaced with objects of type TChild īŽ without altering any of the desirable properties of that program (correctness, task performed, etc.) From Interfaces to SOLID
  • 32. SOLID design principles ī‚¨ Liskov substitution principle ī‚¤ Tied to the Open / Closed principle īŽ If you define a child, you should not modify the parent ī‚¤ Code-reusability of the parent implementation ī‚¤ You will be able to stub or mock an interface or a class īŽ Allow correct testing of a whole system: even if all single unit tests did pass, real system may not work if this principle was broken From Interfaces to SOLID
  • 33. SOLID design principles ī‚¨ Liskov substitution patterns ī‚¤ Design by contract īŽ Meyer's (Eiffel language) rule: “when redefining a routine [in a derivative], you may only replace its precondition by a weaker one, and its postcondition by a stronger one” īŽ Define assertions at method level: īŽ What does it expect, guarantee, and maintain? īŽ About input/output values or types, side effects, invariants, errors/exceptions, performanceâ€Ļ From Interfaces to SOLID
  • 34. SOLID design principles ī‚¨ Liskov substitution patterns ī‚¤ Write your code using abstract variables īŽ Rely on parents methods and properties īŽ Use interface variables instead of class implementation īŽ Uncouple dependencies via class composition From Interfaces to SOLID
  • 35. SOLID design principles ī‚¨ Liskov substitution patterns ī‚¤ Factory pattern īŽ In strongly typed languages (Java, C#, Delphi), the factory is the class/object type and its constructor ī‚¤ Repository pattern īŽ Allow persistence agnosticism (e.g. via ORM) ī‚¤ Service locator pattern īŽ Get a class instance implementing a given interface īŽ According to the given context (no global/singleton) From Interfaces to SOLID
  • 36. SOLID design principles ī‚¨ Liskov substitution patterns ī‚¤ Practical, not dogmatic LSP īŽ “Parent” and “Child” are not absolute īŽ Depending on the context, you may define a given level as the “highest” LSP abstract class īŽ e.g. if you work on server side, you may need some server-only properties and methods īŽ LSP idea is to be consistent, once the abstraction level is defined From Interfaces to SOLID
  • 37. SOLID design principles ī‚¨ Liskov substitution patterns ī‚¤ Practical, not dogmatic LSP īŽ “Parent” and “Child” are not absolute īŽ Inheritance is often used as code sharing among classes, not as an abstraction contract īŽ In this context, LSP may not apply at class level: be pragmatic, and write efficient code īŽ But LSP may apply at interface level, for a set of methods implemented by the class From Interfaces to SOLID
  • 38. SOLID design principles ī‚¨ Liskov substitution code smells if aObject is aClass then â€Ļ case aObject.EnumeratedType of â€Ļ function â€Ļ abstract; without further override; unit parent; uses child1,child2,child3; From Interfaces to SOLID
  • 39. SOLID design principles ī‚¨ Interface segregation principle ī‚¤ Once an interface has become too 'fat' it shall be split into smaller and more specific interfaces so that any clients of the interface will only know about the methods that pertain to them ī‚¤ In a nutshell, no client should be forced to depend on methods it does not use From Interfaces to SOLID
  • 40. SOLID design principles ī‚¨ Interface segregation principle ī‚¤ Smaller dedicated classes should be preferred īŽ Single Responsibility Principle īŽ Favor composition over inheritance ī‚¤ Smaller dedicated interfaces īŽ Gather operations/methods per context īŽ Meaningful naming and conventions īŽ So that the contract would be easier to understand From Interfaces to SOLID
  • 41. SOLID design principles ī‚¨ Interface segregation principle ī‚¤ Perfectly fits the SOA uncoupling pattern īŽ Stateless MicroServices for horizontal scaling ī‚¤ Allows to release memory and resources ASAP īŽ Smaller objects have more bounded dependencies ī‚¤ Ease unit testing īŽ Less coverage īŽ Less coupling From Interfaces to SOLID
  • 42. SOLID design principles ī‚¨ Interface segregation principle ī‚¤ Excludes RAD īŽ Logic implemented in TForm TDataModule where methods are procedural code in disguise īŽ Put your logic behind interfaces and call them from your UI (over VCL and FMX) ī‚¤ Favors DDD īŽ Segregation avoid domain leaking īŽ Dedicated interfaces, e.g. for third party consumption From Interfaces to SOLID
  • 43. SOLID design principles ī‚¨ Dependency Inversion ī‚¤ High-level modules should not depend on low-level modules īŽ Both should depend on abstractions īŽ Following other SOLI principles ī‚¤ Abstractions should not depend upon details īŽ Details should depend upon abstractions īŽ Business Logic should not depend on database īŽ Application Layer should not depend on client UI techno From Interfaces to SOLID
  • 44. SOLID design principles ī‚¨ Dependency Inversion ī‚¤ In most conventional programming style: īŽ You write low-level components (e.g. DB tables) īŽ Then you integrate them with high-level components ī‚¤ But this limits the re-use of high-level code īŽ In fact, it breaks the Liskov substitution principle īŽ It reduces the testing abilities (e.g. need of a real DB) From Interfaces to SOLID
  • 45. SOLID design principles ī‚¨ Dependency Inversion may be implemented ī‚¤ Via a plug-in system īŽ e.g. external libraries (for embedded applications) ī‚¤ Using a service locator īŽ e.g. SOA catalog (SaaS/cloud) īŽ class resolution from an interface type From Interfaces to SOLID
  • 46. SOLID design principles ī‚¨ Dependency Inversion may be implemented ī‚¤ Via Dependency Injection īŽ Concretions are injected to the objects using them īŽ Only abstractions are known at design/coding time īŽ Uncoupled implementation injected at runtime īŽ Modular coding īŽ Perfect for bigger/complex projects, with a set of teams īŽ Ease testing, via stub/mock dependencies injection īŽ e.g. a fake database, defined as a Repository service īŽ Scaling abilities From Interfaces to SOLID
  • 47. SOLID design principles ī‚¨ Dependency Inversion may be implemented ī‚¤ Via Dependency Injection īŽ A class will define its dependencies as read-only interface members īŽ Implementation will be injected at constructor level īŽ via explicit constructor parameters īŽ via automated resolution via RTTI īŽ via service locator/resolver From Interfaces to SOLID
  • 48. DI, Stubs and Mocks ī‚¨ Thanks to SOLID design principles ī‚¤ All your code logic will now be abstracted to the implementation underneath ī‚¤ But you need to inject the implementation īŽ This is Dependency Injection purpose ī‚¤ You can also create fake instances to implement a given interface, and enhance testing īŽ Introducing Stubs and Mocks From Interfaces to SOLID
  • 49. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Define external dependencies as interface īŽ as (private / protected) read-only members ī‚¤ To set the implementation instance: īŽ Either inject the interfaces as constructor parameters īŽ Or use a Factory / Service locator From Interfaces to SOLID
  • 50. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Purpose is to test the following class: From Interfaces to SOLID TLoginController = class(TInterfacedObject,ILoginController) protected fUserRepository: IUserRepository; fSmsSender: ISmsSender; public constructor Create(const aUserRepository: IUserRepository; const aSmsSender: ISmsSender); procedure ForgotMyPassword(const UserName: RawUTF8); end; constructor TLoginController.Create(const aUserRepository: IUserRepository; const aSmsSender: ISmsSender); begin fUserRepository := aUserRepository; fSmsSender := aSmsSender; end;
  • 51. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Dependencies are defined as īŽ Two small, uncoupled, SOLID task-specific interfaces From Interfaces to SOLID IUserRepository = interface(IInvokable) ['{B21E5B21-28F4-4874-8446-BD0B06DAA07F}'] function GetUserByName(const Name: RawUTF8): TUser; procedure Save(const User: TUser); end; ISmsSender = interface(IInvokable) ['{8F87CB56-5E2F-437E-B2E6-B3020835DC61}'] function Send(const Text, Number: RawUTF8): boolean; end;
  • 52. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Using a dedicated Data Transfer Object (DTO) īŽ No dependency against storage, nor other classes From Interfaces to SOLID IUserRepository = interface(IInvokable) ['{B21E5B21-28F4-4874-8446-BD0B06DAA07F}'] function GetUserByName(const Name: RawUTF8): TUser; procedure Save(const User: TUser); end; TUser = record Name: RawUTF8; Password: RawUTF8; MobilePhoneNumber: RawUTF8; ID: Integer; end;
  • 53. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ The high-level method to be tested: īŽ Open/Closed, Liskov and mainly Dependency Inversion principles are followed īŽ Will we need a full database and to send a SMS? From Interfaces to SOLID procedure TLoginController.ForgotMyPassword(const UserName: RawUTF8); var U: TUser; begin U := fUserRepository.GetUserByName(UserName); U.Password := Int32ToUtf8(Random(MaxInt)); if fSmsSender.Send('Your new password is '+U.Password,U.MobilePhoneNumber) then fUserRepository.Save(U); end;
  • 54. DI, Stubs and Mocks ī‚¨ "The Art of Unit Testing" (Osherove, Roy - 2009) ī‚¤ Stubs are fake objects implementing a given contract and returning pre-arranged responses īŽ They just let the test pass īŽ They “emulate” some behavior (e.g. a database) From Interfaces to SOLID
  • 55. DI, Stubs and Mocks ī‚¨ "The Art of Unit Testing" (Osherove, Roy - 2009) ī‚¤ Mocks are fake objects like stubs which will verify if an interaction occurred or not īŽ They help decide if a test failed or passed īŽ There should be only one mock per test From Interfaces to SOLID
  • 56. DI, Stubs and Mocks From Interfaces to SOLID
  • 57. DI, Stubs and Mocks ī‚¨ Expect – Run – Verify pattern From Interfaces to SOLID procedure TMyTest.ForgotMyPassword; var SmsSender: ISmsSender; UserRepository: IUserRepository; begin TInterfaceStub.Create(ISmsSender,SmsSender). Returns('Send',[true]); TInterfaceMock.Create(IUserRepository,UserRepository,self). ExpectsCount('Save',qoEqualTo,1); with TLoginController.Create(UserRepository,SmsSender) do try ForgotMyPassword('toto'); finally Free; end; end;
  • 58. DI, Stubs and Mocks ī‚¨ Expect – Run – Verify pattern īŽ TInterfaceStub / TInterfaceMock constructors are in fact Factories for any interface īŽ Clear distinction between stub and mock īŽ Mock is linked to its test case (self: TMyTest) From Interfaces to SOLID procedure TMyTest.ForgotMyPassword; var SmsSender: ISmsSender; UserRepository: IUserRepository; begin TInterfaceStub.Create(ISmsSender,SmsSender). Returns('Send',[true]); TInterfaceMock.Create(IUserRepository,UserRepository,self). ExpectsCount('Save',qoEqualTo,1);
  • 59. DI, Stubs and Mocks ī‚¨ Expect – Run – Verify pattern īŽ Execution code itself sounds like real-life code īŽ But all dependencies have been injected īŽ Stubs will emulate real behavior īŽ Mock will verify that all expectations are fulfilled From Interfaces to SOLID with TLoginController.Create(UserRepository,SmsSender) do try ForgotMyPassword('toto'); finally Free; end; end;
  • 60. DI, Stubs and Mocks ī‚¨ Expect – Run – Verify pattern From Interfaces to SOLID procedure TMyTest.ForgotMyPassword; var SmsSender: ISmsSender; UserRepository: IUserRepository; begin TInterfaceStub.Create(ISmsSender,SmsSender). Returns('Send',[true]); TInterfaceMock.Create(IUserRepository,UserRepository,self). ExpectsCount('Save',qoEqualTo,1); with TLoginController.Create(UserRepository,SmsSender) do try ForgotMyPassword('toto'); finally Free; end; end;
  • 61. DI, Stubs and Mocks ī‚¨ Run – Verify (aka “Test spy”) pattern From Interfaces to SOLID procedure TMyTest.ForgotMyPassword; var SmsSender: ISmsSender; UserRepository: IUserRepository; Spy: TInterfaceMockSpy; begin TInterfaceStub.Create(ISmsSender,SmsSender). Returns('Send',[true]); Spy := TInterfaceMockSpy.Create(IUserRepository,UserRepository,self); with TLoginController.Create(UserRepository,SmsSender) do try ForgotMyPassword('toto'); finally Free; end; Spy.Verify('Save'); end;
  • 62. DI, Stubs and Mocks ī‚¨ Another features: ī‚¤ Return complex values (e.g. a DTO) ī‚¤ Use a delegate to create a stub/mock īŽ Using named or indexed variant parameters īŽ Using JSON array of values ī‚¤ Access the test case when mocking ī‚¤ Trace and verify the calls īŽ With a fluent interface īŽ Log all calls (as JSON) From Interfaces to SOLID
  • 63. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Inheriting from TInjectableObject type TServiceToBeTested = class(TInjectableObject,IServiceToBeTested) protected fService: IInjectedService; published property Service: IInjectedService read fService; end; ī‚¤ Will auto-inject interface published properties īŽ At instance creation īŽ Handled by TSQLRest.Services From Interfaces to SOLID
  • 64. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Inheriting from TInjectableObject var Test: IServiceToBeTested; begin Test := TServiceToBeTested.CreateInjected( [ICalculator], [TInterfaceMock.Create(IPersistence,self). ExpectsCount('SaveItem',qoEqualTo,1), RestInstance.Services], [AnyInterfacedObject]); ... From Interfaces to SOLID
  • 65. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Inheriting from TInjectableObject procedure TServiceToBeTested.AnyProcessMethod; var Service: IInjectedService; begin Resolve(IInjectedService,Service); Service.DoSomething; end; From Interfaces to SOLID
  • 66. DI, Stubs and Mocks ī‚¨ Dependency Injection ī‚¤ Inheriting from TInjectableAutoCreateFields type TServiceToBeTested = class(TInjectableObjectAutoCreateFields, IServiceToBeTested) protected fService: IInjectedService; fNestedObject: TSynPersistentValue; published property Service: IInjectedService read fService; property NestedObject: TSynPersistentValue read fNestedObject; end; ī‚¤ Will auto-define published properties īŽ Resolve interface services īŽ Create TPersistent TSynPersistent TAutoCreateField From Interfaces to SOLID
  • 67. Weak references ī‚¨ Delphi type reference model ī‚¤ class īŽ as weak references (plain pointer) and explicit Free īŽ with TComponent ownership for the VCL/FMX ī‚¤ integer Int64 currency double record widestring variant īŽ with explicit copy ī‚¤ string or any dynamic array īŽ via copy-on-write (COW) with reference counting ī‚¤ interface īŽ as strong reference with reference counting From Interfaces to SOLID
  • 68. Weak references ī‚¨ Strong reference-counted types (OLE/ COM) ī‚¤ Will increase the count at assignment ī‚¤ And decrease the count at owner’s release ī‚¤ When the count reaches 0, release the instance ī‚¨ Issue comes when there are ī‚¤ Circular references ī‚¤ External list(s) of references From Interfaces to SOLID
  • 69. Weak references ī‚¨ Managed languages (C# or Java) ī‚¤ Will let the Garbage Collector handle interface variable life time ī‚¤ This is complex and resource consuming ī‚¤ But easy to work with ī‚¨ Unmanaged languages (Delphi or ObjectiveC) ī‚¤ Need explicit weak reference behavior ī‚¤ mORMot features zeroing weak pointers īŽ Like Apple’s ARC model From Interfaces to SOLID
  • 70. Weak references ī‚¨ Zeroing weak pointers From Interfaces to SOLID IParent = interface procedure SetChild(const Value: IChild); function GetChild: IChild; function HasChild: boolean; property Child: IChild read GetChild write SetChild; end; IChild = interface procedure SetParent(const Value: IParent); function GetParent: IParent; property Parent: IParent read GetParent write SetParent; end;
  • 71. Weak references ī‚¨ Zeroing weak pointers This code will leak memory From Interfaces to SOLID IParent = interface procedure SetChild(const Value: IChild); function GetChild: IChild; function HasChild: boolean; property Child: IChild read GetChild write SetChild; end; IChild = interface procedure SetParent(const Value: IParent); function GetParent: IParent; property Parent: IParent read GetParent write SetParent; end; procedure TParent.SetChild(const Value: IChild); begin FChild := Value; end; procedure TChild.SetParent(const Value: IParent); begin FParent := Value; end;
  • 72. Weak references ī‚¨ Zeroing weak pointers This code won’t leak memory FChild and FParent will be set to nil when the stored instance will be freed From Interfaces to SOLID IParent = interface procedure SetChild(const Value: IChild); function GetChild: IChild; function HasChild: boolean; property Child: IChild read GetChild write SetChild; end; IChild = interface procedure SetParent(const Value: IParent); function GetParent: IParent; property Parent: IParent read GetParent write SetParent; end; procedure TParent.SetChild(const Value: IChild); begin SetWeakZero(self,@FChild,Value); end; procedure TChild.SetParent(const Value: IParent); begin SetWeakZero(self,@FParent,Value); end;
  • 73. Weak references ī‚¨ Delphi NextGen memory model ī‚¤ Uses ARC for every TObject instance īŽ This is transparent for TComponent / FMX īŽ No try â€Ļ finally Free block needed īŽ But breaks the proven weak reference model and a lot of existing code ī‚¤ Only UTF-16 string type īŽ Direct 8 bit string type disabled īŒ īŽ UTF8String RawByteString back in 10.1 Berlin īŠ From Interfaces to SOLID