SlideShare uma empresa Scribd logo
1 de 137
Baixar para ler offline
PHPSpec
the only Design Tool you need
flickr.com/mobilestreetlife/4179063482/
Kacper Gunia @cakper
Software Engineer @SensioLabsUK
Symfony Certified Developer
PHPers Silesia @PHPersPL
!
‘Is my code well 

designed?’
’That’s not the way
I would have done it…’
It’s hard to

change!
We're afraid
to change it…
We cannot

reuse it!
So what
Design
is about?
‘The key in making great and
growable systems is much more to
design how its
modules communicate
rather than what their internal
properties and behaviors should be.’
Alan Kay
Design is about
Messaging
$orders	
  =	
  $orderRepository	
  
	
  	
  -­‐>getEntityManager()	
  
	
  	
  	
  -­‐>createOrderQuery($customer)	
  
	
  	
  	
  -­‐>execute();
$orders	
  =	
  $orderRepository	
  
	
  	
  -­‐>findBy($customer);	
  
!
We have
to refactor! :)
We need
two weeks
to refactor! :)
We need
two sprints
to refactor! :|
We need
two months
to refactor! :/
Refactoring
is the process of restructuring
existing code without
changing its external behavior
4 Rules of Simple Design
1. Passes its tests
2. Minimizes duplication
3. Maximizes clarity
4. Has fewer elements
…so we need
to write
Tests!
how
to write
Tests?
Tests
Driven
Development
Red
GreenRefactor
Red
GreenRefactor
But!
How to test
something that
doesn’t exist?
flickr.com/ucumari/580865728/
Test in TDD
means
specification
Specification
describes
behavior
Behavior
Driven
Development
BDD improves
Naming
Conventions
Tools
Story BDD
vs
Spec BDD
Story BDD
description of
business-targeted
application behavior
Spec BDD
specification for
low-level
implementation
http://phpspec.net/
Spec BDD
tool created by
@_md & @everzet
Bundled with
mocking library
Prophecy
composer	
  create-­‐project	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  

	
  	
  	
  	
  	
  	
  	
  	
  	
  cakper/phpspec-­‐standard	
  

	
  	
  	
  	
  	
  	
  	
  	
  	
  project-­‐name
But!
Isn’t it a tool just
like PHPUnit?
PHPUnit is a
Testing Tool
PHPSpec is the
Design Tool
class	
  CustomerRepositoryTest	
  extends	
  
PHPUnit_Framework_TestCase	
  
{	
  
	
  	
  	
  	
  function	
  testClassExists()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $customerRepository	
  =	
  new	
  CustomerRepository;	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  $customer	
  =	
  $customerRepository-­‐>findById(5);	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>assertInstanceOf('Customer',	
  $customer);	
  
	
  	
  	
  	
  }	
  
}
class	
  CustomerRepositorySpec	
  extends	
  ObjectBehavior	
  
{	
  
	
  	
  	
  	
  function	
  it_is_initializable()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $this-­‐>shouldHaveType('CustomerRepository');	
  
	
  	
  	
  	
  }	
  
}
Naming
TestCase
!
Specification
Test
!
Example
Assertion
!
Expectation
OK, so how to
specify a method?
What method can do?
return a value
modify state
delegate
throw an exception
Command-Query
Separation
Command
change the state of a system
but do not return a value
Query
return a result and do not
change the state of the
system (free of side effects)
Never both!
class	
  CustomerRepositorySpec	
  extends	
  ObjectBehavior	
  
{	
  
	
  	
  	
  	
  function	
  it_loads_user_preferences()	
  
	
  	
  	
  	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  $customer	
  =	
  $this-­‐>findById(5);	
  
!
	
  	
  	
  	
  	
  	
  	
  	
  $customer-­‐>shouldBeAnInstanceOf('Customer');	
  
	
  	
  	
  	
  }	
  
}
Matchers
Type
shouldBeAnInstanceOf(*)
shouldReturnAnInstanceOf(*)
shouldHaveType(*)
$customer-­‐>shouldBeAnInstanceOf('Customer');
Identity ===
shouldReturn(*)
shouldBe(*)
shouldEqual(*)
shouldBeEqualTo(*)
$this-­‐>findById(-­‐1)-­‐>shouldReturn(null);
Comparison ==
shouldBeLike(*)
$this-­‐>getAmount()-­‐>shouldBeLike(5);
Throw
throw(*)->during*()
$this-­‐>shouldThrow(‘InvalidArgumentException’)

	
  	
  	
  	
  	
  -­‐>duringFindByCustomer(null);
Object State
shouldHave*()
$car-­‐>hasEngine();	
  
!
$this-­‐>shouldHaveEngine();
Scalar
shouldBeString()
shouldBeArray()
Count
shouldHaveCount(*)
Or write your own
Inline Matcher
function	
  it_should_have_poland_as_avialable_country()	
  
{	
  
	
  	
  	
  	
  $this-­‐>getCountryCodes()-­‐>shouldHaveValue('PL');	
  
}	
  
!
public	
  function	
  getMatchers()	
  
{	
  
	
  	
  	
  	
  return	
  [	
  
	
  	
  	
  	
  	
  	
  	
  	
  'haveValue'	
  =>	
  function	
  ($subject,	
  $value)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  return	
  in_array($value,	
  $subject);	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  }	
  
	
  	
  	
  	
  ];	
  
}
But!
Design is about
Messaging!
And (so far) there
is no messaging…
London School
Mockist TDD
only tested object is real
Test Doubles
Dummy
tested code requires
parameter but
doesn’t need to use it
function	
  let(EntityManager	
  $entityManager)	
  
{	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($entityManager);	
  
}	
  
!
function	
  it_returns_customer_by_id()	
  
{	
  
	
  	
  	
  	
  $customer	
  =	
  $this-­‐>findById(5);	
  
!
	
  	
  	
  	
  $customer-­‐>shouldBeAnInstanceOf('Customer');	
  
	
  	
  	
  	
  }	
  
}
function	
  let(EntityManager	
  $entityManager)	
  
{	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($entityManager);	
  
}	
  
!
function	
  it_returns_customer_by_id()	
  
{	
  
	
  	
  	
  	
  $customer	
  =	
  $this-­‐>findById(5);	
  
!
	
  	
  	
  	
  $customer-­‐>shouldBeAnInstanceOf('Customer');	
  
	
  	
  	
  	
  }	
  
}
Stub
provides "indirect input"
to the tested code
function	
  it_bolds_the_output(Stream	
  $stream)	
  
{	
  
	
  	
  	
  	
  $stream-­‐>getOutput()	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>willReturn('4	
  Developers');	
  
!
	
  	
  	
  	
  $this-­‐>bold($stream)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldReturn('<b>4	
  Developers</b>’);	
  
}
function	
  it_bolds_the_output(Stream	
  $stream)	
  
{	
  
	
  	
  	
  	
  $stream-­‐>getOutput()	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>willReturn('4	
  Developers');	
  
!
	
  	
  	
  	
  $this-­‐>bold($stream)	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldReturn('<b>4	
  Developers</b>’);	
  
}
Mocks
verifies "indirect output”
of the tested code
function	
  let(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($logger);	
  
}	
  
!
function	
  it_returns_customer_by_id(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $logger-­‐>debug('DB	
  queried')	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>findById(5);	
  
}
function	
  let(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($logger);	
  
}	
  
!
function	
  it_returns_customer_by_id(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $logger-­‐>debug('DB	
  queried')	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>findById(5);	
  
}
Spy
verifies "indirect output”
by asserting the expectations
afterwards
function	
  let(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($logger);	
  
}	
  
!
function	
  it_returns_customer_by_id(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $this-­‐>findById(5);	
  
!
	
  	
  	
  	
  $logger-­‐>debug('DB	
  queried')	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldHaveBeenCalled();	
  
}
function	
  let(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($logger);	
  
}	
  
!
function	
  it_returns_customer_by_id(Logger	
  $logger)	
  
{	
  
	
  	
  	
  	
  $this-­‐>findById(5);	
  
!
	
  	
  	
  	
  $logger-­‐>debug('DB	
  queried')	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldHaveBeenCalled();	
  
}
(a bit more)
complex example
function	
  let(SecurityContext	
  $securityContext)	
  {	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($securityContext);	
  	
  
}	
  
!
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
function	
  let(SecurityContext	
  $securityContext)	
  {	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($securityContext);	
  	
  
}	
  
!
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
function	
  let(SecurityContext	
  $securityContext)	
  {	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($securityContext);	
  	
  
}	
  
!
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
function	
  let(SecurityContext	
  $securityContext)	
  {	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($securityContext);	
  	
  
}	
  
!
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
function	
  let(SecurityContext	
  $securityContext)	
  {	
  
	
  	
  	
  	
  $this-­‐>beConstructedWith($securityContext);	
  	
  
}	
  
!
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
But mocking
becomes painful…
And it smells…
Law of Demeter
unit should only
talk to its friends;
don't talk to strangers
It’s time to
refactor! :)
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  	
  
	
  	
  	
  	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
function	
  it_returns_user_from_token(	
  
	
  	
  	
  	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $this-­‐>getUser()-­‐>shouldRetun($user);	
  
}	
  
!
public	
  function	
  __construct(SecurityContext	
  $securityContext){	
  
	
  	
  	
  	
  $this-­‐>securityContext	
  =	
  $securityContext;	
  
}	
  
!
public	
  function	
  getUser()	
  
{	
  
	
  	
  	
  	
  $token	
  =	
  $this-­‐>securityContext-­‐>getToken();	
  
	
  	
  	
  	
  if	
  ($token	
  instanceof	
  TokenInterface)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  $token-­‐>getUser();	
  
	
  	
  	
  	
  }	
  
!
	
  	
  	
  	
  return	
  null;	
  
}
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  	
  
	
  	
  	
  	
  SecurityContext	
  $securityContext,	
  	
  
	
  	
  	
  	
  TokenInterface	
  $token,	
  User	
  $user)	
  	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getToken()-­‐>willReturn($token);	
  
	
  	
  	
  	
  $token-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type('Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  	
  
}
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  DomainSecurityContext	
  $securityContext,	
  

	
  	
  	
  	
  User	
  $user)	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type(‘Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  
}	
  
Composition over Inheritance
separation of concerns
small, well focused objects
composition is simpler to test
public	
  function	
  __construct(SecurityContext	
  $securityContext){	
  
	
  	
  	
  	
  $this-­‐>securityContext	
  =	
  $securityContext;	
  
}	
  
!
public	
  function	
  getUser()	
  
{	
  
	
  	
  	
  	
  $token	
  =	
  $this-­‐>securityContext-­‐>getToken();	
  
	
  	
  	
  	
  if	
  ($token	
  instanceof	
  TokenInterface)	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  return	
  $token-­‐>getUser();	
  
	
  	
  	
  	
  }	
  
!
	
  	
  	
  	
  return	
  null;	
  
}
We can still
improve
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  DomainSecurityContext	
  $securityContext,	
  

	
  	
  	
  	
  User	
  $user)	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type(‘Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  
}	
  
function	
  it_loads_user_preferences(	
  
	
  	
  	
  	
  GetResponseEvent	
  $event,	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  
	
  	
  	
  	
  DomainSecurityContextInterface	
  $securityContext,	
  

	
  	
  	
  	
  User	
  $user)	
  
{	
  
	
  	
  	
  	
  $securityContext-­‐>getUser()-­‐>willReturn($user);	
  
!
	
  	
  	
  	
  $user-­‐>setPreferences(Argument::type(‘Preferences'))	
  
	
  	
  	
  	
  	
  	
  	
  	
  	
  -­‐>shouldBeCalled();	
  
!
	
  	
  	
  	
  $this-­‐>handle($event);	
  
}	
  
Dependency
Inversion Principle
high-level modules should
not depend on low-level
modules; both should depend
on abstractions
DIP states:
DIP states:
abstractions should not
depend upon details; details
should depend upon
abstractions
Isn’t it overhead?
What are benefits of
using PHPSpec?
TDD-cycle
oriented tool
ease Mocking
focused on
Messaging
encourage
injecting right
Collaborators
and following
Demeter Low
enables
Refactoring
and gives you
Regression Safety
and it’s trendy ;)
Is PHPSpec
the only design tool
we need?
s
So it helps ;)
Kacper Gunia
Software Engineer
Symfony Certified Developer
PHPers Silesia
Thanks!

Mais conteúdo relacionado

Mais procurados

Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Leonardo Proietti
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationKirill Chebunin
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful softwareJorn Oomen
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Konstantin Kudryashov
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteLeonardo Proietti
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHPKacper Gunia
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using CodeceptionJeroen van Dijk
 
Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13Rafael Dohms
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP GeneratorsMark Baker
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix itRafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in actionJace Ju
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 

Mais procurados (20)

Mocking Demystified
Mocking DemystifiedMocking Demystified
Mocking Demystified
 
Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5Rich domain model with symfony 2.5 and doctrine 2.5
Rich domain model with symfony 2.5 and doctrine 2.5
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
 
Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015Min-Maxing Software Costs - Laracon EU 2015
Min-Maxing Software Costs - Laracon EU 2015
 
Symfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il clienteSymfony2, creare bundle e valore per il cliente
Symfony2, creare bundle e valore per il cliente
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Zero to SOLID
Zero to SOLIDZero to SOLID
Zero to SOLID
 
Dependency Injection in PHP
Dependency Injection in PHPDependency Injection in PHP
Dependency Injection in PHP
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
Refactoring using Codeception
Refactoring using CodeceptionRefactoring using Codeception
Refactoring using Codeception
 
Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13Your code sucks, let's fix it! - php|tek13
Your code sucks, let's fix it! - php|tek13
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
Electrify your code with PHP Generators
Electrify your code with PHP GeneratorsElectrify your code with PHP Generators
Electrify your code with PHP Generators
 
You code sucks, let's fix it
You code sucks, let's fix itYou code sucks, let's fix it
You code sucks, let's fix it
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
New in php 7
New in php 7New in php 7
New in php 7
 
Advanced php testing in action
Advanced php testing in actionAdvanced php testing in action
Advanced php testing in action
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 

Destaque

TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016CiaranMcNulty
 
Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Matthias Noback
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages webJean-Pierre Vincent
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsDavey Shafik
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phingRajat Pandit
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)Matthias Noback
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performanceafup Paris
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Marcello Duarte
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!tlrx
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLGabriele Bartolini
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Bruno Boucard
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)Arnauld Loyer
 
Performance serveur et apache
Performance serveur et apachePerformance serveur et apache
Performance serveur et apacheafup Paris
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsRyan Weaver
 
Password (in)security
Password (in)securityPassword (in)security
Password (in)securityEnrico Zimuel
 

Destaque (20)

TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016TDD with PhpSpec - Lone Star PHP 2016
TDD with PhpSpec - Lone Star PHP 2016
 
Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017Tactical DDD (just better OOP?) - PHPBenelux 2017
Tactical DDD (just better OOP?) - PHPBenelux 2017
 
Techniques d'accélération des pages web
Techniques d'accélération des pages webTechniques d'accélération des pages web
Techniques d'accélération des pages web
 
Diving deep into twig
Diving deep into twigDiving deep into twig
Diving deep into twig
 
Elastic Searching With PHP
Elastic Searching With PHPElastic Searching With PHP
Elastic Searching With PHP
 
Get Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP StreamsGet Soaked - An In Depth Look At PHP Streams
Get Soaked - An In Depth Look At PHP Streams
 
PHP5.5 is Here
PHP5.5 is HerePHP5.5 is Here
PHP5.5 is Here
 
Automation using-phing
Automation using-phingAutomation using-phing
Automation using-phing
 
The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)The quest for global design principles (SymfonyLive Berlin 2015)
The quest for global design principles (SymfonyLive Berlin 2015)
 
Top tips my_sql_performance
Top tips my_sql_performanceTop tips my_sql_performance
Top tips my_sql_performance
 
Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015Understanding Craftsmanship SwanseaCon2015
Understanding Craftsmanship SwanseaCon2015
 
Why elasticsearch rocks!
Why elasticsearch rocks!Why elasticsearch rocks!
Why elasticsearch rocks!
 
Writing infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQLWriting infinite scalability web applications with PHP and PostgreSQL
Writing infinite scalability web applications with PHP and PostgreSQL
 
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015Si le tdd est mort alors pratiquons une autopsie mix-it 2015
Si le tdd est mort alors pratiquons une autopsie mix-it 2015
 
L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)L'ABC du BDD (Behavior Driven Development)
L'ABC du BDD (Behavior Driven Development)
 
Behat 3.0 meetup (March)
Behat 3.0 meetup (March)Behat 3.0 meetup (March)
Behat 3.0 meetup (March)
 
Performance serveur et apache
Performance serveur et apachePerformance serveur et apache
Performance serveur et apache
 
Caching on the Edge
Caching on the EdgeCaching on the Edge
Caching on the Edge
 
The Wonderful World of Symfony Components
The Wonderful World of Symfony ComponentsThe Wonderful World of Symfony Components
The Wonderful World of Symfony Components
 
Password (in)security
Password (in)securityPassword (in)security
Password (in)security
 

Semelhante a PHPSpec - the only Design Tool you need - 4Developers

Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web servicesMichelangelo van Dam
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConRafael Dohms
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsClinton Dreisbach
 
Paying off technical debt with PHPSpec
Paying off technical debt with PHPSpecPaying off technical debt with PHPSpec
Paying off technical debt with PHPSpecLewis Wright
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Michelangelo van Dam
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11Michelangelo van Dam
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your CodeAbbas Ali
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxMichelangelo van Dam
 
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learnedMoving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learnedBaldur Rensch
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015Fernando Daciuk
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosDivante
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐいHisateru Tanaka
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011Alessandro Nadalin
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormMichelangelo van Dam
 

Semelhante a PHPSpec - the only Design Tool you need - 4Developers (20)

Introduction to Zend Framework web services
Introduction to Zend Framework web servicesIntroduction to Zend Framework web services
Introduction to Zend Framework web services
 
Your code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnConYour code sucks, let's fix it - DPC UnCon
Your code sucks, let's fix it - DPC UnCon
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Zend framework service
Zend framework serviceZend framework service
Zend framework service
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Dealing with Legacy PHP Applications
Dealing with Legacy PHP ApplicationsDealing with Legacy PHP Applications
Dealing with Legacy PHP Applications
 
Paying off technical debt with PHPSpec
Paying off technical debt with PHPSpecPaying off technical debt with PHPSpec
Paying off technical debt with PHPSpec
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Tidy Up Your Code
Tidy Up Your CodeTidy Up Your Code
Tidy Up Your Code
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learnedMoving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
Moving a high traffic ZF1 Enterprise Application to SF2 - Lessons learned
 
WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015WordPress Realtime - WordCamp São Paulo 2015
WordPress Realtime - WordCamp São Paulo 2015
 
Why is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenariosWhy is crud a bad idea - focus on real scenarios
Why is crud a bad idea - focus on real scenarios
 
関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい関西PHP勉強会 php5.4つまみぐい
関西PHP勉強会 php5.4つまみぐい
 
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011 Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
Be lazy, be ESI: HTTP caching and Symfony2 @ PHPDay 2011 05-13-2011
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStorm
 
PHPSpec BDD Framework
PHPSpec BDD FrameworkPHPSpec BDD Framework
PHPSpec BDD Framework
 

Mais de Kacper Gunia

How a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty systemHow a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty systemKacper Gunia
 
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learnedRebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learnedKacper Gunia
 
The top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doingThe top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doingKacper Gunia
 
Embrace Events and let CRUD die
Embrace Events and let CRUD dieEmbrace Events and let CRUD die
Embrace Events and let CRUD dieKacper Gunia
 
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Kacper Gunia
 
OmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ toolOmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ toolKacper Gunia
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 

Mais de Kacper Gunia (9)

How a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty systemHow a large corporation used Domain-Driven Design to replace a loyalty system
How a large corporation used Domain-Driven Design to replace a loyalty system
 
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learnedRebuilding Legacy Apps with Domain-Driven Design - Lessons learned
Rebuilding Legacy Apps with Domain-Driven Design - Lessons learned
 
The top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doingThe top 10 things that any pro PHP developer should be doing
The top 10 things that any pro PHP developer should be doing
 
Embrace Events and let CRUD die
Embrace Events and let CRUD dieEmbrace Events and let CRUD die
Embrace Events and let CRUD die
 
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
Domain-driven Design in PHP and Symfony - Drupal Camp Wroclaw!
 
OmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ toolOmniFocus - the #1 ‘Getting Things Done’ tool
OmniFocus - the #1 ‘Getting Things Done’ tool
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Code Dojo
Code DojoCode Dojo
Code Dojo
 
SpecBDD in PHP
SpecBDD in PHPSpecBDD in PHP
SpecBDD in PHP
 

Último

4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sectoritnewsafrica
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Mark Simos
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Karmanjay Verma
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...BookNet Canada
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsYoss Cohen
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesThousandEyes
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...itnewsafrica
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxAna-Maria Mihalceanu
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 

Último (20)

4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
4. Cobus Valentine- Cybersecurity Threats and Solutions for the Public Sector
 
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
Tampa BSides - The No BS SOC (slides from April 6, 2024 talk)
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#Microservices, Docker deploy and Microservices source code in C#
Microservices, Docker deploy and Microservices source code in C#
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
Transcript: New from BookNet Canada for 2024: BNC SalesData and LibraryData -...
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
Infrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platformsInfrared simulation and processing on Nvidia platforms
Infrared simulation and processing on Nvidia platforms
 
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyesAssure Ecommerce and Retail Operations Uptime with ThousandEyes
Assure Ecommerce and Retail Operations Uptime with ThousandEyes
 
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...Abdul Kader Baba- Managing Cybersecurity Risks  and Compliance Requirements i...
Abdul Kader Baba- Managing Cybersecurity Risks and Compliance Requirements i...
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
A Glance At The Java Performance Toolbox
A Glance At The Java Performance ToolboxA Glance At The Java Performance Toolbox
A Glance At The Java Performance Toolbox
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 

PHPSpec - the only Design Tool you need - 4Developers