Win a copy of Succeeding with AI this week in the Artificial Intelligence and Machine Learning forum!

Aaron Shawlington

Ranch Hand
+ Follow
since Oct 01, 2013
Cows and Likes
Cows
Total received
0
In last 30 days
0
Total given
0
Likes
Total received
11
Received in last 30 days
0
Total given
1
Given in last 30 days
0
Forums and Threads
Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Aaron Shawlington


In languages that have references & pointers (as mentioned by the poster above) such as C++, then it tends to refer to the fact that a pointer 'points' to a memory address containing a value, while a reference (using the & operator in C++) is as the poster above mentioned - an alias of the value of that pointer (the variable).

What's important to understand here is that that 'alias' of that variable allows you to modify the value of that variable, but not the reference to it (the pointer).
I.e. if you pass a pointer, you then have the option to manipulate that pointer (to make it point somewhere else), or to manipulate the value that that pointer points to. With a reference you can only manipulate the value that reference points to.

There are loads of reasons to use one over the other, but one example to use a reference might be this:

You want to pass a large variable to a function AND you don't want anyone to accidentally make your pointer point to something other than the original variable.

By using a reference you don't have to copy the value to pass into the function - you just pass the memory address of that variable. You could do the same by passing a pointer to that memory address, but then the receiving function could accidentally manipulate that pointer (not it's value) to point to something else. That would mean that other areas of code referencing that original variable would get broken.

4 years ago
I get the impression that you're concentrating on testing at a too granular level. You should rarely ever want to test a single method on it's own. If it's some mathematics then I can understand that because you need to validate your algorithm - but in that case I'm not sure a lambda is the best place for it anyway. Those inline lambdas are a nice syntax for brevity when doing simple things. If you cram a load of logic into them then you're possibly kindof going against the point if them in the first place.
5 years ago
WHat takes 10 minutes? the whole thing? or the post-compile deployment?
5 years ago
Just read up on those patterns, and then (this is the important bit) get a deep understanding of WHY? Why is my favourite question ever. Just learn what people are doing and then ask yourself why over and over again until you start finding yourself giving your own opinions to other people. At that point you'll have trained your brain to think like a good developer - rather than to just mimic what good developers do.
5 years ago
Repeating what has already been said, but in different words incase it helps. If this makes no sense, then ignore it...

You could think of a class as a recipe. A recipe has a list of ingredients and a load of actions which need to be performed using those ingredients (in order to produce some output such as a cake).

In your Java class you'll find data and methods. The data is like the ingredients, and the methods are like the actions to be performed (such as beating the eggs).

The thing to remember about recipes, though, is that you can have different variations of the same recipe, right? When the recipe says you need 300g of flour to bake your cake, you could - if you wish - use double the amount if you want to make a cake twice as big. Also you could choose to use Raspberry jam instead of strawberry jam. Etc.

So a class is like a recipe that isn't too strict - it might force you to use flour, but it might not care how much. Or it might force you to have jam, but you might be free to use whatever flavour of jam you like so long as it's a type of jam.

So lets take a CakeRecipe class and create 2 instances of it (2 objects by using new CakeRecipe() twice). Lets suppose that by default the jam is Strawberry - when we invoke the bake method on each (recipe1.bake(); recipe2.bake()) we might get back 2 strawberry cakes.

Now lets suppose instead that we created our two Cake class instances:



but before we bake them we change the data in recipe2 to use raspberry jam instead of strawberry:



And then we bake then by invoking the bake method in each recipe:



cake1 will have strawberry jam while cake2 has raspberry jam.

And because the Cake class, like all classes, is a bit like a recipe - it also has data (jam flavour) and methods.
Perhaps the cake has a method calculateFatContent(). Now because cake1 and cake2 have different jam, perhaps they have different fat contents in the cake.

Perhaps cake1.calculateFatContent() returns 50g, and cake2.calculateFatContent() returns 45g.



In that sense, Objects are a grouping of methods (programming logic) and data into a cohesive unit - rather than random data being accessible by random functions for any random reason. And classes are templates (or recipes) of that grouping. When you get an object you know what class type it is, which means that you know what methods it has and what data you can manipulate. Because all objects are of a class type, when you create new objects you are forced to follow the template (or recipe). This can help to keep your code neat & tidy & maintainable.

There are downsides to object orientation, but you shouldn't worry about that yet.


5 years ago
Are you looking for some kind of 'state machine'?

Derik Davenport wrote:

Aaron Shawlington wrote:I think it's very likely that you should take your difficulties as a design smell - i.e. rethink your wider design, rather than trying to hack the existing one to make it work.

I agree. It is possible that some creative refactoring would solve my problem.. You asked 'Does the parser need to construct the Generator'. No, but in this example I have stipulated that it must use one. But perhaps there is a way to refactor so that I don't need to use one, or that the methods that rely on Generator could be grouped in Generator on within a class that contains a generator. I would have to think about it in terms of a real world example.

It violates the Liskov substitution principle for a start - and that's a very sensible principle 99% of the time.

I am not sure I understand the application of Liskov very well. I once believed that it just meant that I shouldn't be allowed to create a subclass that made the method of a parent class have a more restrictive scope or throw an exception not thrown by the parent class. And that doesn't really apply. I did a quick google on Liskov and found that some people interpret it much more liberally. For some people, overriding any method would be a violation. Whatever the correct interpretation of Liskov is, my problem would still exist if the child class had not overriden any methods of the parent (abstract) class.

In my original code I made the parent class abstract so that this would not be an issue. Moreover, I created an Interface for the Parent class. When I created that interface, it was my intention to state that usage of any instance of any concrete class (a subclass of AbstractMessageParser) would be accessed only through the interface. I am genuinely unsure of how to apply Liskov to that condition. Clearly, if I made HtmlParser derive from SmtpParser, then yes, that would certainly fail some kind of smell test. Is that Liskov?



As an aside, my understanding has always been that in simple terms the principle means that you should be able to swap a superclass instance for a subclass instance without breaking the semantics of your program.

I was thinking about this last night on the way home from work. I decided that perhaps it isn't really a Liskov violation - but it just has (to me) a Liskov kind of smell to it (not very helpful I'm sure). I think it's just because your abstract class feels too 'involved' with the responsibilities of it's subclass instances - a side effect of wanting this compile time validation I suppose.



5 years ago
Be very careful with your constructors and initializers too (one of the posts was talking about trying whacky things here). The JVM will execute the super constructor first, including methods invoked, and then it will initialise any fields in the subclass (potentially undoing what was done in the superclass constructor) before it then proceeds with the rest of the subclass constructor.
5 years ago
I think it's very likely that you should take your difficulties as a design smell - i.e. rethink your wider design, rather than trying to hack the existing one to make it work.
It violates the Liskov substitution principle for a start - and that's a very sensible principle 99% of the time. When I find myself in difficulty, and then notice that I'm violating some generally sound principle, then it's normally a sign to me that I've gone down the wrong path somewhere.

In your example it also looks as though your classes are far too aware implementation details. Does the parser implementation really have to construct the generator?

And then when your code is less tangled, would you really need that compile-time protection? That's what unit tests are for (when your code is built using the correct abstractions).
5 years ago
I think I need to apologise to Vitaliy... For some reason I was thinking that you and the OP were the same person! No wonder my question didn't make sense to you.
5 years ago

Vitaliy Gaydarenko wrote:I emulated two situations about what we speak. And compare results.
We talk about resources, not abut that it will be a same code.



Sure... but using different code to wonder about different resource usage implications of writing that different code, doesn't make any sense when that code compiles down the the same thing. I.e. the different in the code that you're analysing is illusory (for want of a better word).

The last example you posted doesn't compile down to the same thing both times, so it's a valid test. Fine.

So what I'm checking is that you understand *why* using the StringBuilder is more efficient in the second example than not using it - and that you understand *why* it makes no difference in the first example (although I suppose I answered my own question when I said it compiles to the same thing).

The first is important to understand in order to have some mechanical sympathy wen writing code (although most of the time it doesn't matter too much).
The second is important because it can save you from writing theoretically more optimal, yet redundant, code at the cost of readability.
5 years ago

Vitaliy Gaydarenko wrote:I have a little test:
String s = "Start ";
for (int i = 0; i < 100000; i++) {
s += i;
}
System.out.println(s);

and
StringBuilder sb = new StringBuilder("Start ");
for (int i = 0; i < 100000; i++) {
sb.append(i);
}
System.out.println(sb.toString());

Speed of second (with Builder) is greater in thousands time.
And so, with Builder is much better than without it.



Do you understand why it makes a difference in tis test, but not your first example? (assuming you trust that it wouldn't - as it compiles to the same bytecode)
5 years ago

Junilu Lacar wrote:
What version of Java is this though?



1.8.0 of whatever comes with OSX - unless I symlinked it to my homebrew installation :s
5 years ago
Also just had a thought... you specifically mention Java 6. There were some changes to the String pooling in one of the minor version updates (which you may or may not be referring to or interested in).

It used to be the case (unless I'm remembering it back-to-front) that "FOOBAR" and "FOO" were backed by the same character array, with the first string just having a reference to the last character at index 5 and the second string at index 2.

Now each string gets it's very own character array all for itself, and if you want to optimise and have the old behaviour then you need to implement it yourself.

That's the rough idea anyway - it's been a while since I looked into those changes.
5 years ago

Dave Tolls wrote:
the compiler creates a StringBuilder for each of those '+=' lines.



Good point - i've never bothered to try that out before. I had assumed that it just couldn't handle loops.

**edit** for interest:


5 years ago