text:
A Business Fable
Once upon a time a boy went to business school. The boy was not sure he wanted to go into business, because what he most loved was writing stories about aliens and monsters and girls who did not love him back. But he knew he could not hope to earn a living from such stories, so business school it was.
The boy learned many interesting things, until he began to think perhaps business was for him after all. One day, he attended a class in which students were divided into groups and asked by the lecturer to solve the following puzzle:
"A man buys a horse for $400. He feeds it, trains it, and sells it to a racetrack manager for $500. However, soon he regrets his decision, and asks the racetrack manager if he can have the horse back. The racetrack manager, being a good capitalist, asks for $700. The man objects, seeing no reason why the horse should be worth so much more than the day before, but eventually he relents and accepts the loss. Some years later, he finally sells the horse to neighbor for $800. Question: What is his total profit or loss?"
The boy's group began to discuss this puzzle. The boy thought the solution was fairly obvious: the man bought and sold the horse twice, making $100 profit each time. However, his teammates were seduced by the puzzle's suggestion of a loss, and insisted this be accounted for. They thought the man broke even.
The boy tried to explain his reasoning a different way. He added up the man's outlays and revenues, showing the difference was $200. The group agreed, but insisted this was then canceled out by the loss. The boy tried again. "Imagine it's not the same horse," he said. "The man buys and sells one horse, then buys and sells a second horse." The debate became heated. There was no second horse, the group insisted. There was one horse, and the man broke even.
After a few minutes, the lecturer halted the exercise and asked each group for its verdict. Only unanimous decisions would be accepted. Every other group in the class declared their belief that the man broke even. The boy's group hissed at him to bow to the majority opinion, but he could not bring himself to do it. They informed the lecturer that they could not agree.
The answer, said the lecturer, was that the man made $200 profit. However, the exercise was not about that. It was designed to test teamwork. He had observed most groups working effectively: establishing leadership roles, managing divergent opinion, and finding common ground to reach a shared solution. The boy's team, however, was a textbook example of failure: it had allowed a disruptive element to block them from consensus. It was then that the boy decided business was probably not for him.


text:
Northland Septic provides residential and commercial septic services in Laporte, including septic design, septic installation, septic pumping, septic system repair, drain cleaning, waste hauling and compliance inspection. Count on us for all of your Laporte sewer and septic needs.
From septic system installation in Laporte to maintenance, rentals, repairs, our team of highly trained professionals has the equipment and expertise necessary to provide you with unparalleled efficiency and service. Septic services in Laporte include:
If you are experiencing any of these issues, please contact Northland today. These symptoms may indicate a failure in your septic system, which cause serious problems if not repaired. Common problems include:
For Residential permit applications in Laporte, MN, please visit the city website at http://www.laportemn.com/
Thank you so much for your help and great service! What nice guys!
Northland Septic Maintenance Inc.
4207 16th Street NW
Backus, MN 56435
Main Phone: 888.454.4999

subset: commoncrawl


text:
Neon Genesis Evangelion Platinum Collection
The story of Neon Genesis Evangelion goes back to the year 2000, when a global catastrophe known as the "Second Impact" occurred. During this event, Antarctica was destroyed, and half of the human population of Earth was wiped out. The government announced that the cause of the disaster was due to a large meteorite landing on Antarctica. However, it turns out the "Second Impact" was caused by experiments authorized by an organization called Seele; the experiments were actually done by a research organization called Gehirn. They were experimenting on "beings" that are referred to as Angels and Adam.
Ten years later, Gehrin evolved into a paramilitary organization called Nerv, which is located in Tokyo-3, a militarized civilian city located in one of the last dry areas of Japan. Seele has given Nerv the mission to locate the remaining Angels and destroy them, and accomplishing this through developing biomechanical mecha called Evas. Each Eva has its own designated pilot, and operates by synchronizing the pilot's soul and the human soul inside the Eva. This is done by using a liquid substance known as LCL.
The series itself actually begins in 2015, when Tokyo-3 is under attack by a third Angel. Conventional weapons are useless, so Nerv takes control of the battle. Nerv decides to use the Evas against the Angel. Meanwhile, Commander Ikari's 14-year-old son, Shinji Ikari, arrives in Tokyo-3 right as the Angel starts to attack the area.
It turns out Commander Ikari (who hasn't seen his son in three years), has summoned Shinji to serve as a pilot for one of the Evas. Shinji, however, suffers from anxiety, depression, lack of self esteem, and loneliness. As the Angel starts to attack the area near the Geofront, Shinji ends up reluctantly agreeing to pilot Evangelion Unit 01. Over the course of the series, two other pilots are important: Rei Ayanami and Asuka Sohryu Langley.
Neon Genesis Evangelion seems to start out normally enough, but as the series progresses, the viewer comes to realize there's a lot more going than there appears on the surface. By the end of the series, there's been a serious look at the psyches of all three of the main Eva pilots.
When it comes to this set, each disc allows you to choose which language you want: English or Japanese with English subtitles. The only disc in the set that has anything other than episodes is the first disc. In addition to the first five episodes, this disc includes DVD credits and "ADV Previews" (which includes six trailers for other anime being released by ADV at the time this set was released). The second, third, and fourth discs contain five episodes each. The fifth disc contains six episodes, and the sixth disc contains the "Director's Cut" versions of episodes 21 through 24.
One of the best things about this set is the fact that it collects all 26 episodes, as well as the four "Director's Cut" episodes, into one collection; this is much more convenient than having to buy the nine single DVDs that needed to be purchased before this set was released. However, the downside is that ADV decided to make this box set a "bare bones" release; they didn't even try to include the character profiles from the eight single discs of the main series, or any of the extras from the single disc release of the "Director's Cut" episodes.
If you're wanting to add Neon Genesis Evangelion to your anime collection, the Platinum Collection is the best way to go, even though there's not much in the way of extras. However, both this set, as well as the DVD singles, are out of print. Check out various used DVD sellers, and try to find the best deal that you can for this set.
|Angel Attack
The Beast
A Transfer
Hedgehog's Dilemma
Rei I
Bonus Features
|Rei II
A Human Work
Asuka Strikes!
Both of You, Dance Like You Want to Win!
Magma Diver
|The Day Tokyo-3 Stood Still
She Said, "Don't Make Others Suffer for Your Personal Hatred."
Lilliputian Hitcher
Weaving A Story
Those Women Longed for the Touch of Others' Lips, and Thus Invited Their Kisses
|Splitting of the Breast
Fourth Child
Weaving a Story 2: Oral Stage
|He Was Aware That He Was Still a Child
Don't Be.
Rei III
The Beginning and the End, or "Knockin' on Heaven's Door"
Do You Love Me?
Take Care of Yourself
|He Was Aware That He Was Still a Child [Director's Cut]
Don't Be. [Director's Cut]
Rei III [Director's Cut]
The Beginning and the End, or "Knockin' on Heaven's Door" [Director's Cut]
This site needs an editor - click to learn more!
You Should Also Read:
Neon Genesis Evangelion
The End of Evangelion
Neon Genesis Evangelion Death & Rebirth
Related Articles
Editor's Picks Articles
Top Ten Articles
Previous Features
Site Map
Content copyright © 2019 by Lesley Aeschliman. All rights reserved.
This content was written by Lesley Aeschliman. If you wish to use this content in any manner, you need written permission. Contact BellaOnline Administration for details.


text:
Volunteers are the backbone of football clubs. Meet new people and become engaged in the community by volunteering within a football club or umpiring group. Clubs are always looking for volunteers to assist them and there are endless roles that can be filled.
See volunteer roles and responsiblities
Become a volunteer by searching the Club Locator below and getting in contact with your local club.
Alternatively, you can complete the volunteer enquiry form below and the relevant state manager will provide you with a list of clubs in your area that you may wish to volunteer with.


text: OCEAN SPRINGS — Long Beach High School students will compete for a national title in ocean science knowledge after beating 21 other teams from five states. Mississippi teams took four of the top five places out of 22 teams from Alabama, the Florida Panhandle, Louisiana, Mississippi, and Tennessee. Officials said it was the biggest group of Hurricane Bowl contestants since ...Read More »


text:
In memoriam: Dr. Roger Long, retired Asian theatre professorUniversity of Hawaiʻi at Mānoa
Chancellor's Office
HONOLULU - Roger Long, former Associate Dean of Arts and Humanities and emeritus professor of Asian Theatre at the University of Hawaii at Manoa, died early Monday.
Dr. Long was on the Manoa faculty from 1976 until his retirement in 2004, teaching classes in Southeast Asian Theatre, Contemporary Asian Dramatic Literature, and Asian acting for the Western actor. In addition to serving 10 years as associate dean of the College of Arts and Humanities, Dr. Long was also past chair of the Department of Theatre and Dance, and of the Southeast Asian Studies Program.
He directed and produced many performances at Kennedy Theatre and Manoa Valley Theatre, including Angels in America: Part 1 and Balinese Kecak. He received his doctorate in philosophy from UH Manoa in 1979. Several years ago, Dr. Long established four endowments at the College of Arts and Humanities at UH Manoa in support of specific theatre, dance, and music programs.
"The passing of Dr. Long is a deep loss for the University of Hawaii and our community because of his tremendous impact on the performing arts as a teacher, director and patron," said Interim Chancellor Denise Konan.
Dr. Long also founded the college's "Study ALMOST Abroad" program, designed to bring students from mainland campuses to UHM for one semester to take courses not available at their home campuses. Originally developed for theatre students to experience the rich Asian theatre offerings at UHM, it rapidly expanded to many other areas in which UHM has outstanding classes.
There will be a celebration of Dr. Long's life at Kennedy Theatre, at a date and time to be announced.
For more information, visit: http://www.hawaii.edu/theatre/index.htm


text:
Updated 2:05 p.m. ET, 8/26/2014
Charlotte (CNN) – President Barack Obama detailed Tuesday how his administration is attempting to rectify shortfalls in caring for war veterans, just as new threats abroad could require more sacrifices for American military families.
Speaking at the annual American Legion conference in Charlotte, Obama announced new executive actions aimed at improving mental health services and financial opportunities for servicemen and women, months after allegations of massive wrongdoing surfaced at the Department of Veterans Affairs.
Follow @politicaltickerFollow @KevinLiptakCNN
His remarks came as the United States contemplates further action to stem the expansion of ISIS in Iraq and Syria, including airstrikes. The President declared in front of roughly 7,000 legionnaires in Charlotte on Tuesday he was ready to "take direct action where needed to protect our people and to defend our homeland," but added that under no circumstances would American combat troops return to Iraq.
"Rooting out a cancer like ISIL won't be easy, and it won't be quick," Obama said, using the administration's name for the terrorist group which last week beheaded an American freelance journalist, James Foley.
"Our message to anyone who harms our people is simple: America does not forget our reach is long. We are patient. Justice will be done," he said.
The actions to improve veterans care Obama announced Tuesday included expanding research into post-traumatic stress disorder and brain injuries, developing ways to prevent suicide among veterans, and making it easier for veterans to transition into mental health services provided by civilian doctors or the VA after leaving active duty.
The President also announced new partnerships with financial lenders to make it easier for veterans to negotiate lower mortgage and student loan interest rates.
The systemic problems within the veterans' department led to the resignation of Eric Shinseki, a retired Army general who had headed the troubled agency since Obama took office in 2009. The American Legion, whose annual conference Obama spoke at Tuesday, was among several veterans groups calling for Shinseki to step down.
His replacement, former corporate chief Robert McDonald, was approved unanimously by the Senate at the end of July. Lawmakers also green-lighted $16 billion in new funding to build more VA facilities and hire more workers, though some said the measure didn't do enough to criminalize the wrongdoing at the agency.
Obama on Tuesday said revelations veterans waited months for care while managers attempted to cover it up were "outrageous and inexcusable."
"We're focused on this at the highest levels," Obama told the American Legion crowd. "We are going to get to the bottom of these problems. We're going to fix what is wrong. We're going to do right by you. And we are going to do right by your families. And that is a solemn pledge and commitment that I'm making to you here."
His appearance in North Carolina comes as that state's incumbent Democratic Sen. Kay Hagan faces a tough battle for re-election. Attacks by her Republican rival heavily feature her support for some of Obama's more controversial programs.
It was initially unclear whether Obama and Hagan would appear together Tuesday. She greeted Obama with a hug and a kiss on the cheek on the tarmac after Air Force One's arrival. She also spoke after him on the American Legion stage.
But before their friendly encounter, Hagan released a statement saying Obama's administration hasn't yet done enough to regain the trust of veterans after the agency scandal.
"Thanks to the cut and run Democrats, the incompetence of Obama and Hillary, we are now in a mess that could have been prevented. They both the supported the big "Arab Spring"… and the Middle east is under the control of radical Muslims…..
If you watched the President's speech, the attendees were very polite. They know a crock of crap when they hear it…. But as good Troopers, they respected the Office…..
Bush and Cheney were wrong… we should have never gone into Iraq… We should have concentrated on Afghanistan….. After being in Iraq and Afghanistan three times each, I have the right to say that…."
I'm a bit confused here, first you write... "Thanks to the cut and run Democrats, the incompetence of Obama and Hillary...", then later you write... "Bush and Cheney were wrong… we should have never gone into Iraq…"; am I to take away from this that we should have stayed in Iraq despite your (and everyone else's) assessment it was a mistake? If you think your neighbor kidnapped your child, so you kick in the door only to find you were 100% incorrect, you should still not leave his home (based on some he-man principle I was never taught, I presume)?
If we made a huge mistake (and we did) the only way to fix it would be to immediately take steps upon realizing our mistake to correct it (i.e. leave the country we invaded without just cause- same goes for Afghanistan as far as I am concerned). For you to describe Democrats, for their correcting the egregious errors of bush/cheney, as 'cut and run' is disingenuous at best... cowardly at worst.
If you truly served... thank you for your service, but I cannot agree with your obvious partisan opinion.
What Obama did was right and it was a long time coming. It was one of his campaign promises, he kept it, and I for one applaud him for it. If we were all to get our panties in a wad every time some righty trotted our their version of 'How Obama ruined my Country' (which apparently there was a choice between that and 'What I did this Summer' as the Sophomore essay) we'd all be walking around funny... luckily, I belong to the 'We don't get our patnies in a wad, we point and laugh at those who do... Party'.
If you'd like to join, we have plenty of room in our tent. We don't have purity tests and free thinking isn't just encouraged, it is expected. We are unorganized and not always on the same page... but we are relentless in our fight for 'liberty and justice for ALL' (so many people forget that crucial last part).
"Cut and run" describes Rand Paul's exit strategy when confronted with immigrants and burgers.
The tepid applause Obama got tells it all. Funny how the drones say no scandal when both the IRS and VA officials apologized for their incompetence and corruption. Then the press goes in full defense mode for Obama and now nothing was done wrong. All made up. All faux scandals. Blah, blah blah. So why did they apologize for something they "never" did and was made up? Keep drinking the Koolaide drones.
ISIL is not the 'administrations name' for the dangerous off-shoot of al-Qaeda! It is UN terminology! ISIS refers to Iraq & Syria, while ISIL refers to this groups efforts to take over all Islamic nations! Saying it's the administration's name makes it sound like it was something they made up, it's a bit of an insult! But that's par for the course in this contrary political climate for this president!!
This is all a lie – thousands, perhaps a million vets, have died because of President Obama and the VA.
People – listen to us Tea Partiers – don't believe the press, the media, especially not the scientists.
And where is His Birth Certificate? Huh? I haven't seen it, so the last 7 years didn't really count. Mitt Romney was really President, and he is doing a good job.
sly – You made the best post today.
@DM40-Actually the numbers I posted leave questions as well. First, I shoudn`t have put the word cut in my comment because the 3936 is the minus difference from 2009 to 2013 in the four branches. Second, what about new recruits from 2009 to 2013? Third, What about the service members changing status from active to reserve or vice versa. Last, we know the cuts have been made and in 2009 the Deparment of the Navy introduced PTS(which is a set standards to meet to reenlist) to the Navy and Marines. Since 2009 there is a minus 12,000 difference from those two branches. The Air Force has seen a surge of over plus 7,000 since 2009 and little change in the Army.
Dean is wrong again.
What this country has become is a place where vets are ignored and medical care (and everything else) is given to the refuse dumped here from central America
Talk,talk,talk more talk,do nothing,more talk.
@sly – This is all a lie – thousands, perhaps a million vets, have died because of President Obama and the VA.
Get a grip Charlie.. the problems at the VA have as much to do with Obama as they did with Dubya. Zip!!
The VA problems are systemic, and had you been alive during the Johnson thru Reagan era's, you'd know not much has changed.
The defense mode by the press is due to the fact that the right wing propaganda is totally unsubstantiated, and the faux outrage is due to your Party becoming irrelevant and to be honest, it's gotten REALLY OLD!
The IRS did their job (over-zealously maybe) but not under the direction of the WH (much as it pains the right) and with no more targeting of conservative than liberal groups. Issa's witch hunt would be DOA had he granted Lerner immunity, but he can't do that or the parties over honey!
Intelligent Americans realize that the GOP has been after the current occupant since day one in office. They have failed miserably and for the last FIVE yrs have been acting like the kids that started the house fire, then sat on the other side of the street criticizing how the fire dept is going about putting it out.
@willhaas – Our President just loves to travel at the tax payers expenxe and add CO2 to the atmosphere. He did not have to go to Charlotte to give thispeechch. He could have given it at the White House and the media would have broadcast it all over the world.
haha.. had he done that from the WH you'd be whining about how he's above the vets, and should have traveled there in person.... meanwhile you expend additional flatulence into the atmosphere!
So a veteran develops a non-service related medical condition (diabetes, cancer, ALS, you name it) and the VA treats this non-service related illness for free? What a bunch of hooey. These same vets are probably also the same critics who denounce welfare for civilians. What's the difference. Id the vet got his/her medical condition while in the service, the taxpayer should rightly pay. For non-service related medical conditions, the vets can get in line with the rest of the unwashed. This is the largest welfare scam in the world. Get a pimple on yer butt and expect the taxpayer to pay because once upon a time you were in he service I don't think so!.
Why is it that on one of the busiest boulevards Veterans Memorial Boulevard with a large American Flag that it is extremely dangerous to walk and shop. Handicapped people could not possible use when someone who is not finds it very hard to manuever? Apparently i
I'm constantly amazed at how the executive branch will saddle up Air Force 1 and in this case take a flight to Charlotte NC to do a short speech at the American Legion convention, then jet right back to DC. With the fantastic video conferencing technology available now why couldn't the President give his speech that way? I'd reckon several million dollars spent to support squads of Secret Service Agents, transporting two "Beast" Presidential Limos to Charlotte and back to DC, driving a small fleet of Secret Service chase cars, escort vehicles and SWAT transports to Charlotte and back to DC and all the attendant per diem for the supporting cast to arrive early, stay several days (or a week or more for the advance team) and return to DC... Ridiculous!
"The tepid applause Obama got tells it all. Funny how the drones say no scandal when both the IRS and VA officials apologized for their incompetence and corruption. Then the press goes in full defense mode for Obama and now nothing was done wrong. All made up. All faux scandals. Blah, blah blah. So why did they apologize for something they "never" did and was made up? Keep drinking the Koolaide drones."
Oh, I don't think anyone on the left has ever claimed nothing was wrong... they just aren't willing to hand over Obama to the issus inquisition board to be water boarded and have bamboo slivers put under his finger nails until he confesses to being born in Kenyan, to having singlehandely caused the Hindenburg to explode, to have sank the Maine, and all the other whacky 'scandals' you and your ilk pull out of your arses on a daily basis.
I got an idea... why don't you all impeach him? The Constitution allows for the House, (which your whacko birds fully control) to impeach President Obama.
So why don't ya'll just impeach him if he has broken so many laws and been directly pulling the strings of every scandal created in hannity writing room since day one?
You don't because you know what that would lead to. Even you brain dead lackeys have enough brain cells (and faux news is NOT telling you to do this, or else you'd be on here whining to do it daily) to realize that would be the last straw for the American people and the backlash would likely deliver us the House; gerrymandering or not.
I willl give you rubes that.... so far you have not been stoopid enough to repeat that mistake (but, I still have hopes cruz or some other idiot will get you fired up to do it (but, you won't... not until faux or rush or the koch masters tell you to).
I think your hopes would then lie solely in boner's leadership...
and I can't tell you how much that makes me smile.
@The REAL Truth...
@sly – This is all a lie – thousands, perhaps a million vets, have died because of President Obama and the VA.
Get a grip Charlie.. the problems at the VA have as much to do with Obama as they did with Dubya. Zip!!
You might want to go back and read this with your tongue firmly planted in your cheek....


text:
Article content
Sports organizations have never cared much for being socially aware, socially active and, more importantly, socially responsible.
For as large a part that sports are of the social fabric, organizations and in many ways their fans would rather believe they survive on an island where they live by their rules, their morals and their value system.
These organizations believe that responsibilities, as part of the global picture, belong to someone else. They exist in a toy department, where reality doesn't exist.
When you attempt to impose the rules everyone else lives by or when you plead for governing bodies of sports to acknowledge they have deeper responsibilities, the cry of "Leave us alone, we are sports" is keened to the high heavens.
It is an embarrassment that can no longer be tolerated.
How difficult is it for organizations like the IOC and FIFA, governing body for international soccer, to change their way of thinking?
It is virtually impossible.
Check the numbers. Russia spent $50 billion on the Olympics.
It is also difficult for millions of fans of sports to commit to a new line of thinking because for them, the spectacle is everything.
For the IOC and FIFA, any kind of change to a more responsible way of selecting countries and limiting the cost of an Olympics or World Cup is anathema to how they operate.
It's about money, sponsorships, individual gratuities and rewards promised and delivered.
To throw a social component into the mix of selection process or restraint would simply complicate the issue of finding the money. Human rights, poverty and fairness in labour practices have a way of denting the pocketbook.
We won't even get into the fact the Olympics have become nothing more than a massive jingoist orgasm for major nations to prove whose is bigger. Nations love that.
Does anyone else find it incredibly coincidental that the 2014 Winter Olympics are in Russia, the 2018 World Cup is in Russia, the 2014 World Cup is in Brazil and the 2016 Summer Olympics are in Brazil?
The social and human rights issues in these countries, not the least of which is poverty, is extraordinary, yet FIFA and the IOC somehow handed these countries not one, but two major events.
It has never been FIFA policy to name the location of a World Cup more than six years before the event. Yet the 2022 World Cup has already been awarded to Qatar. Why?
Here's just a hint of what FIFA ignored to award the World Cup to Qatar.
The most obvious is the lack of individual rights for gays and women.
The tournament is supposed to be held in summer, when temperatures reach more than 45 C.
Recent official figures show that 185 Nepalese men died last year in Qatar, and the International Trade Union Confederation has warned that up to 4,000 workers could perish before the 2022 World Cup begins, if there are no meaningful reforms to working conditions. Slave labour is building World Cup facilities.
The IOC, FIFA, participating nations, the media, all say the right words about how horrified they are. But it's all words.
Countries love to brag about how good their athletes are and the media, well the media loves covering these events and are often the leader in jingoism and complaints when their food isn't just right.
It is possible to make a difference. You can't expect it from organizations like FIFA or the IOC to make any significant changes. They are the epitome of the old boys' network Changes could be made, but developed nations would have to put aside their own special interests. Most of those nations stepped up in helping to bring down apartheid.
Sponsors would have to step up and refuse to sponsor major events that go to nations with a history of human rights violations.
We know that's not going to happen yet.
But it will because somewhere down the line the World Cup or the Summer Olympics will explode in Brazil or Russia. Riots will happen and dozens will die.
It may not be this year or in two years, but it will happen.
Then, no matter how much we try, we won't be able to deny our solid silver tournaments are really nothing more than silver plated.


text:
Prodim International is the maker of the acclaimed Proliner 3d/2d measuring device. The mechanical wire measuring mechanism that is attached to a pen, allows the user to capture both 2d and 3d polylines in a matter of seconds. The onboard touch screen allows the user to instantly view and edit the drawing file. You are then able to transfer the DXF/CCD via a USB flash drive directly into your cad/cam system.
Originally designed for the rapid measurements of hulls in the marine industry the Proliner has found its way into a multitude of applications. Prodim is dedicated to meeting the needs of several companies around the world and has different models including 3d lasers and industry specific software to help facilitate production.
Proliner Digital Measurement Solutions
Jake Hasseler, Prodim USA


text:
We knew the Chanel entitled its Spring/Summer 2014 collection "art" but taking one look at the decor, and it's clear Karl took it to the next level. Set in an all-white gallery setting, the walls were covered with Chanel-inspired canvases and sculptures. When I first saw it, my jaw dropped and I thought, I want all of it — and that's before I even saw the fashion!
Photo by Olivier Sailant for Chanel


text:
The Importance of Seeking Advice
The 24-year old boy studying in a yeshiva in Israel was anxious to get started on shidduchim since almost everyone of his peers was already married. His only obstacle was an older brother back in the States who was still unmarried.
His high hopes for a breakthrough in the situation through a shidduch in which his brother was involved were dashed when a call came from home that once again nothing had come of this attempt to find a marriage partner. He then began to seriously consider passing up his brother despite the pain this might cause him. When he finally decided to do so he phoned his parents to inform them. His father's reaction was to inquire whether he had asked a rosh yeshiva's advice on the matter. Although he was absolutely confident that he would receive confirmation of his decision, he consented to immediately seek his advice.
Since his own rosh yeshiva was officiating at a wedding out of town and he was anxious to fulfill his promise to his father, he decided to consult the head of a yeshiva not far away from his own. After hearing his situation the rosh yeshiva said it was permissible for him to pass up his brother but also asked him for some details about that brother's personality and what type of girl he was looking for. Upon hearing his description the rosh yeshiva told him that he knew a family in the States whose daughter would be an ideal match and gave him their telephone number.
The happy ending was that the older brother became engaged to that girl and our hero's problem was solved by heeding his father's advice to seek advice.


text:
Not to be confused with the movie, the book version of The Fellowship of the Ring includes several scenes with the mysterious, and quite possibly brain damaged, Tom Bombadil.
On the positive side, Tom saves the hapless hobbits twice: first from Old Man Willow, an ancient and malevolent tree that lives on a toxic mix of Highballs and lost Halflings; and then, from a number of barrow-wights, evil soul-sucking undead creatures, not to be confused with Barry Wights, who are excellent, soulful (and unfortunately regular dead) singers of sexy songs.
Speaking of song, Tom spends much of his time in a whimsical and poetic dreamscape of his own construction, singing as he passes blithely through the Old Wood. Tolkien tells us that he dresses in yellow boots and a blue jacket, leaving one to wonder if the author just forgot to mention if Tom was wearing pants, or if he is simply glossing over the lack of pants. I suspect that latter, because he does tell us that Tom has a long brown beard, bright blue eyes, and an extremely red face.
Red face? Is Tolkien suggesting Tom is an alcoholic? It's hard to say. He acts kind of inebriated, given his propensity to speak in the bizarre poetry of a metre that is at best unconventional, and at worst, deranged. He also likes to talk about himself in the third person. This does not seem to annoy his wife, Goldberry. (Who may or may not be the spirit of the river Withywindle, but who is definitely some kind of saint for putting up with this narcissistic and enigmatic half-wit.)
Bombadil is totally unaffected by the Ring, and he demonstrates this by doing a little sleight-of-hand, taking the ring from Frodo, and making it disappear in the air. (I suspect he palms it, but again, Tolkien does not tell us directly.) The One Ring doesn't make him invisible, and he doesn't seem to be influenced by Sauron through it.
So why don't they just keep the ring hidden with Tom? It would have saved Frodo a painful stab-wound, massive existential angst, and having to endure Sam's repeated attempts at innuendo, by suggesting that he could really go for a nice bit of "cony stew."
Apart from the fact, that, hey, no trilogy, Gandalf suggests that because Tom is unaffected by the ring, he would probably not consider it important enough to protect. That's a nice way of saying he's a flighty (possibly pantsless) wanker.
Speaking of Goodreads, you can win a copy of my new book, Pirate Therapy & Other Cures, in a giveaway that ends May 15.
Add me as a friend while you're there!


text: To create a Playbook.gg account, you'll need to log in or sign up with Twitch first.The Curse Media sites and services, including your contract with us regarding the provision of Curse Media sites and services, will soon be transferred to Fandom, and all of your personal data will be transferred to Fandom as part of that process to the extent related to Curse Media. Your existing relationship with Twitch in connection with other Twitch Services will not be impacted by this transfer. For more information, click here.For users in the European Economic Area, by logging into an account which was deleted during our transition to Fandom (Wikia, Inc.), you are providing consent for your account terms and associated personal data to be transferred to Fandom and for Fandom to process that information in connection with our Privacy Policy.


text:
You know, the gang at VSoft, led by Vince Parrett, have really contributed a lot to the Delphi and the Developer community. First, they built FinalBuilder – probably one of the best known apps built with Delphi -- and now ContinuaCI for all developers. And being Delphi developers, they have contributed the DelphiMocks and DUnitX frameworks to the Delphi community. Recently, they added another little gem to that list – TCommandLineParser.
It's seems less common than it used to be with "regular" applications, but command line switches certain remain popular and common with console applications. They are used to pass filenames, boolean values, and other information on the command line. Handling those switches can be a bother, and it's seems silly to repeat similar code for each application. This is where TCommandLineParser comes in.
TCommandLineParser is a library that makes it really easy to add and read command line parameters to your applications. Sure, the RTL provide the ParamStr/ParamCount functionality, but they don't provide some of the features that TCommandLineParser does. For instance, with TCommandLineParser you can:
To get started using it, you can pull the code using Git from the following endpoint (You do have Git installed on your machine, right?) :
The project comes with a simple demo application, but let's build one ourselves so that we can step through the process and really see how it works. So, let's take the following steps:
4. Now, add a new, blank unit to the file and call it CLPOptions.pas. This is the file that will hold the class that will end up with all of the command line parameter values. In that file we'll have an interesting class – one with nothing but class variables. Put the following code into the unit.
TSampleOptions = class
class var
FileToProcess: string;
OutputInUpperCase: Boolean;
NumberOfIterations: integer;
This class contains a string, a Boolean and an integer. Other types that can be passed on the command line include enumerated types, sets, and floating point numbers. Again, this class will end up holding the values passed on the command line, and since the variables are all class variables, they can be accessed directly without having to instantiate the class.
5. Next, we'll register these items with the TOptionsRegistry class. This class is the one that translates the command line parameters into options usable by your application. You can define options as having a long name, a short name, and whether the parameter is optional or required. The TOptionsRegistry.Parse method will then parse out the command line and fill in the values of the class we defined above. In order to do that, create a new, empty unit, add it to the project, and call it CLPConfig.pas. Then, add VSoft.CommandLine.Options and CLPOptions to the uses clause of your new unit. Then, add the following code to the implementation part of the unit (you can leave the interface section empty):
procedure ConfigureOptions;
Option : IOptionDefintion;
Option := TOptionsRegistry.RegisterUnNamedOption<string>('The file to be processed',
procedure(value : string)
TSampleOptions.FileToProcess:= value;
Option.Required := true;
Option := TOptionsRegistry.RegisterOption<Boolean>('OutputInUpperCase','o', 'The output should be in upper case',
procedure(value : Boolean)
TSampleOptions.OutputInUpperCase:= value;
Option.Required := true;
Option.HasValue := False;
Option := TOptionsRegistry.RegisterOption<integer>('NumberOfIterations','n','The number of times the file should be processed',
procedure(value : integer)
TSampleOptions.NumberofIterations := value;
Option.Required := False;
Option.HasValue := True;
Here's what is important to note about the following code:
Of course this procedure needs to be called very early in the executable timeline, so you should add an initialization section to the unit that looks like this:
Switches are key to passing command line parameters, and TCommandLineParser will accept the following to define a switch:
Note that for options that have HasValue set to False, there is no need to pass a value.
Of course, once you have set all these options, you need to write some code to retrieve them, and handle the situation when things aren't right – required parameters are missing, or switches requiring values don't have them.
Go to the DPR file and add this code:
ParseResult : ICommandLineParseResult;
//parse the command line options
ParseResult := TOptionsRegistry.Parse;
if ParseResult.HasErrors then
Writeln('Usage :');
procedure(value : string)
end else
Writeln('FileToProcess : ', TSampleOptions.FileToProcess);
Writeln('OutputInUpperCase : ', TSampleOptions.OutputInUpperCase);
Writeln('Iterations : ', TSampleOptions.NumberOfIterations);
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
Note the following about the above code:
That's it for code. Now for using the application. First, let's get a look at what happens when you pass no parameters at all. Press F9 and you should see something like this:
Note that you receive error messages, and a description of how the command line parameters work.
Then, go to Run|Parameters and in the Parameters box enter:
somefile.dat -o -n:42
Running the app should result in the following:
Which shows that the parameters were correctly passed.
And that is about it. It takes a bit of work to get going, but not much, and you get a lot of functionality for the little input that you have to make.
Like I said in the title – another gem from the folks at VSoft Technologies.
Sadly, the good old Embarcadero newsgroups NNTP Feed appear to have come to an end. Alas. I've been a member of those groups in one form or another for over 20 years, starting with the Compuserve forums and ending up with the wonderful and grossly underappreciated NNTP newsgroups. I believe that Embarcadero is trying to get the newsgroups back up in a read-only status. Nevertheless, it appears to be time to move on.
So where can we migrate to? I see three places where the community can communicate and get questions answered.
So for now, those are the places to gather and get help. Times are changing for the Delphi community, both in terms of what the tool can do and where we will communicate online. I encourage folks to move on from the newsgroups and try out the newer places to hang out and get help.
My book, "Coding in Delphi" is now available in print. This is pretty cool. You can get it from CreateSpace or Amazon. I'm grateful for every order.
It seems very strange to have my own entry for sale on Amazon. Writing a book is a lot of work, but I will say, it's quite satisfying to hold the book in your hand and see your name on Amazon.com. :-)
I'd also be very grateful for book reviews on Amazon. If you like the book, please let people know. And if you don't like it, write a review and say why. Either way, I'll appreciate your honest assessment. You can write the review right from the Amazon order page.
And again, I'm grateful to all of you who have had so many nice things to say, who helped edit the book, and who make the Delphi community so great.
In a previous post, I humbly suggested that Embarcadero publish their unit tests for Delphi. I still think it is a good idea, but I understand if they don't do it. They do have a lot to do.
So I thought – after suggestions from folks that read the post, including Kenneth Cochran – that it would be a good idea to just go ahead and start our own community project. So I did.
The Delphi Unit Tests Project
This is a pretty straight-forward project – it is merely a set of unit tests for Delphi's RTL. You can find out the basics on the home page of the wiki, where you'll also find further information about writing tests, etc. It's a wiki, so it will continue to be expanded. I'm kind of weird in that I actually enjoy writing unit tests, so I've been adding tests over the last week or so.
This is a community project based on Mercurial. That means that anyone can fork it, add tests, and then submit a pull request. We've already had four or five submissions, and I'm really appreciative. It's quite easy to contribute, and you can write tests for anything you like. Any submitted tests must pass, of course.
We are also using the new Delphi unit testing framework, DUnitX. It is still a bit rough around the edges, but hopefully this will be an impetus to get it fully up to speed. I've volunteered to write the GUI runner, but there are some architectural issues that need to be taken care of. Right now, you can output to NUnit xml and the console. DUnitX is attribute based and really easy to use.
Things I'd like to eventually get done:
In any event, come join the cause and write a test. Even one single test would be fine!
All good developers write unit tests. The Delphi team is no different. The team has a suite of unit tests for the RTL and a very, very large set of tests for the compiler. The tests for the RTL are, to a large degree, DUnit based. The compiler tests are a bit different, as they date back well before DUnit even existed. They are a set of console applications that write out PASS or FAIL to the standard output depending on whether the test passed or failed. I believe that this suite of tests also tests a lot of the lower level RTL. I know the QA team doesn't like to test the RTL using a tool that depends heavily on the RTL itself.
So anyway, this suite of tests exists. They get run constantly as part of a continuous integration process at Embarcadero. And the suite gets expanded as time goes by. When I managed the R&D team, I even contributed to the test suite myself.
But given that you can't ever have enough unit tests, and that like all companies, Embarcadero has limited resources, the test suite doesn't expand fast enough. (Actually, I suppose no test suite expands fast enough, right?)
So I have a plan: Embarcadero should open source their unit test suite and accept inputs from the community.
Here's why I think they should do that.
I could think of some objections that they might have. Here are some of those objections, along with reasons why those objections should be ignored.
I thought long and hard for reasons why Embarcadero shouldn't open source their tests, and I couldn't think of any. Seriously, I can't think of a downside here.
So how about it, guys?
As you know, I love Dependency Injection. I wrote a whole series of articles on it using the Spring for Delphi framework, and in my previous position instituted its pervasive use in the large project there. I'm scheming to integrate it into the legacy app I work on now. I bought and read the definitive book on the subject:
But there was always one thing that bugged me -- In Mark Seemann's book and in this article (Service Locator is an Anti-pattern) he argues against the use of a ServiceLocator – that is, a class that grabs instances out of the DI Container and hands them to you for your use. I never really agreed, as I didn't see any other way to do it – of course you needed to grab instances out of the container via a Service Locator pattern. How else would you do it? I mean, you can do Constructor Injection and all, but at some point you need to grab an instance of something, right? I had read his stuff, read the comments and arguments on the topic, but was never really persuaded. But then again, maybe I was missing something. The question of "how" always held me back.
Well, I was working on some demo code for my book, and out of the blue, all of a sudden, it hits me: Seemann is right. The ServiceLocator is an anti-pattern, mainly because it is pretty much unneeded.
Here's what happened.
First thing: if you go to my demo code on BitBucket, you'll see a Dependency Injection demo there that uses the ServiceLocator to grab instances of registered classes. It's cool – you can understand the basics of DI by looking at it. You can properly decouple the code and end up with nothing but a unit of interfaces in your uses clause. Nice. I even did a CodeRage presentation using this basic code. That code illustrates how you can use a DI Container and the ServiceLocator to create loosely coupled code. No worries. However, you'll notice that the calls to the ServiceLocator kind of become replacements for calls to Create.
Only you can do the same thing with no ServiceLocator calls.
Second: The Delphi Spring Container has a set of methods that I confess I never quite understood:
function InjectConstructor(const parameterTypes: array of PTypeInfo): TRegistration<T>; overload;
function InjectProperty(const propertyName: string): TRegistration<T>; overload;
function InjectMethod(const methodName: string): TRegistration<T>; overload;
function InjectMethod(const methodName: string; const parameterTypes: array of PTypeInfo): TRegistration<T>; overload;
function InjectField(const fieldName: string): TRegistration<T>; overload;
These methods allow you to inject (duh) different items into your classes and automatically instantiate them as a result. I knew they were there, I knew that they were useful, but I never understood completely why they were in there. You could pretty much get along without them because you had the ServiceLocator to grab anything you need.
I was reading Mark Seemann's book again, and reading about how you should be using constructor injection everywhere, and how you need to push the creation of your component graph all the way back to the composite root. In Delphi, that means all the way back to the first line of the DPR file. And if you do that, you could end up with this monster constructor that requires every single class your application needs. And it was this notion that made me think "The ServiceLocator is necessary to get rid of that huge constructor."
So I confess I never quite got it.
But yesterday, I'm working on sample code for my book, and of course, I have to show how the above methods work. I'm working up demos (I'll show a simple one below that illustrates the whole thing) and it hits me: The key to the whole notion of a ServiceLocator being an anti-pattern lies in what these five methods can do.
And basically what they can do is this: They can cause the creation of every single class needed for your application during the registration process. They can completely eliminate the need for you to ever call the ServiceLocator (with one exception, discussed below) because if you can call the ServiceLocator, you can use these methods to register the connection between what you need the ServiceLocator for and the registration process.
Put another way, every call to the ServiceLocator can be replaced by a registration call. You don't need the ServiceLocator because the registration process alone is enough.
So I think a simple example is in order. I'll try to keep it short and sweet.
Consider the following unit of code:
unit uNoServiceLocatorDemo;
, Spring.Services
, Spring.Collections
IWeapon = interface
procedure Weild;
IFighter = interface
procedure Fight;
TBattleField = class
FFighter: IFighter;
procedure AddFighter(aFighter: IFighter);
procedure Battle;
TSword = class(TInterfacedObject, IWeapon)
procedure Weild;
TKnight = class(TInterfacedObject, IFighter)
FWeapon: IWeapon;
constructor Create(aWeapon: IWeapon);
procedure Fight;
{ TBattleField }
procedure TBattleField.AddFighter(aFighter: IFighter);
FFighter := aFighter;
procedure TBattleField.Battle;
WriteLn('The Battle is on!');
{ TKnight }
constructor TKnight.Create(aWeapon: IWeapon);
inherited Create;
FWeapon := aWeapon;
procedure TKnight.Fight;
WriteLn('The knight swings into action!');
{ TSword }
procedure TSword.Weild;
WriteLn('"Swoosh" goes the sword!');
Here we have some classes that are all nicely decoupled. Our registrations are neatly named. The classes use constructor injection to ask for their dependencies, and the TKnight and the TSword are nicely registered, just waiting to be grabbed and used in a decoupled way using the ServiceLocator. All is great. And then in order to actually have our cast of characters do anything, you might do something like this:
procedure FightBattle;
Battlefield: TBattleField;
TempKnight: IFighter;
TempSword: IWeapon;
Battlefield := TBattleField.Create;
TempKnight := ServiceLocator.GetService<IFighter>;
TempSword := ServiceLocator.GetService<IWeapon>;
TempKnight.Weapon := TempSword;
procedure FightBattle;
Battlefield: TBattleField;
TempKnight: IFighter;
TempSword: IWeapon;
Battlefield := TBattleField.Create;
TempKnight := ServiceLocator.GetService<IFighter>;
TempSword := ServiceLocator.GetService<IWeapon>;
TempKnight.Weapon := TempSword;
You need a knight and a sword? Well, just call the ServiceLocator, grab the sword, arm the knight, add him to the battle, and off it goes. You get this:
It all works, and it is all decoupled. But you are still using the ServiceLocator.
The argument against the ServiceLocator is pretty simple: It's a singleton, singletons are global variables, and global variables are bad. (That's a gross oversimplification – read the article and the comments for a better discussion….) Plus, if you don't need it, why use it?
Well, you don't need it. Watch.
First thing to note is that Seeman says you should have one call to the ServiceLocator at the very root of your application. You get one shot. We'll see that one shot below.
Second, let's change how we register our classes and interfaces:
GlobalContainer.RegisterType<TBattleField>.InjectMethod('AddFighter', ['knight']);
GlobalContainer.RegisterType<TBattleField>.InjectMethod('AddFighter', ['knight']);
Some things to note:
Thus we've used the container to "wire up" all the dependencies and ensure that they are properly created before the main class or any other class is even asked for. The call to GlobalContainer.Build in the DPR file will ensure this takes place.
Finally, we run everything with the much simpler and cleaner:
procedure FightBattle;
Battlefield: TBattleField;
Battlefield := ServiceLocator.GetService<TBattlefield>;
And there's our one call to ServiceLocator at the very root of our application (FightBattle gets called in the DPR file as this is a console application).
You can do the same thing with constructors – you can call InjectConstructor, passing the names of registrations for each of the parameters in the constructor. And if need be, for both InjectConstructor and InjectMethod, you can add in non-registered parameters such as integers and strings, etc.
Bottom line: Use the injection methods and the container to connect up your classes and inject dependencies, not the ServiceLocator.
And I haven't even yet mentioned how you can replace the InjectXXXXXX calls with attributes.
Okay, now I feel better since I agree with Mark Seemann over at http://blog.pleoh.dk. Being in disagreement with a smart guy like that isn't a comfortable place to be.
I hope that you all know that when you do a full build on your Delphi project, you should never allow hints and warnings to remain in your code. Warnings, in particular, are an indication that something is going on that you almost certainly don't want to be going on. But what about hints? Hints can't really be a problem, can they?
Well, yeah, they can definitely point to something happening that you don't want to happen – or in the case below, of something not happening that you do want to happen.
Let's say you are maintaining an older Delphi application and you run across some code that looks like this:
Screen.Cursor := crSQLWait;
// A bunch of database code that might make
// the user wait
Screen.Cursor := crDefault;
And naturally you think "Oh my, that will never do. What happens if an exception occurs in that database code! The cursor might be stuck! That needs a try…finally block around it!". And so you do the following:
Screen.Cursor := crSQLWait;
// A bunch of database code that might make
// the user wait
Screen.Cursor := crDefault;
And that's better, but something is still nagging at you, and it suddenly hits you – "what if the cursor wasn't actually crDefault to start with? Shouldn't you restore the cursor to whatever it was before you started?" So you are feeling a bit cocky and you proceed with a bit too much haste and you do this:
OldCursor: TCursor;
OldCursor := Screen.Cursor;
Screen.Cursor := crSQLWait;
// A bunch of database code that might make
// the user wait
Screen.Cursor := crDefault;
But like I said, you are feeling a bit cocky, and you think "I'll be this is all over the place" and you search for similar code patterns and you are right and you go off and fix this "omission" that is scattered all over your codebase. Things are great, right?
Finally you compile and there is a <shudder> hint in your code!
[dcc32 Hint] Unit5.pas(29): H2077 Value assigned to 'OldCursor' never used
and you're like "Whaaat? It's just a silly hint, who cares!". But of course, your conscience is nagging at you, and you remember that Nick told you to not allow any hints or warnings, not even stupid hints like this one, and you suddenly realize that your code has an <another shudder> bug in it and it is not doing at all what you wanted and intended for it to do.
And of course, you fix the subtle bug of forgetting to actually set the cursor back to its original value:
OldCursor: TCursor;
OldCursor := Screen.Cursor;
Screen.Cursor := crSQLWait;
// A bunch of database code that might make
// the user wait
Screen.Cursor := OldCursor; // <--- forgot this part
And then you think "Dang, that Nick dude was right! Hints really can indicate problems", and you never let another hint slide for as long as you live.
And of course, I should say that I totally made this scenario up, and that I would never, ever, ever do anything like that. Nope, not me. Nope. No way. Neeeever happened.
I'm currently reading Head First Design Patterns, and am finding it very useful and educational. One problem, though – it's all in Java. So I thought that as part of the exercises, I'd translate the code to Delphi. And also as part of my learning process, I thought it would be a good idea to post an article about each of the patterns. I also encourage you to buy the book and read it for yourself.
I'm currently reading Head First Design Patterns, and am finding it very useful and educational. One problem, though – it's all in Java. So I thought that as part of the exercises, I'd translate the code to Delphi. And also as part of my learning process, I thought it would be a good idea to post an article about each of the patterns. I also encourage you to buy the book and read it for yourself.
The first real pattern that the book shows is the Observer Pattern. You should use the observer pattern when you have one object that notifies other objects when events occur. Or more succinctly, use it when you have an object that needs to notify other objects about stuff that happens.
HFDP uses the example of a simple weather station that gathers data about the weather. Each time the weather station takes readings, it needs to update the views of that weather. The weather station reports on Temperature, Humidity, and Pressure. There are three views that the application provides – current conditions, statistics about the weather, a simple forecast.
The idea here is that the weather station is the subject – it is the object being observed and doing the notifying. The different displays for the information are the observers – they watch what happens on the weather station and update themselves based on the notifications that they receive from the weather station. Another way to look at it is that the weather station is a publisher of information, and the displays are subscribers.
The formal definition given for the Observer Pattern goes like this: The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.
The formal definition given for the Observer Pattern goes like this: The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified and updated automatically.
But when it comes time to implement this, the temptation is to simply embed the displays inside of a method of the weather station. You might create classes for each view, instantiate them in the weather stations constructor, and then simply update the views in a method called MeasurementsChanged.
But of course if you do this, you are breaking some of the base design rules. First, you'd be coding against an implementation instead of against an interface. Second, you've made it really hard to add a new data display should that become necessary. Displays are hard-coded into the weather station and can't be added or removed at runtime. If we do want to add more displays, we'd need to modify the weather station itself. Or, put more succinctly, the weather station and its displays are tightly coupled to each other. And if you know one thing about me, I abhor tight coupling. And you should too.
In any event, there is a better way – the Observer Pattern. As noted above, observer pattern consists of a Subject that is monitored by Observers. We'll implement a very simple version of the observer pattern. The first thing we will do of course, is declare two interfaces:
IObserver = interface
procedure Update(aTemperature: integer; aHumidity: integer; aPressure: Double);
ISubject = interface
procedure RegisterObserver(aObserver: IObserver);
procedure RemoveObserver(aObserver: IObserver);
procedure NotifyObservers;
The first interface is IObserver, which the observing classes will implement. In it they'll be updated with all the weather information that the weather station has for us. The second is ISubject, which will be implemented by the weather station. It takes three methods, two for handling the connecting and disconnecting of IObservers, and the third for doing the actual notification to the observers.
The first implementation we'll look at is the Weather Station. Here is its implementation declaration.
TWeatherData = class(TInterfacedObject, ISubject)
FTemperature: integer;
FHumidity: integer;
FPressure: double;
FObserverList: TList<IObserver>;
function GetTemperature: integer;
function GetHumidity: integer;
function GetPressure: double;
constructor Create;
destructor Destroy; override;
procedure SetWeatherInformation(aTemperature: integer; aHumidity: integer; aPressure: double);
procedure RegisterObserver(aObserver: IObserver);
procedure RemoveObserver(aObserver: IObserver);
procedure NotifyObservers;
procedure MeasurementsChanged;
property Temperature: integer read GetTemperature;
property Humidity: integer read GetHumidity;
property Pressure: double read GetPressure;
The plumbing for managing the weather implementation is all what you'd expect. The interesting part, of course, is the implementation of ISubject. Internally, it uses a TList<IObserver> to manage all the observers that get registered with it. The RegisterObserver and RemoveObserver methods simply insert and remove, respectively, instances of classes that implement the IObserver interface.
The real action occurs in the NotifyObservers method. We'll get to that in a second. First, though, let's take a look at the observers. Since all the displays are very similar, this is a good time to use good old-fashioned inheritance to declare a base class that implements the needed functionality, and then have descendent classes that do the work of providing the specified displays. Here, then, is the interface for TWeatherDataDisplay:
TWeatherDataDisplay = class(TInterfacedObject, IObserver, IDisplay)
FSubject: TWeatherData;
FTemperature: integer;
FHumidity: integer;
FPressure: Double;
constructor Create(aWeatherData: TWeatherData);
destructor Destroy; override;
procedure Update(aTemperature: integer; aHumidity: integer; aPressure: Double); virtual;
procedure Display; virtual; abstract;
TWeatherDataDisplay has fields to keep track of the current weather information. It's descendants can do with it as they please. It also implements the IDisplay interface so that it can report out what it has to say. The Update method will allow the Subject – in this case the weather station – to update the displays. Update is a virtual method, by the way, so that descendants can do different things with the incoming information.
Okay, so let's look under the hood. The weather station can accept and remove IObserver implementers at runtime. implements the NotifyObservers method as part of the ISubject interface. It gets called whenever the weather information changes. It is implemented as follows:
procedure TWeatherData.NotifyObservers;
Observer: IObserver;
for Observer in FObserverList do
Observer.Update(Temperature, Humidity, Pressure);
This is pretty simple – it merely enumerates over each item in the observer list and calls the Update method, passing along the new weather data. The base class stores the information, and its descendants process it.
The real "work" gets done when the weather station updates the temperature data and calls NotifyObservers:
procedure TWeatherData.SetWeatherInformation(aTemperature, aHumidity: integer; aPressure: double);
FTemperature := aTemperature;
FHumidity := aHumidity;
FPressure := aPressure;
The entire implementation of our little weather station can be found as part of my demo code on BitBucket.org.
The entire implementation of our little weather station can be found as part of my demo code on BitBucket.org.
So all of this comes together in a method to create a weather station and add observers:
procedure DoWeatherStation;
WeatherStation: TWeatherStation;
CurrentDisplay: IDisplay;
ForecastDisplay: IDisplay;
StatsDisplay: IDisplay;
WeatherStation := TWeatherStation.Create;
CurrentDisplay := TCurrentConditionsDisplay.Create(WeatherData);
ForecastDisplay := TForecastDisplay.Create(WeatherData);
StatsDisplay := TStatisticsDisplay.Create(WeatherData);;
WeatherStation.SetWeatherInformation(70, 55, 28.90);
WeatherStation.SetWeatherInformation(68, 59, 28.96);
WeatherStation.SetWeatherInformation(35, 66, 27.40);
WeatherStation.SetWeatherInformation(55, 55, 27.40);
Here are some interesting things to note:
So that should be a quick rundown on how the observer pattern works. The obvious weakness here is that our IObserver interface is very specific to weather data. You can create your own interface for your specific implementation. The pattern remains the same no matter how the IObserver interface is designed. This is obviously a good place for generics to enter the picture, and in fact, the Delphi Spring framework implements a generic IObservable<T> interface and implementing class.
So in summation, the Observer pattern ensures that publishing classes (subjects) can communicate updates to their subscribing (observer) classes with very loose and flexible coupling. Observers can be updated and removed at runtime. Adding observers requires no change to subjects. Subjects don't know much at all about what the observers are up to. It's all very easy and elegant and loosely coupled – just like you want it.
Next up – the Decorator Pattern.
One of those fun little issues in our business is trying to figure out the difference between iterating and enumerating. This StackOverflow answer does a pretty good job of explaining it. Iterating is doing something – usually a series of steps – over and over again. Enumerating is going over each item in a given collection. A subtle difference, sure. One usually iterates when enumerating.
Okay, so enumerating is going over each item in a collection. IEnumerable can enumerate over the items in a collection as we saw in my last article. But you can enumerate over other things as well. For instance, in Delphi, you can use the for…in statement to enumerate over the characters in a string.
But this makes me wonder: how does something become, well, enumeratable? How do you make something so that you can use with the for…in statement?
Well, it's pretty easy. The rules for Delphi are simple:
So, at this point, a simple demo would be helpful, eh?
You can already enumerate the characters in a string, but it's a simple example, and so the following example implements this easy to understand enumeration on a string:
TForInDemoClassEnumerator = class
FString: string;
FIndex: integer;
function GetCurrent: Char; virtual;
constructor Create(aString: string);
function MoveNext: Boolean;
property Current: Char read GetCurrent;
TForInDemo = class
FTheString: string;
procedure SetTheString(const Value: string);
constructor Create(aString: string);
function GetEnumerator: TForInDemoClassEnumerator;
property TheString: string read FTheString write SetTheString;
This code declares two classes. The first class is the enumerator – the class that does the work of moving over each item, and which will be returned by the call to GetEnumerator. The second is the class that will be enumerated. Notice, too, that TForInDemoClassEnumerator has the read-only property Current with the reader GetCurrent and MoveNext methods. The TForInDemo class has a call to GetEnumerator that returns an instance of TForInDemoClassEnumerator.
First let's look at TForInDemoClassEnumerator. You create it by passing the constructor the item to be enumerated – in this case a string. Hence, the constructor:
constructor Create(aString: string);
Here is the implementation of the MoveNext method:
function TForInDemoClassEnumerator.MoveNext: Boolean;
Result := FIndex < FString.Length;
if Result then
This code does two things. First, it sets the result. The function returns True if the enumerator is able to move to the next item, and False if it has reached the end of the items to be enumerated. In this case, it merely checks to see the index is before the length of the string. If the end has not yet been reached, it just increases the FIndex field. So it's job here is merely to move the index along, and report if the end has been reached.
The actual item itself is returned by the GetCurrent method, which is self-explanatory:
function TForInDemoClassEnumerator.GetCurrent: Char;
Result := FString[FIndex];
And that is it for the enumerator. It's pretty simple. But we'll soon see that you can do some cool things with these enumerators because you have complete control over how they return the data that they are enumerating over.
The next step is to see how the actual class to be enumerated provides its enumerator to the compiler. When the compiler builds the for…in loop construct, it looks at the in part of the construct and thinks "Hey, I need an enumerator here, so I'll call GetEnumerator". If the item in question indeed has a method called GetEnumerator, it calls it, and all is well. If not, the compiler raises an error because the type in the in part of the for…in loop isn't enumeratable.
But of course, our TForInDemo class has such a method, and it is quite simple:
function TForInDemo.GetEnumerator: TForInDemoClassEnumerator;
Result := TForInDemoClassEnumerator.Create(FTheString);
It merely creates and returns an instance of our enumerator, passing it the string value it is storing for the purpose of enumerating. Pretty easy and straight forward, really.
Now that we've created all these classes, you can run the following code:
procedure DoStuff;
ForInDemo: TForInDemo;
C: Char;
ForInDemo := TForInDemo.Create('HelloWorld');;
for C in ForInDemo do
Write(C, ',');
Now the above discussion talks a lot about specific methods that must be included as part of an enumerator, and as part of a class that wants to be enumerated. And of course, that should immediately make you think "Interfaces!". And sure enough, there are some nice interfaces that fall out of this. (You knew I'd work interfaces into things here eventually, didn't you. Yes, you did.)
Consider this interface:
IEnumerator<T> = interface
function GetCurrent: T;
function MoveNext: Boolean;
property Current: T read GetCurrent;
That should look awfully familiar. It's the exact two methods and one property needed to implement an enumerator – hence the name.
I've declared this IEnumerator<T> interface myself, but the Delphi RTL includes a similar one in the System.pas unit. And at its base, IEnumerable<T> is all about implementing the GetEnumerator method.
I've declared this IEnumerator<T> interface myself, but the Delphi RTL includes a similar one in the System.pas unit. And at its base, IEnumerable<T> is all about implementing the GetEnumerator method.
It leverages generics because the type of what is being enumerated doesn't matter as far as the interface is concerned. And remember when I said that a call to GetEnumerator could return an interface? Well it can, and the compiler will happily use an IEnumerator<T> to implement the for…in loop.
Thus, your enumerators can implement this interface and your calls to GetEnumerator can return this interface, and you can add flexibility to how they are implemented. Here's an example:
TStringEnumerator = class(TInterfacedObject, IEnumerator<Char>)
FIndex: integer;
FString: string;
function GetCurrent: Char;
constructor Create(aString: string);
function MoveNext: Boolean;
property Current: Char read GetCurrent;
TInterfaceEnumeratorDemo = class
FTheString: string;
procedure SetTheString(const Value: string);
constructor Create(aString: string);
function GetEnumerator: IEnumerator<Char>;
property TheString: string read FTheString write SetTheString;
Notice that the call to GetEnumerator returns an IEnumerator<Char> which is actually the individual type being iterated. In this case, the generic type needs to be the same type as the variable being returned in the for part of the for…in loop.
This enables you to do the following:
procedure DoInterfaceStuff;
InterfacedEnumerator: TInterfaceEnumeratorDemo;
c: Char;
InterfacedEnumerator := TInterfaceEnumeratorDemo.Create('GoodbyeWorld');
for c in InterfacedEnumerator do
Write(C, ',');
The implementation of an enumerator is, as I mentioned, really simple. But what if you wanted to get a little creative in the GetCurrent method? After all, at that point you have complete control over what the enumerator returns. In our simple case with characters and strings, what if we decided to, say, always return the upper case version of the character? Or if we were iterating over integers, return the squares of the numbers in the collection? That would be super easy, right? Well, yes, it would.
Consider this code:
TForInDemoClassUpperCaseEnumerator = class(TForInDemoClassEnumerator)
function GetCurrent: Char; override;
function TForInDemoClassUpperCaseEnumerator.GetCurrent: Char;
Result := UpCase(inherited GetCurrent);
This class descends from TForInDemoClassEnumerator and overrides the existing enumerator for our demo class and returns the upper case of the character in question.
If we wanted, we could return this class from our GetEnumerator call, but that would be sort of playing a trick on the user of our code. How about if we provide two different enumerators, and then make each available for enumeration in a for…in loop. Surely that is possible, right? Of course it is.
First, we'll look at the end result and then work our way backwards to see how it was implemented, because you have to play a little trick to expose more than one enumerator for a class:
procedure DoMoreStuff;
C: Char;
ForInExtraDemo: TForInDemoExtraIterators;
ForInExtraDemo := TForInDemoExtraIterators.Create('Greetings');
for C in ForInExtraDemo.AsUpperCase do
Write(C, ',');
This little routine will display the string "Greetings" as "G,R,E,E,T,I,N,G,S" in the console. But note in the for…in loop that the actual class is not passed to the in clause, but a method that returns a "proxy" class that has the desired enumerator attached to it instead. This is implemented as follows:
TUpperCaseEnumeratorProxy = class
FOwner: TForInDemo;
constructor Create(aOwner: TForInDemo);
function GetEnumerator: TForInDemoClassUpperCaseEnumerator;
constructor TUpperCaseEnumeratorProxy.Create(aOwner: TForInDemo);
inherited Create;
FOwner := aOwner
function TUpperCaseEnumeratorProxy.GetEnumerator: TForInDemoClassUpperCaseEnumerator;
Result := TForInDemoClassUpperCaseEnumerator.Create(FOwner.TheString);
This is just another class that can be enumerated – it has a call to GetEnumerator – and thus be returned by a method call on our "real" enumerating class. It returns an instance of an enumerator called TForInDemoClassUpperCaseEnumerator which we looked at above. So, if you want to iterate over the upper case version of the strings, you call it as we did in the DoMoreStuff method above. The trick here is that instead of iterating over the class itself, you iterate over the proxy class using ForInExtraDemo.AsUpperCase. It's a neat little trick, eh?
Thus, the enumerating class becomes:
TForInDemoExtraIterators = class(TForInDemo)
FUpper: TUpperCaseEnumeratorProxy;
constructor Create(aString: string);
property AsUpperCase: TUpperCaseEnumeratorProxy read FUpper;
constructor TForInDemoExtraIterators.Create(aString: string);
inherited Create(aString);
FUpper := TUpperCaseEnumeratorProxy.Create(Self);
So, that should give you a little insight into what happens with for…in loops and how you can create classes that participate automatically. I'm working towards never using the old for I := 0 to Count –1 do; construct, and making my classes enumeratable.
The code for this article with further examples can be found with my demo code on BitBucket.
I rave about the Delphi Spring Framework. But I think my attention to the Dependency Injection Framework – which is only part of it -- has made you guys think that the two are synonymous. Not true – Spring4D is more than just a Dependency Injection container. In fact, there is a wealth of other stuff to be found in Spring4D.
Inspired by this StackOverflow question and a thread in the newsgroups, I thought that I'd write an article about a very powerful but not so well known (apparently) feature of Spring4D – IEnumerable<T> and the accompanying container interfaces and classes.
So the StackOverflow question basically asks this: How do I find out the maximum value of an integer in TList<integer>?
Well, the first thing you might do is use a for loop to check each item, and save each one as it gets larger. Or if you were really tricky, you'd use a for…in statement to find it. That's the "straight-up" way to do it.
But that isn't the real answer to the StackOverflow question. The real answer is this:
program ListEnumerableDemo;
{$R *.res}
, Spring.Collections;
List: IList<Integer>;
Enumerable: IEnumerable<integer>;
List := TCollections.CreateList<integer>;
Enumerable := List;
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
Now that looks quite a bit different than the code you were thinking of, I'll bet. There doesn't even appear to be any looping going on at all. There is in the background, but it's all been abstracted away for you. You want the maximum value to be found in the list? Just ask for it. Cool.
The key part above, of course, is the use of two things. First, the IList<T> – an interface to a generic list – and secondly, the IEnumerable<T>. Both of these types are provided by the Delphi Spring Framework. Both are defined in the Spring.Collections.pas unit. That unit contains a complete group of collection interfaces – IList<T>, IStack<T> ICollection<T>, etc. – as well as the definition of IEnumerable<T>.
I'd recommend that you consider using Spring.Collections.pas instead of the Generics.Collections.pas unit which comes with Delphi. First, it exposes all of the collection types as interfaces, and you should know by now that you should be coding against interfaces and not implementations. Secondly, each of the types supports the IEnumerable<T> interface, meaning you have the power of this great interface on all of your collections.
I'd recommend that you consider using Spring.Collections.pas instead of the Generics.Collections.pas unit which comes with Delphi. First, it exposes all of the collection types as interfaces, and you should know by now that you should be coding against interfaces and not implementations. Secondly, each of the types supports the IEnumerable<T> interface, meaning you have the power of this great interface on all of your collections.
We'll tackle those two things in order.
The Spring.Collections.pas unit is all you need in your uses clause to avail yourself of all that the Spring collections library provides. The unit includes the following interfaces along with a class to provide easy access to implementations of these interfaces:
All of these types should be familiar to you – if not, you can certainly read up on them via Google. The important part is that they are all generic (though there are non-generic types with store TValue as well) and they all implement IEnumerable<T>.
The unit also provides a class called TCollections which has nothing but class methods that return instances of the types listed above. These methods act as proxies for the constructors of the implementing types. You can create your own instances if you like, but for the most part, TCollections will do the job of getting an implementation of whatever container interface you want. For instance, if you want to get a hold of a dictionary, you can do the following:
The example above uses TCollections.CreateList<integer> to get an implementation of the IList<T> interface.
The implementations are all in units named Spring.Collections.Stack.pas and the like, but the Spring.Collections.pas unit exposes almost everything you need, and so as a rule, you should only need it in your uses clauses to take advantage of these powerful containers.
Those of you who also use .Net are familiar with IEnumerable already, but perhaps you didn't know that the same power was available to you in your Delphi code. For those of you not familiar, you are in for a treat.
The IEnumerable<T> interface is implemented by all of the classes discussed in the previous section, and so any of them can be accessed as an IEnumerable<T>.
Here is the declaration of IEnumerable<T>:
IEnumerable<T> = interface(IEnumerable)
function GetEnumerator: IEnumerator<T>;
function AsObject: TObject;
function TryGetFirst(out value: T): Boolean;
function TryGetLast(out value: T): Boolean;
function First: T; overload;
function First(const predicate: TPredicate<T>): T; overload;
function FirstOrDefault: T; overload;
function FirstOrDefault(const defaultValue: T): T; overload;
function FirstOrDefault(const predicate: TPredicate<T>): T; overload;
function Last: T; overload;
function Last(const predicate: TPredicate<T>): T; overload;
function LastOrDefault: T; overload;
function LastOrDefault(const defaultValue: T): T; overload;
function LastOrDefault(const predicate: TPredicate<T>): T; overload;
function Single: T; overload;
function Single(const predicate: TPredicate<T>): T; overload;
function SingleOrDefault: T; overload;
function SingleOrDefault(const predicate: TPredicate<T>): T; overload;
function ElementAt(index: Integer): T;
function ElementAtOrDefault(index: Integer): T;
function All(const predicate: TPredicate<T>): Boolean;
function Any(const predicate: TPredicate<T>): Boolean;
function Contains(const item: T): Boolean; overload;
function Contains(const item: T; const comparer: IEqualityComparer<T>): Boolean; overload;
function Min: T;
function Max: T;
function Where(const predicate: TPredicate<T>): IEnumerable<T>;
function Skip(count: Integer): IEnumerable<T>;
function SkipWhile(const predicate: TPredicate<T>): IEnumerable<T>; overload;
function SkipWhile(const predicate: TFunc<T, Integer, Boolean>): IEnumerable<T>; overload;
function Take(count: Integer): IEnumerable<T>;
function TakeWhile(const predicate: TPredicate<T>): IEnumerable<T>; overload;
function TakeWhile(const predicate: TFunc<T, Integer, Boolean>): IEnumerable<T>; overload;
function Concat(const collection: IEnumerable<T>): IEnumerable<T>;
function Reversed: IEnumerable<T>;
procedure ForEach(const action: TAction<T>); overload;
procedure ForEach(const action: TActionProc<T>); overload;
procedure ForEach(const action: TActionMethod<T>); overload;
function EqualsTo(const collection: IEnumerable<T>): Boolean; overload;
function EqualsTo(const collection: IEnumerable<T>; const comparer: IEqualityComparer<T>): Boolean; overload;
function ToArray: TArray<T>;
function ToList: IList<T>;
function ToSet: ISet<T>;
function GetCount: Integer;
function GetIsEmpty: Boolean;
property Count: Integer read GetCount;
property IsEmpty: Boolean read GetIsEmpty;
That's a lot of cool stuff, right? Many of the methods here are pretty clear -- it's pretty obvious what the Min and Max methods do. But some of the others are a bit trickier. You can get all of the items. You can get the First and Last items. You can get the first x number of items. You can get the items back out as a List, an Array, or a Set. And most powerfully, you can get any particular group of the items out using a predicate.
What is a predicate? A predicate is an anonymous function (or any function, really, but in our case it is an anonymous function) that takes a single const parameter of the type in question and returns True or False.
TPredicate<T> = reference to function(const value: T): Boolean;
It is used with some of the methods of IEnumerable<T> to answer this simple question: In or out? If the predicate is true, then the individual item is "in", or included. If it is "out", then the predicate will return False. So if you want to get all the items in a list strings that contain the letter 'z', then you can do the following:
function ContainsLetterZ: IEnumerable<string>;
List: IList<string>;
List := TCollections.CreateList<string>;
List.AddRange(['zoo', 'park', 'city', 'town', 'museum', 'jazz festival']);
Result := List.Where(function(const aString: string): Boolean
Result := Pos('z', aString) > 0;
The above uses the Where method to determine items that should be returned as part of a new IEnumerable<string>. The above is saying "return to me an enumerable item where all the strings in the list have 'z' in them."
You can do similar things with the TakeWhile method, which returns items from the start of the list as long as the predicate is True, and stops once the predicate is False. You can determine if a given container has or doesn't have a given element. You can Skip over a given number of elements and take the rest. You can use a predicate to SkipWhile a certain thing is true, and then return the rest once the predicate returns True Basically, once you have a reference to a collection or any IEnumerable<T> instance, you can get out of it pretty much anything you want.
Something to consider: If you have a nicely composed class that includes a private IList<T> which gets exposed through proxy methods, then you might want to expose access to the items via a property of type IEnumerable<T> instead of exposing the actual list itself.
Something to consider: If you have a nicely composed class that includes a private IList<T> which gets exposed through proxy methods, then you might want to expose access to the items via a property of type IEnumerable<T> instead of exposing the actual list itself.
And the real power gets unleashed with the very powerful ForEach methods. Folks have always pined for the lovely ForEach since the days of Borland Pascal's old TCollection object, and now it's back in full force, leveraging the power of anonymous methods. Thus, you can have a collection and do what you please with the items. Here is a simple example of just outputting them to the console window, but you can have your TAction<T> do anything at all that you like for each (sorry) element in the container.
procedure SimpleForEachDemo;
List: IList<integer>;
Action: TAction<integer>;
i: Integer;
Action := procedure(const aInt: integer) begin Writeln(Format('This number is: %d', [aInt])); end;
List := TCollections.CreateList<integer>;
for i := 1 to 10 do
So, basically you have a lot of untapped power there in Spring.Collections.pas, eh? The use of IEnumerable<T> and predicates ought to transform your code and change the way you look for things in lists and collections. If you aren't using these powerful tools yet, I strongly recommend that you add them to your tool chest.
I've written a pretty thorough example application for IEnumerable<T> and put it up on BitBucket. I also have some pretty simple examples showing predicates at work.
Remember, the Delphi Spring Framework is more than a Dependency Injection container. And there's more to it than the container classes as well. I strongly recommend that you start treating Spring4D like part of the Delphi Runtime Library. Heck, I wish Embarcadero would do just that.
Here's another article from my series at CodeFez -- and here's the response that Steve Teixeira wrote to it. The comments on both are a pretty interesting discussion.
Here's another article from my series at CodeFez -- and here's the response that Steve Teixeira wrote to it. The comments on both are a pretty interesting discussion.
I never cease to be amazed at how little the average developer knows about economics. I mean, I don't claim to be an expert, but I have taken a college class or two and read up on the basics. Even just understanding the basics, though, gives one surprising insight into why things happen the way they do in the marketplace.
For instance, we are in the process of hiring a new developer at my company. We figured out what qualifications we were looking for and determined about how much salary we wanted to pay. It quickly become apparent, however, that we weren't offering a high enough salary to attract the caliber of candidates we wanted. So what I did was to go on the newsgroups and start whining about not being able to find any good Delphi programmers. Okay, no, I didn't really do that. What we did, of course, was to increase the salary that we were offering. Simple supply and demand issue: There wasn't enough of a supply of good Delphi programmers at the price we wanted to pay, so the solution is to be willing to pay more – a no-brainer decision, really. Once we did that, we found that we have been able to find plenty of valuable candidates. Simple economics.
One common area that I see developers totally misunderstand is that of Delphi pricing. One thing you learn in Economics 101 is that the vast majority of companies are "price searchers". That is, they are constantly searching for a price that will maximize their profits. (Some companies, mainly producers of commodities, are "price takers". That is, they take whatever price is offered. Farmers are a good example. A corn farmer can only sell his corn at market price. If he asks for more, the market will simply buy corn from another farmer that will take the offered price). Borland is definitely a price searcher. They can set their prices as they please, and will do so to maximize profit. Of course, the market will respond to any particular price by demanding a certain number of units at that price. Price searchers are constantly adjusting prices to maximize the amount of money they make.
Note that they don't set price to maximize revenue, but rather profit. The cost of goods sold is a factor here as is the cost of simply having customers. Sometimes a company will actually price a product in order to limit the number of customers they have in order to maximize profits as sometimes having additional customers causes decreased profits. (That may be a bit counter-intuitive, but think of a product that has high production and support costs.) So for example, sometimes doubling your price can increase profits even though it drastically reduces sales. If doubling the price cuts the number of customers you have in half, but also cuts your production and support costs in half as well, your profit increases. (This is a very simple example, and it is actually hopelessly more complicated than that, but you hopefully get the basic idea).
So Borland, having learned from years of experience and copious sales data, is quite aware of what effect various prices have on sales. No doubt by now they have a pretty good idea what price will maximize their profits and how price changes will effect sales.
Where it gets really interesting is pricing outside of the United States. Europe, of example, is a completely different market than the US. Taxes, the demand curve, and the number of potential customers are all different. Borland clearly believes that they need to – and can – charge more in Europe than in the US. The price difference is not related to the exchange rate between the Euro and the Dollar; it has everything to do with maximizing profits. Clearly Borland believes that a higher price in Europe – again, a completely different market – will mean higher profits. That's why Delphi costs more in Europe. I suppose Europeans could view this as "price gouging", but in reality, it's just the market signaling to Borland that it will bear a higher price than will the American market. Simple economics.
Another economic blunder that developers frequently make is ignoring economies of scale. Borland is a big company that is publicly traded. Many Delphi developers work in small, private companies. Borland has legal obligations, overhead costs, and market demands that most little-shop developers don't even know about, much less take into consideration. Borland's main competition is one of the largest corporations in the world. Borland faces investors who expect a return. Borland has to deal with major entities in the media that can write things that can have profound effects on Borland's business. All of this combines to make running Borland a complex and difficult task that most of us simply don't comprehend.
So I love it when a developer posts in the newsgroups something like this: "Borland should just hire two college students to go through and fix all the Delphi bugs in Quality Central." Well, that sounds great, but is clearly isn't that simple. First, fixing bugs in a big product like Delphi is no small, trivial task. Finding people with the talent and skill to do Delphi bug-fixing isn't easy. And they certainly aren't going to be cheap. The notion that some college interns can do it is quite naïve. The economic blunder comes, though, in thinking that the cost of fixing all those bugs is merely the salary of a couple of developers. First, employees aren't cheap, no matter who you hire. Human capital is by far the most costly – and valuable – part of doing business. Secondly, I don't know what your development process is like, but bug fixing at Borland is more than a guy hacking out some code. Every fix has to be extensively tested for efficacy and correctness, and then the whole product has to be regression tested to ensure that any given fix doesn't actually break something else. Fixes need to be incorporated into shipping product and distributed to existing customers. The documentation needs to be updated. And who know what else needs to be done? The point is this: the costs of things that many people think are small are in fact much larger than the average developer appears to realize.
The economics of running a business like Borland isn't something about which I claim to be an expert. But I do know that I don't know enough to be able to claim to know better than Borland. Something to consider before you fire off a post in the newsgroups that starts out "Borland ought to just...."
This one is a Blast from the Past -- I originally wrote and posted it on December 15, 2005 -- but it is as true today as it was then. I even considered palming it off as fresh material.
This one is a Blast from the Past -- I originally wrote and posted it on December 15, 2005 -- but it is as true today as it was then. I even considered palming it off as fresh material.
It's a standard Dilbert joke that managers are idiots. One doesn't have to hang around programmers too long to find out that many of them work for managers that don't have a clue about developing software and thus make many a nutty decision based on profound ignorance. Plenty of Delphi fans have had a boss that follows the "Nobody ever got fired for choosing Microsoft Development tools" rule and choose Visual Basic as a corporate standard. <shudder> And the old adage states that programmers make crappy managers.
So, I guess, based on the above, it's impossible for someone to be a good manager of programmers. If one doesn't know anything about programming and has never been a programmer, then apparently, he will suck as a manager. And if one has been a programmer, and is so good at it that he gets promoted to be a manager, he,too, will suck as a manager. Sounds like a lose/lose situation all around -- programmers doomed to a life of sucky supervisors.
Well, I'm not buying it. Surely somewhere, somebody is managing programmers well. Somebody has to be leading folks to build some of the insanely good software projects that are going on out there. So, what does it take to manage programmers well? Good question. I'd say that such skills and capabilities exist. I'd also say that they are, sadly, in relatively short supply. Too many Dilbert strips end up on too many cubicles in software development shops.
First, to be a good manager of programmers you have to be,well, a good manager. That's easier than people think, really. Here's my basic list of things one can do and not do to be a good manager:
Now, that's all general stuff. It applies to all managers, whether they lead a team of auto workers or a group of Delphi programmers. What does it take to manage programmers well?
Okay, that's a pretty good list. I've been on both sides of the fence, and as a consultant, I see all sorts of management types and methods. I deal with programmers on a daily basis, and I are one myself, so I think I have a pretty good grip on what's going on from a lot of angles. I'm sure you all will come up with more stuff and comment on it. Please do. After all, I'm not an expert on this stuff and I only write this to try to make you look good. ;-)
The views I express here are entirely my own and not necessarily those of any other rational person or organization. However, I strongly recommend that you agree with pretty much everything I say because, well, I'm right. Most of the time. Except when I'm not, in which case, you shouldn't agree with me.
Powered by BlogEngine.NET 22.214.171.124
Theme by Mooglegiant and modified by Nick Hodges


text:
Welcome to MS Connection! Please sign in to join the conversation. (Not a member? Register now.)
Forgot Password?
Forgot Username?
The MSFriends program connects you with emotional support from volunteers living with MS, 15 hours a day and seven days a week. Connect today by calling the MSFriends helpline at 1-866-673-7436.


text:
Номер в каталоге : TMS320F28069
Function : TMS320F2806x Piccolo Microcontroller
Производитель : Texas Instruments
цоколевка :
Описание :
The F2806x Piccolo™ family of microcontrollers (MCUs) provides the power of the C28x core and CLA coupled with highly integrated control peripherals in low pin-count devices. This family is code-compatible with previous C28x-based code, and also provides a high level of analog integration.
An internal voltage regulator allows for single-rail operation. Enhancements have been made to the High Resolution Pulse Width Modulator (HRPWM) module to allow for dual-edge control (frequency modulation). Analog comparators with internal 10-bit references have been added and can be routed directly to control the ePWM outputs. The ADC converts from 0 to 3.3-V fixed full-scale range and supports ratio-metric V REFHI / V REFLO references. The ADC interface has been optimized for low overhead and latency.
Official Site : http://www.ti.com/product/tms320f28069
даташит PDF Download
Другие с той же файл данные :