blob: c2ba7b596004f8a2ff7bc1392019dcd1fc1b5fd4 [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<body>
<h1>Tutorial 6 - SideEffects</h1>
<p>
The current say() method has a Concern that modifies its value. What if we instead want
the value to be intact, but log that value to System.out? That would be considered a side-effect
of the say() method, and should hence not be done in a Concern. It would be better to implement
this in a SideEffect. SideEffects are executed after the Mixin and all Concerns for a method are done,
which means that the final result has been computed. A SideEffect can access this result value, and
then use that for further computation, but it should not change the value or throw an exception.
</p>
<p>
SideEffects can be either typed or generic, just like Concerns. In the typed case we are
interested in specifying SideEffects for one or more particular methods, whereas in the generic
case the SideEffect is not really relying on what method is being invoked. Both are useful
in different scenarios.
</p>
<p>
The easiest way to implement a typed SideEffect is to subclass the SideEffectOf class. This gives
you access to the result of the real method invocation by using the "result" field, which has the same
type as the interface of the method you want the code to be a side-effect of. Note that calling "result"
does not actually do anything, it only returns the value (or throws the exception, if one was thrown
from the original method) that has already been computed. Similarly, since the method is already done,
you can return anything from the SideEffect method. The framework will simply throw it away, and also
ignore any exceptions that you throw in your code.
</p>
<p>
To declare that the SideEffect should be used you add the @SideEffects annotation to either the
TransientComposite type, the Mixin type, or the Mixin implementation. Either works.
</p>
<p>
Steps for this tutorial:
</p>
<ol>
<li>Create the SideEffect class that logs the result of say() to System.out.</li>
<li>Add a @SideEffects annotation with the SideEffect to the HelloWorldComposite interface.</li>
<li>Remove the Concern from the previous step.</li>
<li>Move the HelloWorldStateMixin from the HelloWorldState to the HelloWorldComposite interface.</li>
</ol>
</body>