Newsgroups: comp.lang.python, comp.lang.ruby, comp.lang.java
From: hungjun...@yahoo.com (Hung Jung Lu)
Date: 5 Nov 2003 21:19:38 -0800
Local: Thurs, Nov 6 2003 12:19 am
Subject: Pure Aspect-Oriented Program: an example
Hi,
I have been looking into AOP (Aspect-Oriented Programming) for AOP is not just buzzword. It's not just callback, it's not just Ruby's Here it is, and let's get some feedback. thanks, Hung Jung -------------------- Suppose you have to implement a checking account that allows class Account { } A program that withdraws money may look like: account = new Account() In order to simplify the discussion, in the following I will omit all After you have implemented the program, your bank manager comes and class Account { } Now, stop thinking in OOP. Let us try to think in AOP. //--------------------------------------------------- } //--------------------------------------------------- aspect AccountStatus { bool enabled codeblock check_status { if not this.enabled: raise AccountDisabledException } method withdraw(...) { this.check_status this.withdraw.code } } //--------------------------------------------------- endow Account with AccountStatus The general idea is to have the concerns implemented outside the Let us proceed to the next step. Say, there is a maximum daily //--------------------------------------------------- } //--------------------------------------------------- aspect AccountStatus { bool enabled codeblock check_status { if not this.enabled: raise AccountDisabledException } method withdraw(...) { this.check_status this.withdraw.code } } //--------------------------------------------------- aspect WithdrawalLimit { real daily_limit real withdrawn_today codeblock check_and_update_withdraw { new_withdrawn_today = this.withdrawn_today + amount if new_withdrawn_today > this.daily_limit: raise WithdrawalLimitExceededException &inner_code this.withdrawn_today = new_withdrawn_today } method withdraw(...) { this.check_and_update_withdraw { ... &inner_code = this.withdraw.code ... } } } //--------------------------------------------------- endow Account with AccountStatus endow Account with WithdrawalLimit Notice the usage of a hook (also known as pointcut): &inner_code. In The above way of programming of course takes longer to write. But, the endow Account with AccountStatus The same is true if one day we want to eliminate the account status //endow Account with AccountStatus Also, once the concerns are separated, it is easier to modify the A careful reader would point out that we may want to check the account //--------------------------------------------------- } //--------------------------------------------------- endow Account with AccountAspects At this point you may say: "Hey! We started with a non-trivial class
//--------------------------------------------------- } //--------------------------------------------------- aspect BalanceKeeping { real balance method withdraw(amount) { this.balance = this.balance amount } } //--------------------------------------------------- aspect AccountStatus { bool enabled codeblock check_status { if not this.enabled: raise AccountDisabledException } method withdraw(...) { // this meta-method is overriden later this.check_status this.withdraw.code } } //--------------------------------------------------- aspect WithdrawalLimit { real daily_limit real withdrawn_today codeblock check_and_update_withdraw { new_withdrawn_today = this.withdrawn_today + amount if new_withdrawn_today > this.daily_limit: raise WithdrawalLimitExceededException &inner_code this.withdrawn_today = new_withdrawn_today } method withdraw(...) { // this meta-method is overriden later check_and_update_withdraw { ... &inner_code = this.withdraw.code ... } } } //--------------------------------------------------- aspect AccountAspects: inherits BalanceKeeping, AccountStatus, WithdrawalLimit { method withdraw(...) { check_status check_and_update_withdraw { // this meta-method overrides ... &inner_code = this.withdraw.code ... } } } //--------------------------------------------------- endow Account with AccountAspects print Account.codeString() Notice that we have started with a bare class with no attributes. All class Account { } A good IDE/compiler/debugger can provide additional information on where each code line or code block comes from, hence making debugging and editing a snap. But we don't need to get into that discussion, now. What have we learned? We have learned that: 1. We can write a purely-AOP program. Codeblock-based AOP actually is more suitable in programming languages class C { } aspect A { method f_before_A = f method f(...) { print 'begin around-advice' result = this.f_before_A() print 'end around-advice' return result } } endow C with A c = new C() print c.f() //------ output One thing I have not mentioned is pattern matching for method names. aspect A { } aspect B { method <f>(...) for f matching 'f*' { } } Another thing that I have not mentioned is that aspects can be endowed to different classes. For instance, if later we have checking accounts and savings accounts, we can apply the same aspect to both classes. That's what other people refer to as "cross-cutting". ... That's all for now. You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
| ||||||||||||||