Dealing with not so exceptional exceptions

55
Dealing with not so exceptional exceptions

Transcript of Dealing with not so exceptional exceptions

Page 1: Dealing with not so exceptional exceptions

Dealing with not so exceptional exceptions

Page 2: Dealing with not so exceptional exceptions

Use case● Newsletter registration service talking to a partner

● Have to block process when failing in some cases

● We don’t really care if it failed in some other cases

● Partner throws an exception when we don’t have enough funds to register a new

email

Page 3: Dealing with not so exceptional exceptions

function exception_handler($exception) {

$logger->critical($exception);

}

set_exception_handler('exception_handler');

Page 4: Dealing with not so exceptional exceptions

function exception_handler($exception) {

$logger->critical($exception);

}

set_exception_handler('exception_handler');

Page 5: Dealing with not so exceptional exceptions

��

Page 6: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 08:11:17] app.CRITICAL: Something really bad occurred {} []

Page 7: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 08:11:17] app.CRITICAL: Something really bad occurred {} []

Page 8: Dealing with not so exceptional exceptions

��

Page 9: Dealing with not so exceptional exceptions

Page 10: Dealing with not so exceptional exceptions

$logger->critical($exception);

Application -> logs

Page 11: Dealing with not so exceptional exceptions

// class NewsletterService

public function register($email) {

// throw an Exception ?

}

Page 12: Dealing with not so exceptional exceptions

// class MemberService

public function register($email, $password) {

// …

$this->newsletterService->register($email);

}

Page 13: Dealing with not so exceptional exceptions

��

Page 14: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 11:12:36] app.CRITICAL: Not enough funds {} []

Page 15: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 11:12:36] app.CRITICAL: Not enough funds {} []

Page 16: Dealing with not so exceptional exceptions

��

Page 17: Dealing with not so exceptional exceptions

Page 18: Dealing with not so exceptional exceptions

��

Page 19: Dealing with not so exceptional exceptions

// class MemberService

public function register($email, $password) {

// …

try {

$this->newsletterService->register($email);

}

catch(\Exception $exception)

{}

}

Page 20: Dealing with not so exceptional exceptions

��

Page 21: Dealing with not so exceptional exceptions

// app.log

Page 22: Dealing with not so exceptional exceptions

��

Page 23: Dealing with not so exceptional exceptions

��

Page 24: Dealing with not so exceptional exceptions

// MemberService::register

try {

$this->newsletterService->register($email);

}

catch(\Exception $exception)

{

$this->logger->critical($exception);

}

Page 25: Dealing with not so exceptional exceptions

��

Page 26: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 03:35:17] app.CRITICAL: Not enough funds {} []

Page 27: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 03:35:17] app.CRITICAL: Not enough funds {} []

Page 28: Dealing with not so exceptional exceptions

Page 29: Dealing with not so exceptional exceptions

��

Page 30: Dealing with not so exceptional exceptions

Page 31: Dealing with not so exceptional exceptions

��

Page 32: Dealing with not so exceptional exceptions

// class NewsletterService

/**

* @throw CouldNotRegisterToNewsletterException

*/

public function register($email) {

// throw an Exception ?

}

Page 33: Dealing with not so exceptional exceptions

// NewsletterService::register

try { // … }

catch(AKnownException $exception) {

throw new CouldNotRegisterToNewsletterException(

sprintf(‘Could not register %s to newsletter’, $email),

0,

$exception);

}

}

Page 34: Dealing with not so exceptional exceptions

// NewsletterService::register

try { // … }

catch(AKnownException $exception) {

throw new CouldNotRegisterToNewsletterException(

sprintf(‘Could not register %s to newsletter’, $email),

0,

$exception);

}

}

Page 35: Dealing with not so exceptional exceptions

// NewsletterService::register

try { // … }

catch(AKnownException $exception) {

throw new CouldNotRegisterToNewsletterException(

sprintf(‘Could not register %s to newsletter’, $email),

0,

$exception);

}

}

Page 36: Dealing with not so exceptional exceptions

// NewsletterService::register

try { // … }

catch(AKnownException $exception) {

throw new CouldNotRegisterToNewsletterException(

sprintf(‘Could not register %s to newsletter’, $email),

0,

$exception);

}

}

Page 37: Dealing with not so exceptional exceptions

// MemberService::register

try {

$this->newsletterService->register($email);

}

catch(CouldNotRegisterToNewsletterException $exception)

{

$this->logger->warning($exception);

}

Page 38: Dealing with not so exceptional exceptions

��

Page 39: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 03:35:17] app.WARNING: Not enough funds {} []

Page 40: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 03:35:17] app.WARNING: Not enough funds {} []

Page 41: Dealing with not so exceptional exceptions

Page 42: Dealing with not so exceptional exceptions

throw new CouldNotRegisterToNewsletterException(

...,

...,

$exception);

Context -> Context

Page 43: Dealing with not so exceptional exceptions

Drawback● Repeat try/catch block each time a fail safe registration is needed

Page 44: Dealing with not so exceptional exceptions

Tell, don’t ask

Page 45: Dealing with not so exceptional exceptions

// class NewsletterService

/**

* @throw CouldNotRegisterToNewsletterException

*/

public function register($email) {

// throw an Exception ?

}

Page 46: Dealing with not so exceptional exceptions

// class NewsletterService

public function registerFailSafe($email) {

try {

$this->register($email);

}

catch(AKnownException $exception) {

$this->logger->warning($exception);

}

}

Page 47: Dealing with not so exceptional exceptions

// class MemberService

public function register($email, $password) {

// …

$this->newsletterService->registerFailSafe($email);

}

Page 48: Dealing with not so exceptional exceptions

Page 49: Dealing with not so exceptional exceptions

��

Page 50: Dealing with not so exceptional exceptions

��

Page 51: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 22:35:17] app.WARNING: Not enough funds {} []

Page 52: Dealing with not so exceptional exceptions

// app.log

[2017-07-19 22:35:17] app.WARNING: Not enough funds {} []

Page 53: Dealing with not so exceptional exceptions

��

Page 54: Dealing with not so exceptional exceptions

Drawback● Trust the implementer of NewsletterService to log properly

● No log showing easily that registration to newsletter failed

Page 55: Dealing with not so exceptional exceptions

Takeaways● Catching an exception is a translation mechanism

● You (probably) mustn’t catch \Exception

● Never hide an error in the system

● Think about the log level and what it means