/
what-is-cop.html
262 lines (230 loc) · 20 KB
/
what-is-cop.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>What is COP?</title><link rel="stylesheet" href="css/style.css" type="text/css" /><meta name="generator" content="DocBook XSL Stylesheets V1.75.2" /><link rel="home" href="index.html" title="" /><link rel="up" href="intro.html" title="Introduction" /><link rel="prev" href="introduction-background.html" title="Background" /><link rel="next" href="qi4j-cop.html" title="COP with Java and Qi4j" />
<!-- favicon -->
<link rel="shortcut icon" href="http://qi4j.org/favicon.ico" type="image/vnd.microsoft.icon" />
<link rel="icon" href="http://qi4j.org/favicon.ico" type="image/x-icon" />
<!-- style -->
<link href="css/shCore.css" rel="stylesheet" type="text/css" />
<link href="css/shCoreEclipse.css" rel="stylesheet" type="text/css" />
<link href="css/shThemeEclipse.css" rel="stylesheet" type="text/css" />
<link href="css/qi4j.css" rel="stylesheet" type="text/css" />
<!-- Syntax Highlighter -->
<script type="text/javascript" src="js/shCore.js"></script>
<script type="text/javascript" src="js/shBrushJava.js"></script>
<script type="text/javascript" src="js/shBrushScala.js"></script>
<script type="text/javascript" src="js/shBrushJScript.js"></script>
<script type="text/javascript" src="js/shBrushBash.js"></script>
<script type="text/javascript" src="js/shBrushPlain.js"></script>
<script type="text/javascript" src="js/shBrushXml.js"></script>
<script type="text/javascript" src="js/shBrushGroovy.js"></script>
<script type="text/javascript" src="js/shBrushPython.js"></script>
<script type="text/javascript" src="js/shBrushRuby.js"></script>
<script type="text/javascript" src="js/shBrushCSharp.js"></script>
<script type="text/javascript">
SyntaxHighlighter.defaults['tab-size'] = 4;
SyntaxHighlighter.defaults['gutter'] = false;
SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.all()
</script>
<!-- JQuery -->
<script type="text/javascript" src="js/jquery-1.6.4.min.js"></script>
<!-- Image Scaler -->
<script type="text/javascript" src="js/imagescaler.js"></script>
<!-- Table Styler -->
<script type="text/javascript" src="js/tablestyler.js"></script>
<!-- Qi4j WebSite Progressive Enhancement -->
<link href="css/progressive-enhancement.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="js/jquery.scrollTo-1.4.2.js"></script>
<script type="text/javascript" src="js/progressive-enhancement.js"></script>
<!-- Analytics -->
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-3118496-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head><body><div xmlns="" xmlns:exsl="http://exslt.org/common" class="logo"><a href="index.html"><img src="images/logo-standard.png" /></a></div><div xmlns="" xmlns:exsl="http://exslt.org/common" class="top-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl><dt><span class="section"><a href="index.html#home">Qi4j</a></span></dt><dt><span class="section"><span xmlns="" href="intro.html">Introduction</span></span></dt><dt><span class="section"><a href="tutorials.html">Tutorials</a></span></dt><dt><span class="section"><a href="javadocs.html">Javadoc</a></span></dt><dt><span class="section"><a href="samples.html">Samples</a></span></dt><dt><span class="section"><a href="core.html">Core</a></span></dt><dt><span class="section"><a href="libraries.html">Libraries</a></span></dt><dt><span class="section"><a href="extensions.html">Extensions</a></span></dt><dt><span class="section"><a href="tools.html">Tools</a></span></dt><dt><span class="section"><a href="glossary.html">Glossary </a></span></dt></dl></div></div><div xmlns="" xmlns:exsl="http://exslt.org/common" class="sub-nav"><div xmlns="http://www.w3.org/1999/xhtml" class="toc"><dl><dt><span class="section"><a href="intro.html#highlights">Highligts</a></span></dt><dt><span class="section"><a href="introduction-background.html">Background</a></span></dt><dt><span class="section"><span xmlns="" href="what-is-cop.html">What is COP?</span></span></dt><dt><span class="section"><a href="qi4j-cop.html">COP with Java and Qi4j</a></span></dt><dt><span class="section"><a href="what-s-an-object-anyway.html">What’s an Object anyway?</a></span></dt><dt><span class="section"><a href="state-modeling.html">Qi4j and state modeling</a></span></dt><dt><span class="section"><a href="related.html">Related publications & projects</a></span></dt></dl></div></div><div class="section" title="What is COP?"><div class="titlepage"><div><div><h3 class="title"><a id="what-is-cop"></a>What is COP?</h3></div></div></div><p>We found this very well written blog entry on the Internet, which very well describes what Composite Oriented
Programming really is.</p><p>The article uses C# and a "show by example" approach to explaining COP, and this shows clearly that COP is not
Java specific, and although Qi4j was (to our knowledge) first to introduce the name, it applies across languages and
potentially deserves one or more languages on its own.</p><p>The article is re-published here, as allowed by the
<a class="ulink" href="http://msdn.microsoft.com/en-us/windowsmobile/bb264332.aspx" target="_top">Microsoft Permissive License</a>
, more recently known as
<a class="ulink" href="http://www.opensource.org/licenses/MS-PL" target="_top">Microsoft Public License</a>. The content below
is NOT under the usual <a class="ulink" href="http://www.opensource.org/licenses/Apache-2.0" target="_top">Apache License</a>.</p><p>We would like to thank Fredrik Kalseth for his explicit approval as well.</p><div class="section" title="Composite Oriented Programming"><div class="titlepage"><div><div><h4 class="title"><a id="_ulink_url_http_iridescence_no_post_composite_oriented_programming_aspx_composite_oriented_programming_ulink"></a><a class="ulink" href="http://iridescence.no/post/composite-oriented-programming.aspx" target="_top">Composite Oriented Programming</a></h4></div></div></div><p>I’ve written a series of post on AOP lately (here, here and here), and in the last part I promised to tackle mixins
and introductions in a future post. When I was doing my research for just that, I came cross a Java framework (just
humor me :p) called Qi4j (that’s <span class="emphasis"><em>chee for jay</em></span>), written by Swedish Richard Öberg, pioneering the idea of Composite
Oriented Programming, which instantly put a spell on me. Essentially, it takes the concepts from Aspect Oriented
Programming to the extreme, and for the past week I’ve dug into it with a passion. This post is the first fruits of
my labor.</p><div class="section" title="OOP is Not Object Oriented!"><div class="titlepage"><div><div><h5 class="title"><a id="_oop_is_not_object_oriented"></a>OOP is Not Object Oriented!</h5></div></div></div><p>One of the things that Richard Öberg argues, is that OOP is not really object oriented at all, but rather class
oriented. As the Qi4j website proclaims, "class is the first class citizen that objects are derived from. Not objects
being the first-class citizen to which one or many classes are assigned". Composite oriented programming (COP) then,
tries to work around this limitation by building on a set of core principles; that behavior depends on context, that
decoupling is a virtue, and that business rules matter more. For a short and abstract explanation of COP,
<a class="link" href="introduction-background.html" title="Background">see this page</a>. In the rest of this post I’ll try and explain some of its easily graspable
benefits through a set of code examples, and then in a future post we’ll look at how I’ve morphed the AOP framework
I started developing in the previous posts in this series into a lightweight COP framework that can actually make
it compile and run.</p></div><div class="section" title="Lead by Example"><div class="titlepage"><div><div><h5 class="title"><a id="_lead_by_example"></a>Lead by Example</h5></div></div></div><p><span class="emphasis"><em>Lets pause for a short aside: obviously the examples presented here are going to be architectured beyond any rational
sense, but the interesting part lies in seeing the bigger picture; imagine the principles presented here applied on a
much larger scale and I’m sure you can see the benefits quite clearly when we reach the end.</em></span></p><p>Imagine that we have a class Division, which knows how to divide one number by another:</p><pre class="programlisting brush: c#">public class Division
{
public Int64 Dividend { get; set; }
private long _divisor = 1;
public Int64 Divisor
{
get { return _divisor; }
set
{
if(value == 0)
{
throw new ArgumentException("Cannot set the divisor to 0; division by 0 is not allowed.");
}
_divisor = value;
}
}
public Int64 Calculate()
{
Trace.WriteLine("Calculating the division of " + this.Dividend + " by " + this.Divisor);
Int64 result = this.Dividend/this.Divisor;
Trace.WriteLine("Returning result: " + result);
return result;
}
}</pre><p>Consider the code presented above. Do you like it? If you’ve followed the discussion on AOP in the previous posts,
then you should immediately be able to identify that there are several aspects tangled together in the above class.
We’ve got data storage (the Dividend and Divisor properties), data validation (the argument check on the Divisor
setter), business logic (the actual calculation in the Calculate method) and diagnostics (the Trace calls), all
intertwined. To what extent is this class reusable if I wanted to implement addition, subtraction or multiplication
calculations? Not very, at least not unless we refactored it. We could make the Calculate method and the properties
virtual, and thus use inheritance to modify the logic of the calculation - and since this is a tiny example, it would
probably look OK. But again, think bigger - how would this apply to a huge API? It would easily become quite difficult
to manage as things got more and more complex.</p></div><div class="section" title="Design by Composition"><div class="titlepage"><div><div><h5 class="title"><a id="_design_by_composition"></a>Design by Composition</h5></div></div></div><p>With a COP framework, we can implement each aspect as a separate object and then treat them as <span class="emphasis"><em>mixins</em></span> which blend
together into a meaningful <span class="emphasis"><em>composite</em></span>. Sounds confusing? Lets refactor the above example using an as of yet imaginary
COP framework for .NET (which I’m currently developing and will post the source code for in a follow-up post), and
it’ll all make sense (hopefully!).</p><p>Above, we identified the four different aspects in the Division class - so let’s implement each of them. First, we
have the data storage:</p><pre class="programlisting brush: c#">public interface ICalculationDataAspect // aspect contract
{
long Number1 { get; set; }
long Number2 { get; set; }
}
public class CalculationDataAspect : ICalculationDataAspect // aspect implementation
{
public long Number1 { get; set; }
public long Number2 { get; set; }
}</pre><p>In this example, the data storage is super easy – we just provide a set of properties (using the C# 3.0 automatic
properties notation) that can hold the values in-memory. The second aspect we found, was the business logic – the
actual calculation:</p><pre class="programlisting brush: c#">public interface ICalculationLogicAspect
{
long Calculate();
}
public class DivisionLogicAspect : ICalculationLogicAspect
{
[AspectRef] ICalculationDataAspect _data;
public long Calculate()
{
return _data.Number1 / _data.Number2;
}
}</pre><p>Here we follow the same structure again, by defining the aspect as an interface and providing an implementation of it.
In order to perform the calculation however, we need access to the data storage aspect so that we can read out the
numbers we should perform the calculation on. Using attributes, we can tell the COP framework that we require this
reference, and it will provide it for us at runtime using some dependency injection trickery behind the scenes. It is
important to notice that we’ve now placed a <span class="emphasis"><em>constraint</em></span> on any possible composition of these aspects – the
DivisionLogicAspect now requires an ICalculationDataAspect to be present in any composition it is part of (our COP
framework will be able to validate such constraints, and tell us up front should we break any). It is still loosely
coupled however, because we only hold a constraint on the <span class="emphasis"><em>contract</em></span> of that aspect, not any specific implementation of
it. We’ll see the benefit of that distinction later.</p><p>The third aspect we have, is validation. We want to ensure that the divisor is never set to 0, because trying to divide
by zero is not a pleasant experience. Validation is a type of advice, which was introduced at length earlier in my AOP
series. We’ve seen it implemented using the IAdvice interface of my AOP framework, allowing us to dynamically hook up
to a method invocation. However, the advice we’re implementing here is specific to the data aspect, so with our COP
framework we can define it as <span class="emphasis"><em>concern</em></span> for that particular aspect, which gives us a much nicer implementation than an
AOP framework could - in particular because of its type safety. Just look at this:</p><pre class="programlisting brush: c#">public abstract class DivisionValidationConcern : ICalculationDataAspect
{
[ConcernFor] protected ICalculationDataAspect _proceed;
public abstract long Number1 { get; set; }
public long Number2
{
get { return _proceed.Number2; }
set
{
if (value == 0)
{
throw new ArgumentException("Cannot set the Divisor to 0 - division by zero not allowed.");
}
_proceed.Number2 = value; // here, we tell the framework to proceed with the call to the *real* Number2 property
}
}
}</pre><p>I just love that, it’s so friggin' elegant ;). Remember that an advice is allowed to control the actual method
invocation by telling the target when to proceed – we’re doing the exact same thing above, only instead of dealing with
a generic method invocation we’re actually using the interface of the aspect we’re advising to control the specific
invocation directly. In our validation, we validate the value passed into the Divisor setter, and if we find it valid
then we tell the target (represented by a field annotated with an attribute which tells the COP framework to inject the
reference into it for us, much like we did with aspects earlier) to proceed with the invocation; otherwise we throw an
exception. This particular concern is abstract, because we only wanted to advise a subset of the methods in the
interface. That’s merely a convenience offered us by the framework - under the covers it will automatically complete
our implementation of the members we left abstract.</p><p>Only one aspect remains now, and that is the logging:</p><pre class="programlisting brush: c#">public class LoggingAdvice : IAdvice
{
public object Execute(AdviceTarget target)
{
Trace.WriteLine("Invoking method " + target.TargetInfo.Name + " on " + target.TargetInfo.DeclaringType.FullName);
object retValue;
try
{
retValue = target.Proceed();
}
catch(Exception ex)
{
Trace.WriteLine("Method threw exception: " + ex.Message);
throw;
}
Trace.WriteLine("Method returned " + retValue);
return retValue;
}
}</pre><p>We’ve implement it as a regular advice, like we’ve seen earlier in AOP, because it lends itself to much wider reuse
than the validation concern did.</p><p>Having defined all our aspects separately, it is now time to put them back together again into something that can
actually do something. We call this the composite, and it is defined as follows:</p><pre class="programlisting brush: c#">[Mixin(typeof(ICalculationDataAspect), typeof(CalculationDataAspect))]
[Mixin(typeof(ICalculationLogicAspect), typeof(DivisionLogicAspect))]
[Concern(typeof(DivisionValidationConcern))]
[Concern(typeof(LoggingAdvice))]
public interface IDivision : ICalculationDataAspect, ICalculationLogicAspect
{ }</pre><p>Basically, we’ve just defined the implementation of an interface IDivision as a composition of the data and logic
aspects, and sprinkled it with the two concerns (the validation concern and the logging advice). We can now use it to
perform divisions:</p><pre class="programlisting brush: c#">IDivision division = Composer.Compose<IDivision>().Instantiate();
division.Number1 = 10;
division.Number2 = 2;
Int64 sum = division.Calculate();</pre><p>That’s pretty cool, no? Take a moment to just think about what doors this opens. To what extent do you think our code
is reusable <span class="emphasis"><em>now</em></span>, if we wanted to implement addition, subtraction and so forth? That’s right – all we’d need to do is
substitute the implementation of the calculation aspect with one that performs the required calculation instead of
division, and we’re done. Let’s do subtraction, for example:</p><pre class="programlisting brush: c#">public class SubtractionLogicAspect : ICalculationLogicAspect
{
[AspectRef] ICalculationDataAspect _data;
public long Calculate()
{
return _data.Number1 - _data.Number2;
}
}</pre><p>That’s it! The rest we can reuse as is, building a new composite:</p><pre class="programlisting brush: c#">[Mixin(typeof(ICalculationDataAspect), typeof(CalculationDataAspect))]
[Mixin(typeof(ICalculationLogicAspect), typeof(SubtractionLogicAspect))]
[Pointcut(typeof(LoggingAdvice))]
public interface ISubtraction : ICalculationDataAspect, ICalculationLogicAspect
{ }</pre><p>Notice that we just left out the validation concern in this composite, as it is no longer needed. What if we wanted
our subtraction to only ever return positive numbers? Easy! We’ll just implement an absolute number concern:</p><pre class="programlisting brush: c#">public class AbsoluteNumberConcern : ICalculationLogicAspect
{
[ConcernFor] protected ICalculationLogicAspect _proceed;
public long Calculate()
{
long result = _proceed.Calculate();
return Math.Abs(result);
}
}</pre><p>And then update the composition to include it:</p><pre class="programlisting brush: c#">[Mixin(typeof(ICalculationDataAspect), typeof(CalculationDataAspect))]
[Mixin(typeof(ICalculationLogicAspect), typeof(SubtractionLogicAspect))]
[Concern(typeof(AbsoluteNumberConcern))]
[Pointcut(typeof(LoggingAdvice))]
public interface ISubtraction : ICalculationDataAspect, ICalculationLogicAspect
{ }</pre><p>To Be Continued…</p><p>I hope this post has whet your appetite for more on this subject, as I will certainly pursue it further in future
posts. I’ve already implemented a prototype framework that supports the above examples, which builds on my
<a class="ulink" href="http://www.iridescence.no/Posts/Implementing-an-AOP-Framework-Part-2.aspx" target="_top">previously posted AOP framework</a>, and I’ll
post the source code for that soon. If you want to dig deeper right now (and don’t mind
a bit of Java), then I suggest you head over to the Qi4j website and poke about there.
<a class="ulink" href="http://rickardoberg.wordpress.com/" target="_top">Richard Öbergs blog</a> also provides great insight.</p></div></div></div><div xmlns="" xmlns:exsl="http://exslt.org/common" class="footer">(c) 2012 The Qi4j Community</div></body></html>