How to properly structure functions? - actionscript-3

let's say we have a class with some methods in it, of which at least one is of rather complex nature:
class Example {
public function Example()
{
}
private function complexFunction():void
{
//Do this
//And do that
//And of course do that
//and do not forget that
}
private function otherImportantFunction():void
{
//Do something
}
//[...]
}
Now "complexFunction()" has grown pretty long and also a little complicated. So a nice thing to do to increase readability would be to split up "complexFunction()" in smaller sub-functions. I usually do it like this:
class Example {
public function Example()
{
}
private function complexFunction():void
{
doThis();
doThat();
andOfCourseDoThat();
andDoNotForgetThat();
}
private function doThis():void
{
//Do This
}
private function doThat():void
{
//Do That
}
private function andOfCourseDoThat():void
{
//And of course do that
}
private function andDoNotForgetThat():void
{
//And do not forget that
}
private function otherImportantFunction():void
{
//Do something
}
//[...]
}
But by now the class is already drowning in minor functions whose sole purpose is to get called once inside "complexFunction()". Do this "splitting-up" a little more often and it becomes hard to spot the important methods between all those helper-functions.
At least this is what happens to me all the time and clarity really suffers for it. That makes me wonder if you know a way to solve that dilemma? Surely there is way or 'best practice' to handle this?
I'm dreaming of a way to group functions together, or to subordinate the minor ones to the superior ones, without creating a whole new class for that purpose. Or is that how it's done?

You are right to split up the one large function into multiple functions. Provided it isn't something like AddOne() instead of value++. Especially functions you'll probably repeat more often can be of use.
When your class is getting filled with multiple functions (or long functions), it might be a good idea to reconsider what your class does. Try to keep your class destined for one subject. For example, a good idea for a class is to make it User-related. Things like creating or removing users can be done in there. Even matching users to, for example, cars they own can be done in there. But don't include functions in the User-class which save or remove Cars. Save that for a different class.
In that case, your Example-class would have instances of the User-class and the Car-class. If it looks like this, you're programming efficiently:
class Example {
function Example()
{
}
function complexFunction():void
{
Car newCar = new Car("KK-E8", Color.Red, true);
carManager.Add(newCar);
User newUser = new User("Moritz", "Krohn", Country.Germany, true);
userManager.Add(newUser);
newUser.addCar(newCar);
...
}
It happens that some classes tend to get large, even when you try to keep things organised. That is never a bad thing, neither are long functions. Just try to keep things seperated, try not to repeat code too much (create functions for that) and try to keep things related to eachother in seperate classes.

I personally find that it increases readability of complex code a lot if it is split into simple functions.
What I don't really get in the code presented is the way those simpler functions are combined into one function, this seems only to work for functions that don't return anything at all (they just seem to have some effects). A more natural way imho to build up a complex function from simpler ones, would be by way of function composition, case distinction or something alike...

Just because a function is "long" does not make it more complex, Some things just take many lines of code.
Take for example:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
loader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
loader.contentLoaderInfo.addEventListener(Event.OPEN, openHandler);
loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progressHandler);
loader.contentLoaderInfo.addEventListener(Event.UNLOAD, unLoadHandler);
loader.contentLoaderInfo.addEventListener(MouseEvent.CLICK, clickHandler);
var request:URLRequest = new URLRequest(url);
loader.load(request);
Is it "long"? yes
Does it have a high Cyclomatic Complexity? no
You can plainly understand what is going on here and it very easy to follow.
And you will find functions/methods with low CC values will always be easier to read.
On the other hand methods with high(+20) CC value should be putting up a red flag.
Splitting a method into separate helper methods does not remove the issue at hand and is actually making things worse for the compiler since now it has to allocate resource devoted to those methods that will only ever be called once.
The rule of thumb is to avoid going above a CC value of 20.
When you get above 20 it is time to start rethinking your class design as it is becoming tightly coupled.
Perhaps the question you should be asking is .
How can I reduce the Cyclomatic Complexity of this?

Related

Checking a Boolean variable in another class

Let me set the stage because it's too much code to post everything:
I have a Main.as that is setting up my SoundController.as so I can trigger sounds from any other class (SoundController.as has all the functions needed to call all my sounds as needed)
I have a ControlPanel.as that can access these sounds by using docRef.soundControl.laserFire or whatever other function name I want, and in this case the laserFire sound would trigger once.
So here is my question. I want to let this laser sound effect finish playing before you can fire another laser. So in SoundController.as I've set up the following pieces of code:
private var _laserPlaying:Boolean = false;
internal function laserFire():void {
_sfxChannel = _laser.play(25);
_laserPlaying=true;
_sfxChannel.addEventListener(Event.SOUND_COMPLETE, laserFinished);
}
internal function laserFinished(event:Event):void {
_sfxChannel.removeEventListener(Event.SOUND_COMPLETE, laserFinished);
_laserPlaying=false;
}
public function get laserPlaying():Boolean {
return _laserPlaying;
}
public function set laserPlaying(value:Boolean):void {
_laserPlaying = value;
}
Now in my ControlPanel class in the enterFrameHandler function I want to do an
if (docRef.soundControl.laserPlaying()==false)
or something to that effect so I can check when the sound is done and allow the player to once again press the trigger to fire the laser. So far any variant I've tried on this either gives me an error (in this case 1195; Attempted access of inaccessible method laserPlaying through a reference with static type SoundController) or it actually compiles but after firing the first laser shot it never allows the trigger to be pressed again. So I'm obviously doing something wrong and am hoping someone can help.
Let me just state that the laser sound is playing just fine that first time, so don't worry about all the code I'm not bothering to show to make that portion of the code work. However, if more info is needed to understand how I'm making anything work just let me know. And Thanks in advance!
If your soundController AND ControlPanel are instantiated in Main:
handle the firing event, in ControlPanel, like this:
if(MovieClip(parent).soundController.soundChannel.position==0)
{
MovieClip(parent).soundController.laserfire();
}else{do nothing;}
Of course use proper instance names.
If this doesn't work you'll have to make your code a little easier to understand.
Sorry for wasting everyone's time. I ended up figuring out what I needed to do to make this work. This probably won't be of much use to anyone else since my setup was probably unique to my layout and not something that anyone else will try, but here is what I did anyway.
In my ControlPanel.as I added the following code:
private var _soundController:SoundController;
And then I have a function that waits for the ControlPanel to be added to the stage and once that occurs I fired:
_soundController = new SoundController(docRef);
Now by adding those I was able to simply call:
if(!_soundController.laserPlaying) { do stuff; }
It now seems to wait for laserPlaying to be false and then moves on as intended.

Check the existence of an object instance

I'm surprised I don't know how to do this, but as it turns out I really don't; simply put, I'm trying to make a side-scrolling shooter game, a basic one and in it, I have 50 stars spawned on-screen through a "for" loop upon the game starting. There is a function which does this and a listener is at the beginning. Problem is, when you lose the game and go back to main menu, 50 more stars would be spawned, which isn't what I want. So, I'm trying to make an "if" statement check at the beginning, so that the game checks whether there is an instance/movie clip of the star object/symbol before determining whether the function that spawns stars should be called out with a listener. So, how do I do this? I looked through some other checks and they didn't help as the codes presented were vastly different there and so I'm just getting errors.
Let me know if a better explanation is needed or if you would like to see some of the code. Note that the game overall already has a lot of code, so just giving all of it would probably not be helpful.
I suggest you rethink your approach. You're focusing on whether stars have been instantiated. That's ok but not the most basic way to think about it.
I would do this instead
private function setup():void{
loadLevel(1);
addListeners();
loadMusic();
// etc...
// call all functions that are needed to just get the app up and running
}
private function loadLevel(lev:int):void{
addStars();
// call all functions that are needed each time a new level is loaded
}
private function restartLevel():void{
// logic for restarting level,
// but this *won't* include adding star
// because they are already added
}
There are other ways to do this but this makes more sense to me than your approach. I always break my game functions into smaller bits of logic so they can be reused more easily. Your main workhorse functions should (IMHO) primarily (if not exclusively) just call other functions. Then those functions do the work. By doing it this way, you can make a function like resetLevel by assembling all the smaller functions that apply, while excluding the part about adding stars.
Here's what I did to solve my problem... Here's what I had before:
function startGame():void
{
starsSpawn();
//other code here
}
This is what I changed it to:
starsSpawn();
function startGame():void
{
//other code here
}
when you said existance, so there is a container, i named this container, (which contain stars , and stars was added to it) as starsRoot, which absolutely is a DisplayObject (right?)
now, to checking whole childrens of a DisplayObject, we have to do this :
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
}
then, how to check if that child is really star!?
as you said
whether there is an instance/movie clip of the star
so your stars's type is MovieClip, and they don't have any identifier (name), so how to find them and make them clear from other existing movieclips. my suggestion :
define a Linkage name for stars from library, thats a Class name and should be started with a capital letter, for example Stars
now, back to the code, this time we can check if child is an instance of Stars
for (var i:int=0; i<starsRoot.numChildren; i++) {
var child = starsRoot.getChildAt[i];
if (child is Stars) {
// test passed, star exist
break;
}
}

How can i get a function to use any movie clip?

I'm a little lost in understanding this kind of function, i get the feeling this has been asked a thousand times but cannot find an explanation of what the code is doing.
Basically i just want a movie clip with instance name box to do something, then reuse the function for other movie clips afterwards
a little like this, but working.
Many Thanks
//my function to be used on "instance name" box
myfunc (box);
function myfunc ();
{
while (this is happening);
{
//in this case box.x = goes where ever i put it
.x = goes here
.y = goes here
}
}
Sorry it's not quite English, my communication skills are terrible
Sure you can do that. You give the function a parameter, then refer to a parameter to change its properties. With such a simple movement function it could accept a DisplayObject - a distant superclass of a MovieClip and thus a superclass to many other possible classes of those objects that can be displayed by Flash.
function myfunc(param:DisplayObject):void {
// no semicolon after declaring the function!
while (somethingIsHappening(param)) {
// why not call a query on that object?
param.x+=1; // move right by 1 pixel
}
}
You might want to look at this manual on ActionScript 3 syntax, and the following pages on variables, functions and classes, to learn more.

Assign super to variable in AS3

I have this:
public class Base {
public function whoAmI() {
trace("base");
}
}
public class Extended extends Base {
public function Extended() {
this.whoAmI() //prints extended
super.whoAmI() //prints base
var test = super;
test.whoAmI() //prints extended
}
public override function whoAmI() {
trace("extended");
}
}
The problem is when I do var test = super, it seems like this is assigned to test instead of super.
Is it possible to do the assignment so that test.whoAmI() prints "base"?
Edit: In the comments it is being said that using super in the way I propose would break overriding. I don't think that's the case. The way I am thinking of it, super could be used the same way as this. I understand that is not the way super is implemented, but using it that way would not break overriding as people are claiming. So for example the same way this is possible:
var test = this;
test.whoAmI();
This should be possible:
var test = super;
super.whoAmI();
It is obviously the choice of the language implementer to not do things this way, and I don't understand the reason why. It doesn't break things, but I guess it does make them more complicated.
I am not suggesting type-casting this to the super class. Obviously that wouldn't work.
You are thinking of "this" and "super" as 2 different instances, 2 different things but they in fact point to the same object (obviously) so at the end it's always "this". Using super is just a special keyword that allows the instance to point to the overrided definitions up the inheritance chain, it does not point to a different object. So "super" does correctly its job, it points to the instance and allow you each time you use it to access overrided definitions and that's it. There's of course no point on trying to store that keyword in a variable since in that case it just return correctly the instance it points to which is always "this".
It's simply a case of misunderstood inheritance principle and I've seen it before, super is mistaken for some kind of instance wrapper up the inheriatnce chain around the object "this" while it's in fact and always the same object.
No, this is not possible.
If this were possible, then overriding methods wouldn't be possible!
For example, take this function...
public function test(a:Object):void {
trace(a.toString());
}
You'd only get [object Object] back if your idea was how things worked.
Ok I understand what you mean your question is more about language definition and specification.
Look at this exemple in c# that explain how you can manage more precisely overriding in c# :
http://www.dotnet-tricks.com/Tutorial/csharp/U33Y020413-Understanding-virtual,-override-and-new-keyword-in-C
But
let's explain a litlle how it's work.
when you extend a class, it's like if you create an object composed of all the object in the inheritance tree so if B extends A and C extends B you have two objects like this:
(B+A) and (C+B+A) with hierarchy between each other B->A and C->B->A. Super is just a way to ascend in the hierachy.
When you cast a C in A for example. In memory you always have an object (C+B+A) but interpreted as A. When you override you just say that a method in child has an higher priority than in parent.
You can try downcasting this manually to any of your class's predecessors. The pointer will still be equal to this but the methods called will use the class table of the class used to downcast.
public class Extended extends Base {
public function Extended() {
this.whoAmI() //prints extended
super.whoAmI() //prints base
var test:Base = this;
test.whoAmI() //should print base
}
public override function whoAmI() {
trace("extended");
}
}
Should your Base extend something, which methods are known or the superclass is dynamic, and there is code that adds methods to prototype of a class, you might use such a downcast to call a superclass's method that might not be there at compile time, but make sure you first call hasOwnProperty in case of a dynamic class to determine whether a method or property exists.

AS3: One class with parameter, or two similar classes

In case of creating two similar custom AS3 visual components, ex. Button, with different look, but same function, which methodology is better, more efficient from the aspect of code-execution, speed, performance?
Creating two, almost identical classes, where the only difference is
in the visual components, so I have to write the button-controlling functions two times?
Creating one class, with a parameter input
that defines, which kind of button I would like to have
1:
package {
public class bigButton {
public function bigButton() {
//make a bigButton
}
}
}
and
package {
public class smallButton {
public function smallButton() {
//make a smallButton
}
}
}
or
2:
package {
public class OneKindOfButton {
public function OneKindOfButton(thisIsBigButton:Boolean) {
if (thisIsBigButton == true) {
//make it big
} else {
//make it small
}
}
}
}
In terms of an academic argument about the two structures (not this particular example), I'd have to argue that the first option is "better." Although opinion based posts are generally regarded as worthless by most of the SO community, I have a couple of points to bring up and would like to hear counter arguments.
For the second option of doing it, first off it makes me think that potentially there should be a base class that contains all the original functionality then a sub-class that tweaks some part of the functionality. Secondly it requires a condition in the constructor (and probably elsewhere littered throughout that class) to deal with the two scenarios the one class is handling. I think part of the issue here is that in AS3 there is a tendency to mash up all of the functionality and the view logic into one class, just because it's possible doesn't make it a good idea.
All said, I would probably go the route of having a base class that contains the functionality for the buttons, then make some sub-classes that do things different visually.
Also in terms of run-time efficiency I believe the first scenario will work out better again due to the extra conditions that will have to be checked at run-time with the second scenario. In any case, when performance and optimization is the issue it's always best to just run a test (build a little test app that makes 10,000 of each, run it a couple of times and get an average).
I would just create one kind of button class since you can draw or add other display objects into it. You don't even need a boolean to control that. For example :
public class OneKindOfButton extends Sprite{
public function OneKindOfButton(width:Number,height:Number) {
create(width,height);
}
private function create(width:Number,height:Number):void
{
graphics.clear();
graphics.beginFill(0xff0000,1.0);
graphics.drawRect(0,0,width,height);
graphics.endFill();
}
}
Now you can use this class to create any size of button.
var myButton:OneKindOfButton = new OneKindOfButton(200,20);
myButton.x = 100;
myButton.y = 300;
addChild(myButton);
If you want to use images instead of drawing into the button you can do that too by just adding bitmaps into the button sprite.
I think all these answers kind of miss the point of Flash.
Firstly, I don't think that View classes should ever have constructor arguments in Flash, because right off the bat you're making it impossible to ever use them on the timeline/stage. The Flash player can't (and shouldn't) provide these constructor arguments. The stage and timeline are Flash's biggest strength, so if you're not using them, you're wasting at least 25% of your time (the time where you're setting x, y, width, height, drawing graphics programmatically and all that unnecessary crap). Why lock yourself into a design that actively prevents you from using all the tools at your disposal?
The way I do it is I have one Class that defines the behavior of the button. Then the buttons are differentiated by having a library symbol for the big button, one for the small button, one for the button shaped like a pig, one for the button that looks like a spaceship, whatever. Any of these symbols will have that single Button Class as the Base Class (or more likely, just be defined as a Button in the library, so they subcass SimpleButton). Then I just place an instance of the library symbol on the stage and the variable in whatever parent Class is typed to my Button Class or SimpleButton.
The advantage of doing this is that the parent Classes don't need to know the specific implementation type, just the more general type. This means that the library symbols can have "export for Actionscript in frame N" unchecked, and they can just be compiled in where they are used. This means that initial load time can be reduced to the point that you may not ever need a preloader, depending on what else you have going on.
For more on this approach, see Combining the Timeline with OOP in AS3.
If the only difference between you two buttons is their look, but all the logic is shared, then you should definitely use only one common class.
If you're dealing with spark button, then you can simply specify a different skin for each of your instances (about spark skins).
package
{
import spark.component.Button;
public class MyCustomButton extends Button
{
static public const SMALL:String = "smallButton";
static public const BIG:String = "bigButton";
static private const DEFAULT_SIZE:String = SMALL;
public function MyCustomButton(type:String = DEFAULT_SIZE)
{
super();
if (type == SMALL)
{
setStyle("skinClass", SmallButtonSkin);
}
else
{
setStyle("skinClass", BigButtonSkin);
}
}
}
}
You then have to create to different skin classes where you'll define the visual logic of your buttons.