Junilu Lacar

+ Follow
since Feb 26, 2001
Junilu likes ...
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
Columbus OH
Cows and Likes
Total received
In last 30 days
Total given
Total received
Received in last 30 days
Total given
Given in last 30 days
Forums and Threads
Scavenger Hunt
expand Rancher Scavenger Hunt
expand Ranch Hand Scavenger Hunt
expand Greenhorn Scavenger Hunt

Recent posts by Junilu Lacar

Tasks defined under a user story should be focused on what needs to be done to complete the story. For example, "Create database scripts for test data" or "Penetration testing/review" or even "update project wiki to document major design decisions." Tasks help you plan your development activities related to a story and make sure you haven't missed anything to bring a story to DONE.

It sounds like you're also (mainly?) using tasks to track time spent. If you're going to do that, then I suggest you use the Pomodoro Technique and note down in the task how many pomodoros you spent, e.g. "Note: Total of fourteen 30-minute pomodoros spent working with intern" under the "Create stored procedure" task.
For comparison, the infix expression (a + b) * c would be ab+c* in postfix and stack-based evaluation would go something like this:

a : (operand)
   push a

b : (operand)
   push b

+ : (operator)
   pop op2 -> b
   pop op1 -> a
   substitute a -> 1
   substitute b -> 2
   add 1 +  2 -> 3
   push 3

c : (operand)
   push c

* : (operator)
   pop op2 -> c
   pop op1 -> 3
   substitute c -> 3
   mult 3 * 3 -> 9
   push 9

(End of expression):
   pop result -> 9
1 week ago
I believe what Stephan has shown you is the step-by-step process of evaluation. This is normally done using a stack. I don't know if you have gotten to stacks yet in your studies so just think of "evaluation" here as finding the innermost leftmost parentheses, substituting any variables inside the parentheses with their current values, calculating the term inside parentheses, then removing the parenthesis around the term. Then repeat the process starting with what's left, again finding innermost leftmost parentheses, etc., until you have reduced everything down to one term/value.

As I mentioned, this evaluation process is normally done with a stack involved and no actual parentheses. Instead, the rules of evaluation are used to turn infix expressions (where the operator is in between the operands) including explicit parentheses, into postfix expressions where the operator comes after its operands. Postfix expressions don't need parentheses to ensure correct order of evaluation.

For example, the infix expression a+b*c, evaluation is done as (a + (b * c)).

In postfix, the same expression is abc*+. The postfix (and converse prefix) order expression doesn't need parentheses around terms and subterms. This allows stack-based evaluation to be fairly straightforward.

For example, with abc*+, this is what happens if you have a = 1, b = 2, c = 3:

a: (operand)
 push a

b: (operand)
 push b

c: (operand)
 push c

*: (operator)
   pop op2 -> c
   pop op1 -> b
   substitute b = 2
   substitute c = 3
   mult 2 * 3 -> 6
   push 6

+: (operator)
   pop op2 -> 6
   pop op1 -> a
   substitute a = 1
   add 1 + 6 -> 7
   push 7

end of expression:
   pop result -> 7

When you get to the end of the postfix expression, you should have one element left on the stack which is the final result.

You can learn more about this if you search for prefix, infix, postfix notation and  stack-based processing of postfix expressions
1 week ago

Daisy Ridley wrote:Agile is one of the world’s most widely used and recognized software development framework.

"Agile" is not a framework. Scrum is a framework.

The Manifesto was developed by a group of fourteen leading figures in the software industry and reflects their experience of what approaches do and do not work for software development.

That's not how you spell 17.
Again, you seem to be conflating connection pools and threads. As Tim already told you, those are different things.

Read some articles about enterprise integration pattern - fire and forget and asynchronous processing of database requests
1 week ago

Stephan van Hulst wrote:it doesn't make sense to me that dice is an instance field and that sumOfLargest() is an instance method. You don't need the dice for anything other than instantiation.

Agreed. These should be static

It's also a pity that you let the class create its own dice rather than having dice injected in the constructor. It would have been much easier to test your class because then you can create it with a mock instance of Dice. The same with generator in your Dice class. Random is a service that more often than not you want to inject, and not create inside the class that depends on it.

Agreed. One must always balance simplicity with testability. Sometimes the cost of testability is more complexity but I think we should err on the side of testability eventually.

I'm guessing the modifier() method is an instance method because that's what the exercise demands.  Bad form though. It doesn't depend on instance fields and so it can be static (and private).

The unit tests and the skeleton code that the exercise started out with did have modifier() defined that way, so I just went with it. I wouldn't think those are hard requirements though so your point that it should be static is valid. Not sure about making it private though. The tests hint that some outside code might want to call it. Need more context about its use.

I don't like that you made the sumOfLargest() method package private to facilitate testing. Private methods are like an implementation detail. Test the methods that depend on it instead. If the private method is complex and you want to be sure that it works properly, there are testing frameworks that access private members.

What stories do the phrases warrior.sumOfLargest() or mage.sumWithoutSmallest() tell me? Don't forget your problem domain.

Yeah, it feels a little icky. Still thinking about this method and how to deal with it.

Why are the number of sides of dice constant? Had you passed the number of sides in the constructor, you could have created a separate die for your ability() method that has the same number of sides as the amount of ability scores there are. Or you could get rid of the Dice class altogether, because it's really just a paper thin wrapper around a Random, without really adding much extra behavior to it.

Point is valid and again goes back to the need to balance simplicity with testability, and (eventually) erring on the side of testability. I think the code will eventually evolve in that direction. It's a good exercise to be able to feel the forces that compel you to move in that direction though and this exercise is great practice. Of course, you also need great feedback like what you've been giving.

If you decide to keep the Dice class, I wonder why the roll() method takes a times parameter. Why not just let the client call the limit() method? A call would then look like: die.rollRepeatedly().limit(4).

Maybe a good approach is to move the methods to a separate utility class that is responsible for generating ability scores. It then has a clear responsibility that is decoupled from the DnDCharacter class

Again, good points. I will think this over and continue refactoring.

I'm going to be on the road again this week so my replies may be fewer and farther apart but I'll keep at this in the evenings when I can.

Thanks again for the discussion and great feedback.

I'd encourage you all to go to exercism.io and start working through these challenges as well. Unless it just happens to be another ksnortum who programs in Java out there, I'm pretty sure our Knute is also working on this.

Happy Monday everyone!
All good thoughts/questions, Stephan.

There are 9K plus students in The Horseshoe each receiving their own diplomas today so it's going to be a while before I can address them all.

All in all, Ohio State University is graduating 12,213 students this spring!

Stephan van Hulst wrote:Let the dice return a known sequence of rolls and then test if the method returns the sum of the highest three.


I'd love to see a different way of approaching the tests than what I did.
Here's the refactored code that is more testable:

and here are some tests for that:

My mindset is to protect myself from screwing up anything in the code by causing a test to fail when any regression is introduced. I think the only thing not covered here is the expression "times - limit" in the sumOfLargest() method.
It just occurred to me that there is no easy way to test code like this:

... or is there? Hmmm... I just got an idea. Will follow up later.
Darn it, I just realized what was bugging me about my implementation of ability(): it's just a happy coincidence that there are six abilities and that the dice I'm using has six sides. So, while the mechanics work, the semantics are nonsensical.

I should have PIEd this (Program Intent-fully and Expressively)

or maybe

Open to suggestions for names besides any() and randomAbility(). random()?

But then again, how do I test this kind of code?

Really need to hit the sack now but I look forward to discussing this some more when I can get back to you guys.
Here's what I have after incorporating what I learned from Stephan and his implementation:

I have to go to bed now; my son is graduating (from college! ) tomorrow and I need to get an early start. There is so much I'd like to discuss about Stephan's code but that will have to wait until Monday evening, US time.

Thanks again, Stephan, for sharing your stream-jutsu. It's pretty awe-inspiring, man.    
The unit tests implied that the DnDCharacter class would only have a no-args constructor. This is what I can up with:

This seems very clunky compared to what you wrote, Stephan.

The (holy) cow(!   ) is for this:

The elegance is stunning.