ThoughtWorks' Agile Project Management application
Adewale Oshineye (feed)
Aidan Rogers (feed)
Alan Francis (feed)
Alex Ruiz (feed)
Amit Rathore (feed)
Andres Taylor (feed)
Andrew Trigg (feed)
Antonio Terreno (feed)
Aslak Hellesoy (feed)
Ben Griffiths (feed)
Ben Hogan (feed)
Benno Rice (feed)
Bernardo Silva (feed)
Bill Six (feed)
Bret Pettichord (feed)
Brett Dargan (feed)
Brian Oxley (feed)
Cenk Civici (feed)
Chaoqun Li (feed)
Charles Lowell (feed)
Charles Tse (feed)
Chris Brown (feed)
Chris Matts (feed)
Chris McMahon (feed)
Christian Kvalheim (feed)
Christian Taubman (feed)
Craig Cruden (feed)
Damian Guy (feed)
Daniel Manges (feed)
Daragh Farrell (feed)
Darren Hobbs (feed)
Dave Astels (feed)
Dave Hoover (feed)
David Kemp (feed)
Dennis Byrne (feed)
Dragos Manolescu (feed)
Duncan Cragg (feed)
Dustin Aleksiuk (feed)
Elizabeth Keogh (feed)
Fabio Gavilondo (feed)
Fred George (feed)
Garrett Smith (feed)
Geoff Oliphant (feed)
George Malamidis (feed)
Greg Luck (feed)
Greg Wdowiak (feed)
Gregor Hohpe (feed)
Griffin Caprio (feed)
Igor Stoyanov (feed)
Ivan Moore (feed)
Jack Bolles (feed)
Jake Scruggs (feed)
James Mead (feed)
James Ross (feed)
James Webster (feed)
Jason Huggins (feed)
Jay Fields (feed)
Jeff Patton (feed)
Jeff Santini (feed)
Jeremy Stell-Smith (feed)
Joe Homs (feed)
Joe O'Brien (feed)
Joe Walnes (feed)
Jon Eaves (feed)
Jon Tirsen (feed)
Jonathan Rasmusson (feed)
Julian Simpson (feed)
Karthik Chandrasekariah (feed)
Kashan Arshad (feed)
Kerry Todyruik (feed)
Kiran Bellubbi (feed)
Kurt Schrader (feed)
Kurtis Seebaldt (feed)
Li Xiao (feed)
Marco Abis (feed)
Marty Andrews (feed)
Matt Clarkson (feed)
Matthew Deiters (feed)
Matthew Ueckerman (feed)
Megan Folsom (feed)
Michael Klynstra (feed)
Michael Ward (feed)
Mike Mclaughlin (feed)
Mike Melia (feed)
Mike Roberts (feed)
Mike Williams (feed)
Muness Alrubaie (feed)
Narayan Raman (feed)
Narayan Raman (Sahi) (feed)
Naresh Jain (feed)
Narla Keshav Ram (feed)
Nat Pryce (feed)
Nathan Arthur (feed)
Niket Kumar Bhumihar (feed)
Obie Fernandez (feed)
Obie Fernandez (feed)
Obie Fernandez (JRoller) (feed)
Owen Rogers (feed)
Paul Coia (feed)
Paul Holser (feed)
Paul Ingles (feed)
Paul Julius (feed)
Paul Miles (feed)
Peter Barry (feed)
Peter F Ryan (feed)
Prashant Gandhi (feed)
Rene Duquesnoy (feed)
Richard Watt (feed)
Ross Niemi (feed)
Ryan Kinderman (feed)
Shane Duan (feed)
Shane Harvie (feed)
Simon Stewart (feed)
Stacy Curl (Digital Compulsion) (feed)
Steve Freeman (feed)
Szczepan Faber (feed)
Thomas Looy (feed)
Tim Bacon (feed)
Tim Goodwin (feed)
Tim Velvick (feed)
Vivek Vaid (feed)
Wilkes Joiner (feed)
William Caputo (feed)
Xiaoming Wang (feed)
__ThoughtBlogs-Admin (feed)
The system I'm currently working on integrates with several external systems, over HTTP, using simple (RESTish) web-services. I really don't want to involve those external systems while testing my own, though; I want to stub 'em out.
My first attempt involved stubbing out HTTP calls using my mocking framework of choice. I'm using RestClient, which I like a lot, and stubbing out RestClient API calls worked quite well. It kept on working quite well for several hours, until I decided to refactor a little, using RestClient in a slightly differently way, at which point it broke completely. Bother. I really don't like having tests coupled to implementation details, so went searching for another way.
FakeWeb looked pretty good, in that it stubs things out at the Net::HTTP layer, which I'm unlikely to refactor out of the picture. In the end, though, it's not really what I wanted. I wanted to be able to do things like:
In short, I wanted a Fake Object, rather than a simple stub.
It occurred to me around about then that we already have plenty of tools for describing the behaviour of web-applications: they're called web-application frameworks! Many of them are too heavy-weight for my purposes, but Sinatra is nicely minimal. So, 60 lines of Ruby code later, I had a little web-app that mimicked one of those external web-services sufficiently for my testing. Win!
But waitaminut. I really don't want to have to start a separate process running my fake web-service, and talk to it using HTTP. That's going to be slow: network I/O isn't cheap. Isn't there some way I can use something like Sinatra but still keep everything in-process?
There is now. ShamRack plumbs Net::HTTP directly into applications built to run on Rack. Which includes all Sinatra apps, as well as Rails, Merb, etc.
Using ShamRack, I avoid the network traffic, making the tests a whole lot faster (about 25 times faster, in my case). Plus, I avoid the complication of having to start and stop an external web-server. Finally, because my fake web-service app is in-process, I get a handy back-channel I can use to setup or inspect it's state during tests.
If you find ShamRack handy, or have ideas about how it could improve, let me know!
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Not a bad explanation of a state machine for guy who just learned about them that day: Good job distant-past-jake. I think ended up using a state machine pattern in my code submission to ThoughtWorks later that year.
I later worked on a huge java project that would generate something like 15 classes for every one written class. I soon got very tired of generated code ("Hey, why did my changes go away? Oh, it's a generated class... (next line said forlornly) Guess I better go dig through the xml pit for what to change.")
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
So mark down July 1st, 2004 as the day I felt like I really might be able to become a programmer. Since starting at Object Mentor I had contributed almost exactly nothing except for the occasional "You spelled that wrong." But on that hallowed day I actually figured something out before Paul. Maybe I wouldn't have to go back to teaching high school remedial physics and hating Sunday nights because of what Monday promised. Heady thoughts.
Interestingly enough Jay Fields wrote a blog post about the "Spellchecking Pair" a few years later. He makes some good points about matching the levels of programmers but:
A. That's not always possible.
B. I'd feel pretty bad if I was a junior guy on his team when he wrote that post.
C. Inexperienced devs already feel like they are worthless -- try not to make them feel worse.
Still it's important to talk about the problem -- you want to bring developers along but sometimes the impedance mis-match can really frustrate both developers. I generally err on the side of "pairing increases the long term health of the project," but of course their are exceptions. It's just that the exceptions have a nasty way of becoming the rule.
mocha/standalone.rb file. It turns out this assumption was incorrect at least in the case of RSpec. This is now fixed.While I’m coding, I usually have a bunch of very helpful pixies hanging around my desk. (They’re Dan’s pixies really, since he thought of them first; I’m just borrowing them.)
The pixies are bored, and just waiting for a job to do. So, when I’m coding a class, they look out for opportunities to help out that class. When I’m coding the Game of Life, for instance, I write a Gui class that lets me toggle the cells on the grid. Then I have to work out what happens when I toggle the cells.
I could do it in the same class - in the gui - but fortunately the pixies step in to prevent me making these poor design decisions. “Oh, I’ll do that for you!” one of the pixies calls out. (They usually start with this phrase, and they’re all called Thistle.)
“Thanks, Thistle! Do you know what you’re doing?”
“Um, not really. What’s toggling a cell? Why’s that valuable? What is it you want me to do for you again?”
“I need you to handle the cell living and dying when I toggle it.”
“Oh, okay!” Thistle says. “I don’t like the ‘and’ word so much, though. It makes me feel like I’m doing two things at once. What do you call that? The living and dying thing?”
“Hm.” I think about it while the pixie taps his foot impatiently. “I’d call it a lifespan, maybe. Can you handle the cell lifespan for me? Just let me toggle the cells. I also need you to tell any observers that there have been some changes to the cells, and give them a way of finding out where those changes are. I think they’ve already got an idea of what they want there.”
“Really? Both things?”
“Well, there’s no point doing one if you don’t do the other. It’s all part of the same role.”
“If that’s what’s valuable to you then I’ll do it,” he says. “Just pretend I’m there for the moment; I’ll be back when you need me.”
“Fine,” I say. So I use a mock pixie in place of the real one. I create an interface which does what the pixie’s going to do: IHandleCellLifespans.
(See, it’s an interface that starts with “I”, and it represents a role that the pixie is playing for me. This is a role-based, anthropomorphized interface.)
So, now we have code which compiles. Of course, the real code in the Gui is null, or maybe a null object pattern - I might create something like IHandleCellLifespans.KILLING_THEM_ALL if I’m feeling particularly mean. But that’s all right, because Thistle the pixie will step in when it’s time.
So, I run the code. I’ve usually written an automated scenario. It doesn’t matter whether I run the scenario or step through the game manually; both result in the same thing happening, or not happening - no matter where I click the mouse, no cells appear. Pixies are notoriously unreliable.
Since I can’t rely on the pixies, I inject a new class to handle the dependency instead. I decide to call it the Engine, for the moment, and I write an example of how to use it and what it should do for me.
The next step is the Next button. I think about how this would work in the Engine, and start writing some code to show how the Engine needs to behave. I’ll need to calculate the number of neighbours, and apply the rules accordingly.
One of the pixies pipes up, “Oh, I’ll do the neighbours!” and another one says, “Oh, I’ll handle the rules!”
“Fantastic!” I’m so trusting; I always forget what these pixies are really like when it comes to getting the work done.
“If I’m going to count the neighbours,” Thistle says, “I’ll need some information about where I’m counting from, and what’s around me.”
“Ah, I can get the information from the cell itself,” I say.
“No, don’t do that. It’s fine where it is; I’ll just sit inside the cell and do it from there. Can you give me something that lets me know where the other cells around me are? Then I can do the work for you.”
“Sure,” I say, “the Engine knows where the life is. I’ll just give you access to the Engine and let it play that role for you.”
“Can’t I do it instead? I’m bored,” one of the other pixies asks. “Just give me the information from the engine, and let him talk to me instead.”
“Um, Okay.”
Of course, when I try to run it then I find out that all the pixies have mysteriously vanished, and I end up assigning the role to the Engine anyway, or one of its anonymous inner classes. Having it defined as a different role means that it’s easy to move this responsibility around. Maybe I’ll create a World to look after the cells, and let that do the job instead; the pixies certainly aren’t very helpful.
“What do you mean, we’re not very helpful?” Thistle says. “Look at your code. You haven’t written anything that isn’t needed by something else, so there’s less code to maintain. Because we jump in all the time to try and do jobs for you, every time you can assign a new responsibility to something else, you do - that’s the single responsibility principle in action; none of your classes are doing too much. And you can replace us with something else that does the job at any time - that’s the Liskov Substitution principle. The roles we perform are clearly named. It’s been easy to describe the behaviour of each class using mocks to stand in when we’re not there, and the examples are very readable. You can also use them to work out whether your code still works or not, by running them as tests.”
“Okay. I can’t see myself relying on you guys for bigger, enterprise stuff, though.”
“What do you mean?” Thistle looks offended. Oops.
“Well, let’s say that I’ve got a shop, and I need the tills to talk to stock control.”
“Controlling stock? Oh, I’ll do that!” one of the pixies announces excitedly.
“What, all on your own?”
“Well, I’ll probably delegate it to a team, but that’s my responsibility - you don’t need to worry about it. I’ll be there when you need me. Just pretend I’m there for now. How would you like to find me? What kind of stuff are you going to send to me, and what do I need to do with it? What would you like back?”
So I start with something simple - a URL that I’ll use to find Thistle the pixie, some domain objects that I want to send him, and some objects that I’d like back in return. We talk about how to get the information across, whether some of the tills might provide different stock information, how to talk to the claims department about the quality of the goods we’re selling, and whether I’ll be okay if the claims he gives me have more information than I need.
“Hold on,” I say. “You’ve got me playing this game now. I’m not a Claims Department. I’m not going to do the job myself. I’ve got a home to go to!”
“Meh, never mind,” Thistle replies. “I’ll be sitting with this team over here, coding the stock control. We’ll just pretend you’re doing the job; we’ll mock you out for now.”
“How will I know that I’m doing the job correctly?”
“We’ll have to talk to each other occasionally. Is that going to be hard? We’ll write some scenarios over in our team that describe how we’re going to use you.”
“What if I make a mistake?”
“Do you know what mistakes you’re going to make already?”
“No,” I confess. “I’m sure there will be some, though.”
“When you make a mistake, we’ll deal with it at that point. Sound good?”
I think about it. I reckon I could write some code that pretends to be doing the job of the Claims Department and responds correctly to the way they’ve described how they’re going to use me - just for those examples - then I could go home and Thistle would never know. I knock up a quick stub and slip it into the stock control team’s scenarios, then I disappear too, just like the pixies. I figure I’ll start coding a real Claims Department that does a more robust job tomorrow.
When I get back the next morning, all the pixies performing the role of Stock Control have been replaced with code too. The Stock Control team claim that they’ve never even seen them.
I corner Thistle again. “You’re really not very helpful, are you?”
Thistle looks sulky. “Of course we are! Look at your architecture. You’ve got simple messages going back and forth. Your code is very tolerant of extra information, as is the code on this side. You’ve got lovely RESTful URLs, because you were thinking about how you’d like to find us, instead of us providing you with some weird mechanism that doesn’t match exactly what you wanted. We’ve got clean interfaces and APIs. There are no extra columns in your database, because you only replaced exactly what we said we’d do in the first place. You’ve got scenarios to describe how we work together, and at a unit level examples to describe how you’re delegating responsibility to the other pixies. It’s a lovely, maintainable system with a fairly flat cost of change. Isn’t that what you wanted?”
I nod thoughtfully. “I think it would have been easier for me to just write the code instead of going through you all the time.”
“Ah,” says Thistle, “but then you’d have code that was easy to write, instead of code that’s easy to use.”
I think about how they made me fill in the role of the Claims Department. “You never did any of the work, though! I could have done that job myself; put myself in each of those roles and then replaced myself with real code. That would have let me create consumer-driven interfaces just as easily as using you.”
Thistle shrugs. “If that’s what works for you, sure.”
“Won’t people think I’m a bit mad? If I start talking about how I’m personally going to use a particular class, or how I’m offering to do a job for another?”
Thistle looks at me with raised eyebrows, then gestures at all the other pixies clustered around my desk.
“I think it’s a little late to be worrying about that now,” he says.
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
"The eighties music was off today" -- huh? I don't remember this at all. Were the Object Mentors crazed 80s fanatics?
I'm still scared about pairing with people I don't know, oddly enough. I've been doing this pairing thing for 5 years now and yet I still get wound up at the prospect of sharing a computer with another programmer -- what if they're better than me and I feel bad? Almost 100% of the time my fear is completely unfounded and I end up having a great time and learning a bunch. The only time I really hated it is when I let the other person type too much -- then I just feel like a loser. No matter what the skill difference, each pair should spend about the same amount of time driving.
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
"I didn't drive today" -- read that as I spent all day watching someone type. Which is not a fun day. Chalk that up to the fact that we were doing regular expressions and I had never seen one before. I'm decent at RegEx's now but I think I avoided them for years because of my first experience. Nothing like resolving to get more involved and then falling out of the frying pan and into the fire to dampen the old spirits. And then a whining computer in the background for extra torment. I'm surprised I didn't just type a single four letter word to sum up June 29th 2004.
This month the talk will be given by one of our organizers, Griffin Caprio, on Semantic Mashups.If you want to come, please RSVP using the links above. That will help us get a idea about food & drinks as well as take care of the building security.
Description
A mashup is a web page or application that combines data or functionality from two or more external sources to create a new service. Semantic mashups take this a step further by utilizing semantic web technologies to create a richer experience. Using RDF, SPARQL and URIs, mashups can evolve past the simple reuse of data and into the discovery of new knowledge.
In this talk, we'll be presenting sports statistic semantic mashup examples and explaining the underlying techniques and technologies that make them possible.
Speaker Bio
Griffin is a startup oriented entrepreneur with substantial experience in all phases of IT governance, product development and software engineering. Focusing on using technology to solve real problems and reducing friction of how technology affects everyday life, his company, 1530 Technologies, builds well engineered products for real world problems.
We are also scheduling some time for people to meet and talk.
Food and drinks will be provided, however it would be appreciated if you can chip in $5 to help cover our costs.
Technorati Tags: semantics, mashup, sports statistics
Hi, I'm Michael Chang, the intern that Griffin was talking about. I'm excited to work at 1530 Technologies this summer and get my feet wet in web development. Throughout the summer I will update the blog with what I'm working on as well as any musings I may have about the web or technology in general.
On one last note, Go Lakers!
run_test method on TestCase which clashed with the public TestRunner#run_test method. So this latter method has been renamed to run_as_test.rubygems – this should be an environmental choice for the user. This describes why requiring rubygems in your library code is a bad idea.coderay and meta_project when they’re only needed to generate the examples for documentation and for publishing files on RubyForge. So I’m removing them and installing them locally as gems when I need them.TestCase#run method. Unfortunately in version 2.0.0 this method differs slightly from the same method in version 2.0.1 & 2.0.2, so we have to provide different implementations to ensure that the internal working of Test::Unit are not compromised by Mocha. Note also that unless the test-unit gem is loaded, requiring 'test/unit' leads to a mixture of standard library and gem classes being loaded causing errors. To avoid a dependency on rubygems, the gem is loaded only if MOCHA_OPTIONS is set to use_test_unit_gem – this option is only intended for use in running Mocha’s own tests. It might be worthwhile to create a shim gem like minitest_tu_shim to allow the test-unit gem to completely replace the standard library, but that’s a job for another day. My previous article on Test::Unit and MiniTest explains how the minitest-tu-shim works. The changes in the Rakefile are to make the default task run with the test-unit gem (version >= 2.0).Mocha::Standalone to Mocha::API to better reflect its purpose. Added a deprecation warning for those who are referencing Mocha::Standalone.Hash (thanks to Taylor Barstow).Rails/ActionPack tests to break. I’ve removed the loading of MiniTest, but this now means the user has to ensure that if they want to use MiniTest in conjunction with Mocha, he must load MiniTest before loading Mocha.ExpectationErrors as errors not failures.Recently I’ve been getting a lot of request for Agile Training and Consulting. Unfortunately the expectations from the training are not clear for me. Most people approach me saying, “we want a TDD training” or “we want a Project Management training“. Once I start talking to them & their team (or even worse sometime during the training), I realize the topic we’re discussing is not their biggest issue. I get a feeling that most organizations have not done their homework to figure out what they really need and how they should go about it. They might have heard somewhere that ‘blah’ will help them and they want to jump on it.
Few months ago I started doing readiness assessments before my trainings. (I’ve also started doing assessments after my training so see if the training was effective.) But I have realized the assessment is not enough. So I’ve started asking the following questions even before the assessments:
Luckily a lot of organizations don’t get back to me with answers for these questions. This is really good for me, because this acts as a filtering criteria. I feel I would have wasted my time training/coaching this team. There are others who are in much more need and are more receptive to what I’ve to contribute.
Tweet This Post
Plurk This Post
Buzz This Post
Delicious This Post
Digg This Post
Ping This Post
Reddit This Post
Stumble This Post
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
This is one of about 10 posts where I say something like: "What the hell happened today -- I need to ask more questions." Part of my role at Obtiva is to say this to our apprentices: "Yes I know you feel like a complete idiot and it seems like you can't take one more day of not knowing what the hell is going on, but believe me that I've been there and it will come. Don't be afraid to look stupid early instead of confessing at the end of a week/month/year that you have no idea." Easy to say, but hard to do.
Also the computer I was using was this Dell Inspiron laptop which was about 2 years old at the time and very slow. Installing Microsoft Visual Studio nearly killed it. I think I actually still have it in the other room - I keep meaning to throw it out but it's hard to let go of tech stuff.
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
The really weird thing about that week was that, up until that moment in my life, I truly sucked at puzzles. Somebody would start in with "You and three friends are walking through the forest and each of you has a prime number of hotdogs..." and I'd get lost and start to panic. I'd be thinking that everyone knows the answer to this but me and they are finally going to find out that I'm a fraud and the dumbest guy in the room. So I'd spend most of my thinking time worrying about how much time was left before someone figured it out and then what if they announced that they had got it but didn't tell me the answer and I had to keep thinking about it knowing that someone had beat me to it and it was probably obvious and... Etc., etc., etc.The weird thing about that week was that I solved every puzzle without getting crazy. It was like after I got the first one I could relax and think about the problem. It's a constant surprise to me how many things essentially boil down to confidence and comfort. If people feel comfortable in a situation they will perform exponentially better than they will in a tense environment.
I've updated Team Piazza to work with Team City 4.x. You can download the new version at http://team-piazza.googlecode.com/files/piazza-20090625.zip.
I ran across this interesting Scala class by Vaclav Pech which makes the data concurrent rather than the code (if I understood the author correctly). The ~ (extraction) and << (insertion) operators looked nifty.
Looking to do the same in Java, I see four key requirements:
With these in mind, I write this:
public class DataFlowReference<T> {
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private volatile T item;
private volatile boolean set = false;
private volatile boolean called = false;
public T get()
throws InterruptedException {
lock.lockInterruptibly();
try {
while (true) {
if (set)
return item;
if (!called) {
called = true;
onFirstGet();
continue;
}
condition.await();
}
} finally {
lock.unlock();
}
}
public void setOnce(final T value) {
lock.lock();
try {
if (set)
return;
set = true;
item = value;
condition.signalAll();
} finally {
lock.unlock();
}
}
protected void onFirstGet() {
}
// Object
@Override
public boolean equals(final Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
final DataFlowReference that = (DataFlowReference) o;
return set && item.equals(that.item);
}
@Override
public int hashCode() {
return set ? item.hashCode() : super.hashCode();
}
@Override
public String toString() {
return "(" + set + ':' + item + ')';
}
} Use of DataFlowReference follows the examples from Vaclav's page: declare dataflow references, create threads whose runables use setOnce() and get(), invoke them all together.
onFirstGet() supports "just in time" supply of item and would call setOnce(T) with a fresh value.
UPDATE: The original version of this class had a horrible, obvious race condition. Caveat plicator.
I’m just reviewing a project’s code. I found a common pattern used in their code base. Every class implements an Interface. Each interface is only implemented by one class. Even more interesting, this interface is not exposed outside. In other words, its not exposed as part of the API.
Then my question is
Why do we need the interface? Why can’t we just use the class directly?
Apparently there is no valid answer. Some told me,
Anyway, we don’t need one stupid interface for every class we create. YAGNI. When we need it, we’ll create it. This is one form of speculative generality code smell.
Go ahead, kill it!
Tweet This Post
Plurk This Post
Buzz This Post
Delicious This Post
Digg This Post
Ping This Post
Reddit This Post
Stumble This Post
var xmlStr = '' +
'<people>' +
' <person gender="male">' +
' <name>Ant</name>' +
' <hair>Shaggy</hair>' +
' <eyes>Blue</eyes>' +
' <height measure="metric">176</height>' +
' </person>' +
' <person gender="male">' +
' <name>Paul</name>' +
' <hair>Spiky</hair>' +
' <eyes>Grey</eyes>' +
' <height measure="metric">178</height>' +
' </person>' +
'</people>';
var $x = new XML(xmlStr);
_assertEqual("Ant", $x.person[0].name.toString());
_assertEqual("Grey", $x.person[1].eyes.toString());
for each (var $p in $x.person){
var $measure = $p.height.@measure.toString();
_assert($measure == "metric");
_assert($p.height > 170);
}
* With iterator:
* 1.6 with 100,000 store size: puts take 45ms. keySet 7ms
* 1.6 with 1000,000 store size: puts take 381ms. keySet 7ms
* 1,000,000 - using FastRandom (j.u.Random was dog slow)
* INFO: Average Get Time for 2065131 observations: 0.013553619 ms
* INFO: Average Put Time for 46404 obervations: 0.1605034 ms
* INFO: Average Remove Time for 20515 obervations: 0.1515964 ms
* INFO: Average Remove All Time for 0 observations: NaN ms
* INFO: Average keySet Time for 198 observations: 0.0 ms
* 9999 - using iterator
* INFO: Average Get Time for 4305030 observations: 0.006000423 ms
* INFO: Average Put Time for 3216 obervations: 0.92008704 ms
* INFO: Average Remove Time for 5294 obervations: 0.048545524 ms
* INFO: Average Remove All Time for 0 observations: NaN ms
* INFO: Average keySet Time for 147342 observations: 0.5606073 ms
* 10001 - using FastRandom
* INFO: Average Get Time for 4815249 observations: 0.005541354 ms
* INFO: Average Put Time for 5186 obervations: 0.49826455 ms
* INFO: Average Remove Time for 129163 obervations: 0.015120429 ms
* INFO: Average Remove All Time for 0 observations: NaN ms
* INFO: Average keySet Time for 177342 observations: 0.500733 ms
* 4999 - using iterator
* INFO: Average Get Time for 4317409 observations: 0.0061599445 ms
* INFO: Average Put Time for 2708 obervations: 1.0768094 ms
* INFO: Average Remove Time for 17664 obervations: 0.11713089 ms
* INFO: Average Remove All Time for 0 observations: NaN ms
* INFO: Average keySet Time for 321180 observations: 0.26723954 ms
* 5001 - using FastRandom
* INFO: Average Get Time for 3203904 observations: 0.0053447294 ms
* INFO: Average Put Time for 152905 obervations: 0.056616854 ms
* INFO: Average Remove Time for 737289 obervations: 0.008854059 ms
* INFO: Average Remove All Time for 0 observations: NaN ms
* INFO: Average keySet Time for 272898 observations: 0.3118601 ms
In summary, with 1 million objects in the map a put to Ehcache using iterate for eviction, takes 381ms!
As a result I have used an alternative to iteration using an algorithm called FastRandom. The result is 0.16 ms, 2,300 times faster!
For very small maps, ConcurrentHashMap iteration is quite quick. From experimental testing in Ehcache 1.6 we use iteration up to 5000 entries and FastRandom for sizes above that.
Here is a sample of code (happens to be from a test) which I think is not communicative.
public class ContactNumberTest {
final String exampleCountryCode1 = "91";
final String exampleCountryCode2 = "1";
final String exampleNumber1 = "8012345678";
final String exampleNumber2 = "2028569635";
ContactNumber phoneNumberA = new ContactNumber(exampleCountryCode1,exampleNumber1);
ContactNumber phoneNumberB = new ContactNumber(exampleCountryCode1,exampleNumber1);
ContactNumber phoneNumberC = new ContactNumber(exampleCountryCode2,exampleNumber2);
@Test
public void testEquals() {
//Symmetry
assertTrue(phoneNumberA.equals(phoneNumberB));
assertTrue(phoneNumberB.equals(phoneNumberA));
//Reflexivity
assertTrue(phoneNumberA.equals(phoneNumberA));
//Not equals
assertFalse(phoneNumberA.equals(phoneNumberC));
}
@Test
public void testHashcode() {
assertTrue(phoneNumberA.hashCode() == phoneNumberB.hashCode());
}
}
I know you must be wondering why in the first place someone is writing tests for equals and hashCode. I agree. Its not required. But lets say someone really needs to.
This is how I would refactor the code to make it more communicative.
public class ContactNumberTest {
private final String indiaCountryCode = "+91";
private final String usCountryCode = "+1";
private final String cellNumber = "8012345678";
private final String mobileNumber = "2028569635";
private final ContactNumber indianNumber = new ContactNumber(indiaCountryCode, cellNumber);
private final ContactNumber sameIndianNumber = new ContactNumber(indiaCountryCode, cellNumber);
private final ContactNumber usNumber = new ContactNumber(usCountryCode, mobileNumber);
private final Map users = new HashMap();
private String userName;
@Test
public void isSymmetrical() {
assertNotSame(indianNumber, sameIndianNumber);
assertEquals(indianNumber, sameIndianNumber);
assertEquals(sameIndianNumber, indianNumber);
}
@Test
public void isReflexive() {
assertEquals(indianNumber, indianNumber);
}
@Test
public void isTransitive() {
ContactNumber newIndianNumber = new ContactNumber(indiaCountryCode, cellNumber);
assertEquals(indianNumber, sameIndianNumber);
assertEquals(sameIndianNumber, newIndianNumber);
assertEquals(newIndianNumber, indianNumber);
}
@Test
public void areNotAlwaysEqual() {
assertFalse(indianNumber.equals(usNumber));
}
@Test
public void equalsIsExceptionFree() {
assertFalse(indianNumber.equals(null));
}
@Test
public void isHashFriendly() {
addUser(”Foo”).usingKey(indianNumber);
assertEquals(”Foo”, users.get(indianNumber));
addUser(”Bar”).usingKey(sameIndianNumber);
assertEquals(1, users.size());
}
private void usingKey(final ContactNumber number) {
users.put(number, userName);
}
private ContactNumberTest addUser(final String userName) {
this.userName = userName;
return this;
}
}
Tweet This Post
Plurk This Post
Buzz This Post
Delicious This Post
Digg This Post
Ping This Post
Reddit This Post
Stumble This Post
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
When pairing goes well it's like hanging out with your friends all day, getting work done, and getting paid to do it.
To be totally honest I never did try to use Python or 'runable' to solve the TicTacToe repeated code problem. I did later learn Ruby and blocks which solved the problem quite nicely. As my friend Pat Farley once said: "Ruby is great at removing the duplication where you're doing the exact same thing repeatedly but all the words are different." I had to think about that one for a week before I got it.
@Test
public void shouldNotOverrideDir() {
new Temporarily().setProperty("a.dir", "was.preset").when(new Snippet() {{
new Main().setupDir();
assertEquals("was.preset", System.getProperty("a.dir"));
}});
}
public class Temporarily {
private Map properties = new HashMap();
public void when(Snippet snippet) {
for (Map.Entry entry : properties.entrySet()) {
System.setProperty(entry.getKey(), entry.getValue());
}
}
public Temporarily setProperty(String propertyName, String propertyValue) {
if (System.getProperty(propertyName) != null) {
properties.put(propertyName, System.getProperty(propertyName));
}
System.setProperty(propertyName, propertyValue);
return this;
}
}
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Oh 'Cowboy' and 'You Cowboy!', your antics still amuse after all these years. Not so pleasant memories about casting classes into other classes. That whole statically typed thing seems like such a fad in hindsight. I shouldn't really trash talk about Java and C# though. I think half the reason I react with aversion to them is that I was a mediocre programmer back when I was in static land. When I was in Ruby I really came into my own as a programmer and so I associate Java and C# with the times in my life when I sucked and Ruby with some actual competency and satisfaction.
Also, I love the part where I was impressed with the flat panel monitors -- this was 2004 when only the serious would shell out tall green for a 15 inch monitor with thousands of colors and a 1:50 contrast ratio.
@Test
public void shouldFreezeTime() {
Freeze.timeAt("2008-09-04").thawAfter(new Snippet() {{
assertEquals(new DateTime(2008, 9, 4, 1, 0, 0, 0), new DateTime());
}});
}
public class Freeze {
public static Freeze timeAt(String dateTimeString) {
DateTimeUtils.setCurrentMillisFixed(JodaDateTime.create(dateTimeString).getMillis());
return new Freeze();
}
public void thawAfter(Snippet snippet) {
DateTimeUtils.setCurrentMillisSystem();
}
}
public class Snippet {}
@Directi we are committed to improve the technical community in India. We started off with TechCamp. Next we launched CodeChef. And now we proudly present DesignChef.
Unlike CodeChef, which was targted at Developers, DesignChef is targeted at Design Professionals like Usability Experts, UX Specialists, Interaction Designers, Front-end developers, etc.
We welcome you to join this non-profit, community initiative and help us grow it.
Tweet This Post
Plurk This Post
Buzz This Post
Delicious This Post
Digg This Post
Ping This Post
Reddit This Post
Stumble This Post
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Fun fact: The two guys worked at a place in my old neighborhood where I got arrested and thrown into jail. Lemme give you some advice about getting arrested -- always carry 100 dollars on you in cash so you can bail yourself out. Most non-terrible offenses have a thousand dollar bail, but they'll accept 10%. The 'jail' was a bit of a let-down as it was really just a room with a locked door and a pay phone. On the plus side I got to call my Dad from 'jail.' Remember that old 'Was not was' song 'Hello dad, I'm in Jail'? Well I do.
As I start working here at 1530 Technologies, I'm starting to see just how important it is to keep usability in mind.
For example, the registration process can make or break any web application. If there are too many steps involved in getting registered and if the user is not dead-set on the product, they may lose interest. I implemented two such usability improvements on one of the apps we're working on:
Given my limited knowledge, I think these are simple usability tweaks that anybody could integrate into their page. Good Luck!
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Yeah that bike ride was kind of a harrowing adventure each morning. The only road that went directly to Object Mentor was a four laner that got lots of traffic. Could be pretty scary.
Till a year ago, I used to think of command & control as micro-management. Last year I heard Mary Poppendieck give a different perspective about it in her keynote(pdf). That’s when I realized that Command & Control means quite opposite of micro-management.
We all know Command and Control comes from US Army. During wars, the Commanders would direct (command) the troops on ground about the next move (goal/mission). And then the staff (troops) on ground would figure out the best strategy to achieve the mission. This is very different from micro-management.
Once the Commanders gives the commands, there is no way s/he can control the situation on ground. Tactical decisions are made by the staff on the war field and strategic decisions are made by Commanders and others outside the war fields, based on their knowledge about situation on the ground.
(no plan survives contact with the real enemy).
The heart of mission command:
Commanders should issue only the most essential orders. These provide general instructions outlining the principal objective and specific missions. Tactical details are left to subordinates.“The advantage which a commander thinks he can attain through continued personal intervention is largely illusory.”
http://www.dtic.mil/dticasd/sbir/sbir043/a30a.pdf
Tweet This Post
Plurk This Post
Buzz This Post
Delicious This Post
Digg This Post
Ping This Post
Reddit This Post
Stumble This Post
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
When I first started re-reading these blogs post I thought to myself: "Funny, I don't remember that we spent a lot of time fixing up the old Python wiki..." Yeah, that's because we didn't -- We burned a week working on the wrong project. I felt so stupid. However, it's an important point that when XPer's start going on and on about having an onsite (or highly available) customer you should probably listen. I've seen this situation many times since: Only person who knows what they want is totally unavailable and so the developers work on their own only to realize that they totally misunderstood the requirements. The awesome thing is that Object Mentor makes its living teaching people how to be Agile/XP and they still made the classic off-site customer mistake. This isn't to bash on them, but merely to say that when the major stakeholders are unavailable (or perceived to be so) then you're going to waste a lot of development time.
Also, Uncle Bob is a nerd's nerd. One time someone was using an old-school dial up modem in the office while he was around. Just from listening to the "scree scraa scraa" noises it made, which he casually heard from across the room while working on something else, he diagnosed some problem or other.
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
Writing a chess program for fun -- still blows my mind. I believe they had their chess programs play each other. I aspire to someday be that geeky.
There was a time I thought I would never go back to a non-refactoring IDE, but I've been using TextMate for a few years now. Although, one of the guys at work uses RubyMine and I have to say that it's coming along quite nicely. I've had my heart broken with Ruby IDEs so many times in the past that I don't know if I'll ever love again.
I'm running a give-away on my other blog. Atlassian are giving away a license for the Bamboo Continuous Integration server. There's also 10 Bamboo T-shirts up for grabs. Just write a few paragraphs about your best or worst build experiences ...
http://www.build-doctor.com/2009/06/16/atlassian-bamboo-giveaway
This summer I'm revisiting my short apprenticeship at Object Mentor. I'll be posting commentary on all my posts from the summer of 2004 exactly 5 years later to the day.
"The Simpsons: Hit and Run" is/was one of those truly great games I still think about from time to time. I wonder if I still have it... Damn! I must have sold it when I got rid of my original Xbox to that guy I met though Craigslist -- he was buying the Xbox and most of my games for his 7 year old son. Only later did it occur to me that I had a number of Grand Theft Auto titles mixed into that bundle. Oh well, that kid's gotta learn about graphic violence someday.
The 'Linked-list' moment still stands out in my brain because just before telling me "It's kinda like a linked-list," Paul had this great look on his face like he had finally thought of a super easy way to explain this concept. He was so clearly pleased with his analogy that I felt just awful fessing up that I had no idea what he was talking about. The weird thing was that, as a teacher, I was totally used to this situation -- just on the opposite side of the learning curve. But that was my job that summer: To get my mental ass kicked every day, learn from it, and come back for more.
My tour of functional programming idioms in C# 3.0 continues with some continuation tests. These two tests are equivalent:
[Test] public void ExplicitReturnStyle() { Assert.That(someObject.Identity("foo"), Is.EqualTo("foo")); } [Test] public void ContinuationPassingStyle() { someObject.Identity("foo", s => Assert.That(s, Is.EqualTo("foo"))); }
Given these two overrides of Identity:
public T Identity<T>(T foo) { return foo; } public void Identity<T>(T foo, Action<T> f) { f(foo); }
In the Continuation Passing Style Identity doesn't return a value. Return'ing is simulated by passing what comes after the function (the continuation) as a function object. In many functional languages continuations are so central to how things work that this is how you return values (and those languages are optimized for doing this). For those of you like me who grew up with the imperative children of pascal, this may be somewhat mind-bending at first. It will also likely have you saying "why would anyone do this?"
Rather than steal his entire article, go see Wes Dyer's article on the subject (where I got the identity example) for more about why one might do this outside of a language (like Scheme or Erlang) where this idiom is apparently the norm.
For even more details (including why this isn't quite CPS) see this by Don Box.
BTW, my answer to "Why do this?" is: "When it is the best way to solve the problem at hand." That I don't know when that will be yet, doesn't really concern me. I don't always learn things with a specific application in mind. Sometimes, I learn things so that when a problem arises, I have a lot of different tools in my toolbox. In other words, I am learning it because its interesting, a bunch of people smarter and more knowledgeable than me have found uses for it, and I might someday too (and I definitely won't if I don't know about it!)
Perhaps the best reason to learn this stuff is because Microsoft has put some sharp tools in the C# toolbox and I think its better to know how they work so that - even if I rarely ever take them out - I don't get cut on them while rummaging around in there.
UPDATE: For Wes's take on why it's important, see here (and really his whole series on the topic is worth the read!)
UPDATE2: If you want to take a deeper tour of these and many other functional concepts, this series of articles by Dustin Campbell goes far and wide if you follow all the links (and the links' links and so on...)
There were some exciting announcements from Apple at WWDCtoday! Being a Mac OS X user (though still chugging along with a mid-2007 Whitebook with cracks on the edges and a not-bright-enough screen) and having an iPhone (with dust creeping under the screen), I'm pretty excited about all the new announcements. Here are my initial reactions:
All-in-all, a pretty eventful WWDC. Going to Google I/O a week ago and experiencing the conference thing (and getting a free Google Ion phone in the process), I would love to go to WWDC next year and see what (Steve Jobs, hopefully) has in store for us.
Labor unions have been around for decades. They formed as a way to prevent management from treating labor unfairly and to guarantee certain rights for their members. Labor unions subsequently rose in power and began to handicap companies ability to cut costs and maximize shareholder value. In this way, they are counter capitalism, since capitalism is meant to maximize profits for it's shareholders. Now, this isn't to say that labor unions are evil or a bad idea, just that the two ideas have fundamentally opposite goals.
Unfortunately, where labor unions once were the champions of honest hard working people, they became the poster child for corruption and greed. It's no coincidence that the labor unions rose in power at the same time the Italian mafia rose in power. Now, the nefarious element has been largely removed from the unions, but the greed still exists. Ultimately, union leaders and members could not see the correlation between their increasingly skyrocketing salary, retirement and health demands and managements increased use of outsourcing. After all, nothing about capitalism requires the use of domestic labor. This has contributed to the down fall of not only companies, but entire industries and sections of the country. Nowhere is this more evident than Detroit and the auto industry. It's a shame that management and labor couldn't see the end coming and agree to make individual sacrifices for the good of everyone. This doesn't mean that the American auto industry would have been saved, but it would have made it easier to compete if people weren't making $35+ an hour for assembly line jobs. My father ran a manufacturing company for almost 20 years and in the end he was a victim of the same fate. People sweeping the floor at his company were earning $20/hr. In the end he just couldn't compete with foreign labor prices.
Chicago is going through its own labor union negotiations right now. In an effort to save 1,500 city jobs, union leaders are meeting with the mayor and his administration to come to some sort of agreement. This includes concessions on both sides, which is welcome news. It seems as though people are starting to understand that the economy is constantly changing and shifting. That is until I read this quote from the union chief:
"There's got to be assurances that, 10 years from now, these jobs that our members have are still gonna be there for them," he said.
It's amazing to think that people are still looking for 10+ year job security in such a changing environment. If you have a guaranteed job for 10 years, what incentive is there for you to change? Instead of figuring out how we can take what we have and freeze it in time to preserve it, we should be figuring out how we can better equipment the people whose jobs are going to be obsolete to tackle new jobs. One of the strange facts about the current economy is that there are thousands of jobs that are still vacant and with no supply of people filling the positions. Unfortunately, these jobs are in emerging and sometimes complex industries like IT and health care. We should be retraining people in these industries rather than trying to maintain and blue collar / assembly line economy.
while true; do wget "http://gregrluckapphelloworld.appspot.com/"; sleep 30; done;The answer is that the dead site stays down for 5 minutes (10 repetitions of my script). And no new instance gets fired up. Your whole site is down.
HTTP/1.0 200 OK Date: Tue, 16 Jun 2009 09:47:01 GMT Expires: Tue, 16 Jun 2009 09:57:01 GMT Cache-Control: public, max-age=600 Content-Type: image/jpeg Server: Google Frontend Content-Length: 237952 Connection: Keep-AliveAnother interesting thing - cache expiry is set to 10 minutes. A CDN will normally set the TTL longer and rely on a technique such as resource renaming to overcome browser cache issues.
Pascal Van Cauwenberghe has written a great post on estimating business value, tying it into a feature-injection style template. I particularly like the idea of calculating business velocity, and showing value earned over cost on a visible chart.
Even though we know that cost accounting isn’t useful without looking at ROI, many companies still have this focus (how many people have had problems getting hold of sharpies because they’re "too expensive"? Coloured post-its? Free coffee?)
Perhaps by making the return on investment over time apparent to everyone, we can motivate the team, show the value we’re earning and gain the trust of the business at the same time.
As an aside, I remember one client where the deadline was very tight, but nobody wanted to work overtime or weekends. Our PM asked us if there was anything we’d like to have which would help us work more effectively. We asked for - and got - fresh fruit every day. The difference in our work - both the amount and quality - was noticeable! (We already felt very well respected, so I discount the placebo effect here).
It’s amazing how much difference a few pounds of expense can make.