Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AOP in Python With Decorators

Avatar for novoland novoland
September 29, 2013

AOP in Python With Decorators

Avatar for novoland

novoland

September 29, 2013
Tweet

More Decks by novoland

Other Decks in Programming

Transcript

  1. Case • BioBench: ◦ Application for biogas installations • Enter

    measurements • Normalize data • Calculate plant performance
  2. Problem description • Large code-base • A lot of calculations

    • Django web-interface • Make calculations available via an API
  3. Problem description • Is there a library/framework? • Are the

    alternatives? • What is the actual impact of the feature? • What aspects to take into account?
  4. Problem description def add(lhs, rhs): return lhs + rhs def

    api_add(request): return add(request.args['lhs'], request.args['rhs'])
  5. Problem description def add(lhs, rhs): return lhs + rhs def

    api_add(request): if request.args['token'] == valid: return add(request.args['lhs'], request.args['rhs']) raise Exception('Security error')
  6. Problem description def add(lhs, rhs): return lhs + rhs def

    api_add(request): if request.args['token'] == valid: database.query().alter usage counter return add(request.args['lhs'], request.args['rhs']) raise Exception('Security error')
  7. Problem description def add(lhs, rhs): return lhs + rhs def

    api_add(request): if request.args['token'] == valid: database.query().alter usage counter result = add(request.args['lhs'], request.args['rhs']) return '<xml>{0}</xml>'.format(result) raise Exception('Security error')
  8. Problem description def add(lhs, rhs): return lhs + rhs def

    api_add(request): if request.args['token'] == valid: database.query().alter usage counter result = add(request.args['lhs'], request.args['rhs']) return '<xml>{0}</xml>'.format(result) raise Exception('Security error')
  9. Problem description def add(lhs, rhs): return lhs + rhs def

    api_add(request): if request.args['token'] == valid: database.query().alter usage counter result = add(request.args['lhs'], request.args['rhs']) return '<xml>{0}</xml>'.format(result) raise Exception('Security error')
  10. Aspect Oriented Programming • What is AOP? • Separation of

    concerns (aspects) • Avoid scattering / tangling
  11. Aspect Oriented Programming • Aspect: ◦ Pointcuts ◦ Join points

    ◦ Advices ▪ Before advices ▪ After advices ▪ Around advices
  12. Aspect Oriented Programming • Before advice ◦ Must execute the

    function (no side-effects) def aspect(function): def advice(*args, **kwargs): do something here return function(*args, **kwargs) return advice
  13. Aspect Oriented Programming • After advice ◦ Must execute the

    function (no side-effects) def aspect(function): def advice(*args, **kwargs): result = function(*args, **kwargs) do something here return result return advice
  14. Aspect Oriented Programming • Around advice ◦ Allowed to bypass

    the function def aspect(function): def advice(*args, **kwargs): do something here result = function(*args, **kwargs) do something here return result return advice
  15. Implementation • Security aspect ◦ Around advice def secure(function): def

    advice(*args, **kwargs): if valid token in request object: return function(*args, **kwargs) raise Exception('No valid token provided') return advice
  16. Implementation • Statistics aspect ◦ Before advice def statistics(function): def

    advice(*args, **kwargs): increase API usage count for the user logged in return function(*args, **kwargs) return advice
  17. Implementation • Serialization aspect ◦ Around advice def serialize(function): def

    advice(format, *args, **kwargs): if not format in ['html', 'xml', 'json']: raise exception result = function(*args, **kwargs) make a http response of 'result' in the right format return advice
  18. Implementation • Dispatcher aspect ◦ Around advice def dispatch(function): def

    advice(*args, **kwargs): proxy the API call to a call to the core system return advice
  19. Implementation def dispatch(function): def advice(*args, **kwargs): if API call in

    proxy mapping: core_function, params = mapping[API call] kwargs.update(extract(params, request)) return function(proxy=core_function, params=params, *args, **kwargs) raise exception return advice
  20. Implementation @secure @serialize @statistics @dispatch def api_call(*args, **kwargs): proxy_function =

    kwargs['proxy'] params = kwargs['params'] return proxy_function(extract params from kwargs)
  21. Conclusion • AOP offers some brilliant concepts in software engineering

    • Separate your concerns / aspects ◦ Avoid classical scattering and tangling