I'm trained as a nuclear and mechanical engineer. In those disciplines, there's an underlying body of knowledge and practice for design and implementation, based on a couple hundred years of experimentation and data analysis, on what works and what doesn't, and why.
Software "engineering" as it is practiced where I usually have worked, seems to be 75% gut feel and 20% anecdotal experience, with the remaining 5% subject to real analysis. I am committed to bringing at least some of the discipline of field engineering (those parts I understand well, and can adapt) to the practice of producing software.
A group of the leading lights in methodology and architecture have come together to form SEMAT -- an acronym of "Software Engineering Method and Theory", with the goal to "refound software engineering based on a solid theory, proven principles, and best practices". It would sound like so much smoke, but consider some of the signatories:
Scott Ambler
Barry Boehm
Bill Curtis
James Odell
Ivar Jacobson
Erich Gamma
The list is quite long, and luminous.
I suggest you go have a look: http://www.semat.org. I'm looking forward to finding out what Scott Ambler and Ivar Jacobson can agree on.
Friday, December 11, 2009
Wednesday, October 7, 2009
BigDecimal
Whenever you're working with money in Java, you should be using BigDecimal. There are other applications, but far and away the most common is monetary calculations. The biggest reason is accuracy: floating point values (stored using IEEE standard 754) can't represent common decimal amounts. For that, you need actual arbitrary precision math--the same kind you learned in grade school. That's what BigDecimal provides. Yes, the operations are clumsy-looking and require a lot of typing. Wouldn't you want your bank or your tax office to have full control over the precision of the values they use to calculate your interest or taxes? You owe it to your users to provide the same precision.
The problem is illustrated simply; pick any number with multipliers other than 2, store it, then print it out.
Using doubles helps, but doesn't make the problem go away--it just delays the point where you'll see a problem. The only real solution is to use arbitrary-precision math (or switch to a CPU which works in base 10 rather than base 2).
Wherever you can, make your first conversion from user input or database storage to BigDecimal using strings. The internal conversion exposes how these values are stored in the first place:
Once you have values stored as BigDecimals, keep all your math between two BigDecimal values. You don't gain anything by storing a value in BigDecimal, then multiplying it by a float or a double! You introduce the same problem by doing that that you sidestepped by moving into BigDecimal. I've seen senior developers do the following:
Given the "BD by double" result above, is this really going to produce the results you expect? By doing this, you just gave up whatever advantage you had using BigDecimal in the first place!
If you use division in BigDecimal, you're going to have to round your results. To illustrate why, consider the following:
Any calculation which results in a repeating decimal result will throw this exception. To deal with this problem, we need to discuss the relationship between "precision", "scale" and "rounding". "Precision" is the number of "significant digits" we learned about in science class in high school. The following numbers all have a precision of 4:
123.4
1234
12340
12.34
0.000001234
Unfortunately, BigDecimal has no internal concept of "precision". It stores its result as an integer of arbitrary precision, and then places the decimal point using a concept called "scale"--the number of places to the right of the decimal point. Thus, the scale of "12.34" is 2; the scale of "0.000001234" is 9. When you construct a BigDecimal with a given scale, you're reducing its precision.
In order to deal with the 'repeating' result, you're going to have to know enough about your problem domain to specify a scale, and a rounding mode to determine the result.
Rounding modes are discussed in detail in the BigDecimal javadoc, and I'll discuss them in a future entry, but for now, here's the list:
Note that "ROUND_DOWN" is the same as truncating the result, and by convention, banks and accountants uses ROUND_HALF_EVEN (and has for at least the 3 decades I've been paying attention, if not longer).
Rules for using BigDecimals are heavily tied to your problem domain, but I do have a few rules of thumb as starting places:
1. Don't round at all until you must (a) divide, (b) you have to store or output results.
2. BigDecimal conversion to and from a database should be done as strings. Hibernate, iBatis, and many other tools support this conversion easily and directly.
3. Standardize your representations early; put a small list of rounding mode/scale pairs for your application in an enumeration somewhere so they will be consistent across your application.
4. Talk frankly with your architects, designers, and requirements people about the use of arbitrary-precision math; make sure everyone is on the same page.
Using BigDecimal seems clumsy and wordy when you start. You'll develop style conventions and approaches which work if you take the plunge, and you'll have a lot more confidence in your numeric results once you do.
The problem is illustrated simply; pick any number with multipliers other than 2, store it, then print it out.
System.out.printf("float: %60.55f\n",0.35f);
float: 0.3499999940395355000000000000000000000000000000000000000
float: 0.3499999940395355000000000000000000000000000000000000000
Using doubles helps, but doesn't make the problem go away--it just delays the point where you'll see a problem. The only real solution is to use arbitrary-precision math (or switch to a CPU which works in base 10 rather than base 2).
Wherever you can, make your first conversion from user input or database storage to BigDecimal using strings. The internal conversion exposes how these values are stored in the first place:
System.out.printf("BD by string: %60.55f\n",new BigDecimal("0.35"));
System.out.printf("BD by double: %60.55f\n",new BigDecimal(0.35d));
System.out.printf("BD by float: %60.55f\n",new BigDecimal(0.35f));
BD by string: 0.3500000000000000000000000000000000000000000000000000000
BD by double: 0.3499999999999999777955395074968691915273666381835937500
BD by float: 0.3499999940395355224609375000000000000000000000000000000
System.out.printf("BD by double: %60.55f\n",new BigDecimal(0.35d));
System.out.printf("BD by float: %60.55f\n",new BigDecimal(0.35f));
BD by string: 0.3500000000000000000000000000000000000000000000000000000
BD by double: 0.3499999999999999777955395074968691915273666381835937500
BD by float: 0.3499999940395355224609375000000000000000000000000000000
Once you have values stored as BigDecimals, keep all your math between two BigDecimal values. You don't gain anything by storing a value in BigDecimal, then multiplying it by a float or a double! You introduce the same problem by doing that that you sidestepped by moving into BigDecimal. I've seen senior developers do the following:
public BigDecimal multiply(BigDecimal bd, double d){
return bd.multiply(new BigDecimal(d));
}
return bd.multiply(new BigDecimal(d));
}
Given the "BD by double" result above, is this really going to produce the results you expect? By doing this, you just gave up whatever advantage you had using BigDecimal in the first place!
If you use division in BigDecimal, you're going to have to round your results. To illustrate why, consider the following:
BigDecimal result = BigDecimal.ONE.divide(new BigDecimal("3"));
Exception in thread "main" java.lang.ArithmeticException:
Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1594)
at BDDemo.main(BDDemo.java:12)
Exception in thread "main" java.lang.ArithmeticException:
Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1594)
at BDDemo.main(BDDemo.java:12)
Any calculation which results in a repeating decimal result will throw this exception. To deal with this problem, we need to discuss the relationship between "precision", "scale" and "rounding". "Precision" is the number of "significant digits" we learned about in science class in high school. The following numbers all have a precision of 4:
123.4
1234
12340
12.34
0.000001234
Unfortunately, BigDecimal has no internal concept of "precision". It stores its result as an integer of arbitrary precision, and then places the decimal point using a concept called "scale"--the number of places to the right of the decimal point. Thus, the scale of "12.34" is 2; the scale of "0.000001234" is 9. When you construct a BigDecimal with a given scale, you're reducing its precision.
In order to deal with the 'repeating' result, you're going to have to know enough about your problem domain to specify a scale, and a rounding mode to determine the result.
Rounding modes are discussed in detail in the BigDecimal javadoc, and I'll discuss them in a future entry, but for now, here's the list:
ROUND_UP round away from zero.
ROUND_DOWN round towards zero.
ROUND_CEILING round towards positive infinity.
ROUND_FLOOR round towards negative infinity.
ROUND_HALF_DOWN round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round down.
ROUND_HALF_EVEN round towards the "nearest neighbor" unless both
neighbors are equidistant, in which case, round towards
the even neighbor.
ROUND_HALF_UP round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
ROUND_UNNECESSARY assert that the requested operation has an exact
result, hence no rounding is necessary.
ROUND_DOWN round towards zero.
ROUND_CEILING round towards positive infinity.
ROUND_FLOOR round towards negative infinity.
ROUND_HALF_DOWN round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round down.
ROUND_HALF_EVEN round towards the "nearest neighbor" unless both
neighbors are equidistant, in which case, round towards
the even neighbor.
ROUND_HALF_UP round towards "nearest neighbor" unless both
neighbors are equidistant, in which case round up.
ROUND_UNNECESSARY assert that the requested operation has an exact
result, hence no rounding is necessary.
Note that "ROUND_DOWN" is the same as truncating the result, and by convention, banks and accountants uses ROUND_HALF_EVEN (and has for at least the 3 decades I've been paying attention, if not longer).
Rules for using BigDecimals are heavily tied to your problem domain, but I do have a few rules of thumb as starting places:
1. Don't round at all until you must (a) divide, (b) you have to store or output results.
2. BigDecimal conversion to and from a database should be done as strings. Hibernate, iBatis, and many other tools support this conversion easily and directly.
3. Standardize your representations early; put a small list of rounding mode/scale pairs for your application in an enumeration somewhere so they will be consistent across your application.
4. Talk frankly with your architects, designers, and requirements people about the use of arbitrary-precision math; make sure everyone is on the same page.
Using BigDecimal seems clumsy and wordy when you start. You'll develop style conventions and approaches which work if you take the plunge, and you'll have a lot more confidence in your numeric results once you do.
Sunday, October 4, 2009
Design Constraints
Last night a bunch of us discussed the lines between architecture, design, and implementation.
I started with a working definition John Prentice gave me--heavily paraphrased, from memory: architecture is "enough design that it's clear the system requirements can be met", and design is "enough design that the path code will follow is clear". Bryan Helm suggested that architecture should also constrain design so that "good design choices will be the natural ones; bad design choices will tend to be excluded", theory being that architects tend to be senior designers as well.
There's a lot of good discussion of "what it is" on the web; I've provided some links at the end for articles I found particularly illuminating and useful.
Within the context of executable design, the group of us agreed we'd all been dealt horrible or irrelevant architectures and designs, and one hallmark of a good architecture, and also a good design, is that you could rough out code that followed the architecture, and it would execute as expected. Similarly, you could implement the design exactly, and it would execute as expected. In both cases, obviously, the system would be grossly incomplete--but the specification at the design level would be complete enough that all the functions required of the system were stubbed out and ready for detailed implementation.
I'm not sure the distinction between architecture and design is important from the point of view of a set of executable design tools. I think architecture should constrain design, and design should constrain construction. Given the way code is actually constructed, the architectural description and the design description must be maintained as the software is developed. What better way to do that than making key portions of these descriptions the armatures upon which code is developed? Code generation isn't the way to go, because you have to keep round-tripping, and you lose the abstraction provided in the design level.
The only way I can see to allow the design to constrain the construction is to use the design itself as the runtime environment for the final code. In the Java and .NET worlds, this means custom class loaders sitting between the developed code and the design, verifying conformance to the design and allowing the design to execute directly if code hasn't been provided to implement it. In this way, you can actually test the design as it is developed, in the same way you test code as it is developed: by running it.
There are many good articles; here's a jumping off point:
http://www.ibm.com/developerworks/rational/library/feb06/eeles/
http://www.bredemeyer.com/whatis.htm
http://www.itarchitect.co.uk/articles/display.asp?id=358
I started with a working definition John Prentice gave me--heavily paraphrased, from memory: architecture is "enough design that it's clear the system requirements can be met", and design is "enough design that the path code will follow is clear". Bryan Helm suggested that architecture should also constrain design so that "good design choices will be the natural ones; bad design choices will tend to be excluded", theory being that architects tend to be senior designers as well.
There's a lot of good discussion of "what it is" on the web; I've provided some links at the end for articles I found particularly illuminating and useful.
Within the context of executable design, the group of us agreed we'd all been dealt horrible or irrelevant architectures and designs, and one hallmark of a good architecture, and also a good design, is that you could rough out code that followed the architecture, and it would execute as expected. Similarly, you could implement the design exactly, and it would execute as expected. In both cases, obviously, the system would be grossly incomplete--but the specification at the design level would be complete enough that all the functions required of the system were stubbed out and ready for detailed implementation.
I'm not sure the distinction between architecture and design is important from the point of view of a set of executable design tools. I think architecture should constrain design, and design should constrain construction. Given the way code is actually constructed, the architectural description and the design description must be maintained as the software is developed. What better way to do that than making key portions of these descriptions the armatures upon which code is developed? Code generation isn't the way to go, because you have to keep round-tripping, and you lose the abstraction provided in the design level.
The only way I can see to allow the design to constrain the construction is to use the design itself as the runtime environment for the final code. In the Java and .NET worlds, this means custom class loaders sitting between the developed code and the design, verifying conformance to the design and allowing the design to execute directly if code hasn't been provided to implement it. In this way, you can actually test the design as it is developed, in the same way you test code as it is developed: by running it.
There are many good articles; here's a jumping off point:
http://www.ibm.com/developerworks/rational/library/feb06/eeles/
http://www.bredemeyer.com/whatis.htm
http://www.itarchitect.co.uk/articles/display.asp?id=358
Sunday, September 20, 2009
Agile, but...
I've heard a lot about the poor effects of "not doing Agile"--that is, doing Agile, but...
These practitioners have a set of expectations around both process and performance. The problem I have is a huge lack of comparative data. When a team is delivering software, it's the rare business that's willing to risk productivity for an experiment to answer questions like "if they can produce x per week under process y, does x decrease if we drop agile practice 'z'?".
When I joined my current project, we were being managed in a barely-recognizable devolvement from scrum. We stopped doing stand-up meetings daily about 4 months ago; we stopped doing status meetings every other day about 8 weeks ago.
Is that negative stuff? I don't have any data either way, but I don't think so. In fact, I think we could argue that we are using exactly the agile things this team needs and can use effectively:
I delivered a formal design document about 2 weeks ago, just in time to start coding for this release cycle. We don't do much formal design, though; we mostly work from a domain model, process specifications, and FitNesse tests. Sometimes, though, you need words-in-a-row and UML diagrams.
We went into code freeze last Friday, limiting check-ins to bug fixes and test fixtures. The following Monday we received several new requirements. Since code freeze, there have been updates to something like 9 process specs. Most, if not all, of those changes will be in the release. We'll probably be in code freeze for two or three weeks, which is a lot in a six-week cycle. We're treating the new requirements as bugs, and to be fair, they're about the size you'd expect from a functionality bug.
We're delivering new functionality at maybe three times the rate of most projects I've been associated with, and at probably 6 times the rate of a typical project in this organization. It's pretty high quality stuff, too, in an environment with hideously complex business rules and very high cost for failure in implementing those rules. Frankly, I'm pretty happy about that.
Here's what we've got that works:
1. very senior, very fast developers. (Plug: if they're from Gorilla Logic, as I am, they couldn't be anything else, as that's a primary focus of Gorilla Logic's hiring practice.)
2. dead quiet when it's time to concentrate. I have a private office. I'm not physically in the same state as the users. In fact, I'm two time zones away. When it's time to crank out well-thought-out results, nothing can beat quiet. (For experimental data on this topic and other key contributors to developer productivity, read "Peopleware" by DeMarco and Lister.)
3. good access to the team when it's time to talk. We have web conferencing, IM, telephones, and desktop video conferencing when we need it.
4. requirements people who aren't bound by the need to generate a document to get the requirements to us, who are highly accessible, and who know the domain quite well.
5. management who understands the importance of getting it right, and respects the professional opinions of the team.
The release will probably slip a week. When we're done, it'll be pretty much what they needed, rather than arbitrarily "what we had working on the release date". We might deliver faster with a different management style, but I wouldn't bet my next paycheck on that. If the problem domain was simple enough to allow for stable requirements, they might not need the software in the first place.
That's agile enough for me.
These practitioners have a set of expectations around both process and performance. The problem I have is a huge lack of comparative data. When a team is delivering software, it's the rare business that's willing to risk productivity for an experiment to answer questions like "if they can produce x per week under process y, does x decrease if we drop agile practice 'z'?".
When I joined my current project, we were being managed in a barely-recognizable devolvement from scrum. We stopped doing stand-up meetings daily about 4 months ago; we stopped doing status meetings every other day about 8 weeks ago.
Is that negative stuff? I don't have any data either way, but I don't think so. In fact, I think we could argue that we are using exactly the agile things this team needs and can use effectively:
I delivered a formal design document about 2 weeks ago, just in time to start coding for this release cycle. We don't do much formal design, though; we mostly work from a domain model, process specifications, and FitNesse tests. Sometimes, though, you need words-in-a-row and UML diagrams.
We went into code freeze last Friday, limiting check-ins to bug fixes and test fixtures. The following Monday we received several new requirements. Since code freeze, there have been updates to something like 9 process specs. Most, if not all, of those changes will be in the release. We'll probably be in code freeze for two or three weeks, which is a lot in a six-week cycle. We're treating the new requirements as bugs, and to be fair, they're about the size you'd expect from a functionality bug.
We're delivering new functionality at maybe three times the rate of most projects I've been associated with, and at probably 6 times the rate of a typical project in this organization. It's pretty high quality stuff, too, in an environment with hideously complex business rules and very high cost for failure in implementing those rules. Frankly, I'm pretty happy about that.
Here's what we've got that works:
1. very senior, very fast developers. (Plug: if they're from Gorilla Logic, as I am, they couldn't be anything else, as that's a primary focus of Gorilla Logic's hiring practice.)
2. dead quiet when it's time to concentrate. I have a private office. I'm not physically in the same state as the users. In fact, I'm two time zones away. When it's time to crank out well-thought-out results, nothing can beat quiet. (For experimental data on this topic and other key contributors to developer productivity, read "Peopleware" by DeMarco and Lister.)
3. good access to the team when it's time to talk. We have web conferencing, IM, telephones, and desktop video conferencing when we need it.
4. requirements people who aren't bound by the need to generate a document to get the requirements to us, who are highly accessible, and who know the domain quite well.
5. management who understands the importance of getting it right, and respects the professional opinions of the team.
The release will probably slip a week. When we're done, it'll be pretty much what they needed, rather than arbitrarily "what we had working on the release date". We might deliver faster with a different management style, but I wouldn't bet my next paycheck on that. If the problem domain was simple enough to allow for stable requirements, they might not need the software in the first place.
That's agile enough for me.
Wednesday, September 16, 2009
"Really Good Programmers"
A young designer/developer/businessman I respect and admire twittered the following today:
"Really good ruby programmers can write code that is so clever that no one less talented than them has a hope of understanding it."
He really should know better.
Really good programmers can, indeed, write code so clever that no one less talented than themselves has any hope of understanding it--but they never do. That's the sort of thing really talented coders do before they become really good programmers. And then, in the code review, their peers tell them to take out the clever bit of code and make it maintainable, thereby vastly improving the code.
A decent piece of software has a lifetime measured in tens of years. During that time, it's likely to be looked at a dozen times for new features, bug fixes, and efficiency updates--not to mention the occasional port. If it took a day to write it initially, it'll probably spend many times that under someone's lens while it's in the maintenance phase. Taking 12 hours to write clear, comprehensible code instead of 8 hours to do something clever will save time in the long run. Is it always worth the extra time? No--but it is often enough that I try to do it every single time I code something.
Strange clever code is fun to write. I write a little self-modifying routine one time, both to prove I could do it, and to solve a timing issue--I counted op-codes and found I could squeeze pattern recognition between bytes on a 19.2kbps serial connection by making the polling routine self-modifying. Nowadays I'd comment it like crazy, and advise that it be removed as soon as CPU speeds increased enough to do so. Back then I wasn't a good enough programmer to know I needed to do that. Hadn't looked at enough of my own code, incomprehensible after 5 years of "rest", to know it was important to do so.
So Jon: educate that Ruby programmer of yours. Someday he'll thank you for it. All your maintenance guys will thank you for it, and you won't have to wait for that.
"Really good ruby programmers can write code that is so clever that no one less talented than them has a hope of understanding it."
He really should know better.
Really good programmers can, indeed, write code so clever that no one less talented than themselves has any hope of understanding it--but they never do. That's the sort of thing really talented coders do before they become really good programmers. And then, in the code review, their peers tell them to take out the clever bit of code and make it maintainable, thereby vastly improving the code.
A decent piece of software has a lifetime measured in tens of years. During that time, it's likely to be looked at a dozen times for new features, bug fixes, and efficiency updates--not to mention the occasional port. If it took a day to write it initially, it'll probably spend many times that under someone's lens while it's in the maintenance phase. Taking 12 hours to write clear, comprehensible code instead of 8 hours to do something clever will save time in the long run. Is it always worth the extra time? No--but it is often enough that I try to do it every single time I code something.
Strange clever code is fun to write. I write a little self-modifying routine one time, both to prove I could do it, and to solve a timing issue--I counted op-codes and found I could squeeze pattern recognition between bytes on a 19.2kbps serial connection by making the polling routine self-modifying. Nowadays I'd comment it like crazy, and advise that it be removed as soon as CPU speeds increased enough to do so. Back then I wasn't a good enough programmer to know I needed to do that. Hadn't looked at enough of my own code, incomprehensible after 5 years of "rest", to know it was important to do so.
So Jon: educate that Ruby programmer of yours. Someday he'll thank you for it. All your maintenance guys will thank you for it, and you won't have to wait for that.
Wednesday, September 9, 2009
architecture by accident
I’ve been on a number of projects with a common problem set:
The introduction to Booch/Rumbaugh/Jacobson "The Unified Modeling Language User Guide" makes the case for design modeling thusly:
"If you want to build a dog house, you can pretty much start with a pile of lumber, some nails, and a few basic tools...
"If you want to build a house for your family, you can start with a pile of lumber, some nails, and a few basic tools, but it's going to take you a lot longer, and your family will certainly be more demanding than the dog. ...
"If you want to build a high-rise office building, it would be infinitely stupid for you to start with a big pile of lumber, some nails, and a few basic tools. ... You will want to do extensive planning, because the cost of failure is high. ...
"Curiously, a lot of software development organizations start out by wanting to build high rises but approach the problem as if they were knocking out a dog house."
(The full text is entertaining; go forth and read the whole thing.)
As a developer, there are a couple of approaches I use to at least try to address this:
Design is key to success in anything but the smallest projects. I use "success" very carefully here; some more recommended reading:
http://thedailywtf.com/Articles/What_Could_Possibly_Be_Worse_Than_Failure_0×3f_.aspx
"When an enterprise software application is deployed to production, it’s almost universally considered to be a success. In most other industries, equating completion and success would be ludicrous. After all, few in the construction industry would deem a two-year-old house with a leaky roof and a shifting foundation anything but a disaster — and an outright liability.
"Yet, had the VCF system gone live, almost everyone involved — from the business analysts to the programmers to the project managers — would have called their work a success. Even after the code devolved into an unsustainable mess, many would still refuse to admit that they had failed. The result is a cycle of failure, as dev shops refuse to recognize and correct issues that plague their projects."
- architecture is deteriorating with time, and was never strong to begin with
- there is no architect or designer with project-wide authority
- nobody views this as a problem–including the development team
- time to add a feature is increasing
- quality issues continually surface as new features affect older ones
The introduction to Booch/Rumbaugh/Jacobson "The Unified Modeling Language User Guide" makes the case for design modeling thusly:
"If you want to build a dog house, you can pretty much start with a pile of lumber, some nails, and a few basic tools...
"If you want to build a house for your family, you can start with a pile of lumber, some nails, and a few basic tools, but it's going to take you a lot longer, and your family will certainly be more demanding than the dog. ...
"If you want to build a high-rise office building, it would be infinitely stupid for you to start with a big pile of lumber, some nails, and a few basic tools. ... You will want to do extensive planning, because the cost of failure is high. ...
"Curiously, a lot of software development organizations start out by wanting to build high rises but approach the problem as if they were knocking out a dog house."
(The full text is entertaining; go forth and read the whole thing.)
As a developer, there are a couple of approaches I use to at least try to address this:
- When adding new features myself, try to talk with everyone with code touching mine. Often there is a conceptual design in each area's designer's mind--there just is no globally-available expression of it.
- I document my own designs with diagrams and written discussion, which I pass around for comment. I try to include global information about the global concept objects I touch. This has the effect of (often) flushing out different views of the responsibilities and limitations of key objects.
- I transfer design information into javadoc, so the next developer can see it as (s)he codes.
Design is key to success in anything but the smallest projects. I use "success" very carefully here; some more recommended reading:
http://thedailywtf.com/Articles/What_Could_Possibly_Be_Worse_Than_Failure_0×3f_.aspx
"When an enterprise software application is deployed to production, it’s almost universally considered to be a success. In most other industries, equating completion and success would be ludicrous. After all, few in the construction industry would deem a two-year-old house with a leaky roof and a shifting foundation anything but a disaster — and an outright liability.
"Yet, had the VCF system gone live, almost everyone involved — from the business analysts to the programmers to the project managers — would have called their work a success. Even after the code devolved into an unsustainable mess, many would still refuse to admit that they had failed. The result is a cycle of failure, as dev shops refuse to recognize and correct issues that plague their projects."
Wednesday, July 15, 2009
FlexMonkey: test automation for Adobe Flex
I'm a real fan of automated testing. I really don't understand the idea of teams of people driving a UI as a way of regression testing, though there are certainly a lot of major products out there which use exactly that method to test. I think one big reason for that is that user interfaces which aren't written in HTML are notoriously hard to regression test.
A lot of what we do at Gorilla Logic is Flex atop Java. As a result of that, we had to find a way to regression test Flex user interfaces; it's not really practical for an agile team to survive without automated regression testing. Enter FlexMonkey. FlexMonkey was developed and offered to the community in open source as THE way to do regression testing for Flex, and having seen it in action, I have to say I'm really impressed. It's easy to get started with, easy to use, and easy to fully automate. The documentation is enterprise-grade, and best of all, it's free. It took me about half an hour to get it running and automated under ant, and I've never coded in Flex.
So go check it out: FlexMonkey 1.0 released in Google Code (open source) yesterday. http://flexmonkey.gorillalogic.com/gl/stuff.flexmonkey.html.
Here's a bit more about Flex and what we do at Gorilla Logic: http://www.gorillalogic.com/what.development.services.flex.html.
A lot of what we do at Gorilla Logic is Flex atop Java. As a result of that, we had to find a way to regression test Flex user interfaces; it's not really practical for an agile team to survive without automated regression testing. Enter FlexMonkey. FlexMonkey was developed and offered to the community in open source as THE way to do regression testing for Flex, and having seen it in action, I have to say I'm really impressed. It's easy to get started with, easy to use, and easy to fully automate. The documentation is enterprise-grade, and best of all, it's free. It took me about half an hour to get it running and automated under ant, and I've never coded in Flex.
So go check it out: FlexMonkey 1.0 released in Google Code (open source) yesterday. http://flexmonkey.gorillalogic.com/gl/stuff.flexmonkey.html.
Here's a bit more about Flex and what we do at Gorilla Logic: http://www.gorillalogic.com/what.development.services.flex.html.
Subscribe to:
Posts (Atom)
