Feed aggregator
Facebook Questions – the ultimate answer to life, the universe, and everything – or an online reputation disaster waiting to happen?
What implications does the new feature of Facebook Questions have for our online reputation of our business or our personal brand?
In the last 24 hours Facebook has been rolling out it’s ‘Questions’ functionality – you will see it on the left hand side of your Home Page or at the top of your Profile or Business Page.
the Answers and Questions feature of Linkedin have been a great way to build online visibility and be a source of lead generation for a number of years. This move by Facebook is another example of them looking to have people spend more time in their company and become a source for information and research about questions we have.
One of the most powerful features is that you can post a reply to a Question as the name of your ‘Facebook Page’ – unlike when you comment on a Facebook Profile or Facebook Page.
Here is a quick video review of the Facebook Questions feature which I published today over on my Biz Growth Media Facebook Page.
You can also ‘follow questions’ and edit the answers to the questions that you respond to.
However one potential disadvantage is that when people click on the links to the questions you ask using the ‘Questions’ feature it will take people away from your Facebook Page.
If you are monitoring your online reputation on Facebook it will be important for you to start to listen to the questions being asked and answered.
When you post an answer or a question it will be seen by the whole of the Facebook community irrespective of your Facebook Profile privacy settings – so be careful what and how you ask and answer questions.
More details about Facebook Questions are here on the Facebook blog.
Remember the novel The Hitchhiker’s Guide to the Galaxy by Douglas Adams where the answer to the ultimate question of life, the universe, and everything was 42 – perhaps Mark Zuckerberg is looking for that book to be re-written – and the answer now being Facebook.
What are your thoughts about Facebook Questions?
ADDITIONAL RESOURCES
Access my FREE Facebook webinars about using Facebook Pages and Facebook Advertising
Access my guide to Facebook Pages best practice guide for colleges and universities
Perhaps Facebook not where your potential clients are networking online? If they are using LinkedIn you might want to access my FREE LinkedIn for business – make sure that you leave a valid email address so that you can access a discount off my forthcoming 4 week programme starting the 9 August 2010 called “LinkedIn for Business Leads and Profits”. The discount is valid until the 31 July 2010.
Share on Facebook var button = document.getElementById('facebook_share_link_1849') || document.getElementById('facebook_share_icon_1849') || document.getElementById('facebook_share_both_1849') || document.getElementById('facebook_share_button_1849'); if (button) { button.onclick = function(e) { var url = this.href.replace(/share\.php/, 'sharer.php'); window.open(url,'sharer','toolbar=0,status=0,width=626,height=436'); return false; } if (button.id === 'facebook_share_button_1849') { button.onmouseover = function(){ this.style.color='#fff'; this.style.borderColor = '#295582'; this.style.backgroundColor = '#3b5998'; } button.onmouseout = function(){ this.style.color = '#3b5998'; this.style.borderColor = '#d8dfea'; this.style.backgroundColor = '#fff'; } } }What Mad Men Gets Right About Innovation
Women on the web: 6 insights from the comScore report on how women are shaping the Internet
Do women and men interact differently online is a question I often get asked. Well here is some research that will help us all when considering how best to connect to our community online.
comScore, Inc. has today released a global report how women interact with the web called, “Women on the Web: How Women are Shaping the Internet” – it’s an extensive analysis of how women are are interacting online across social networks, online video, mobile communications, online retail trends and a number of other key areas.
The report comments that social networking sites reach a higher percentage of women than men globally, with 75.8 percent of all women online visiting a social networking site in May 2010 versus 69.7 percent of men.
Here are a few conclusions I drew from the comScore report.
1. Don’t just look to connect and reach women on women’s magazines, celebrity gossip and baby sites – the report comments that “women are more engaged than men on the Internet -you just have to know where to look”. Think beyond the obvious suspects when looking for online communities where you can reach the female consumer.
2. If you want to connect with women you need to understand how they interact in social networks – the report states “social networking is central to women’s Internet experience”. Women of all ages connect on social networks sharing photo’s, playing games, and watching online video. Globally, women spent an average of 16.3 percent of their online time on social networks in April 2010, compared to only 11.7 percent for the men.
3. Women in the US control the cash – more women than men get engaged with online transactions and collectively spend more.What does this mean then when it comes to the tone and content of your online marketing?
4. Act global but understand local influences – we need to deep our understanding of regional and cultural differences impact in Internet behaviour. The report goes into some depth about differences they have found across the globe.
5. Stop making the excuse that Social Networking is only relevant if you are marketing to a youth audience - the 45+ female segment is driving the greatest proportion of growth for Social Networking sites, in terms of both visitation and time spent. Yes the 15-24 may use these sites more frequently and use them more however the 45+ age group visit and use Social Networking sites just as much as the 25-34 and 35-44 age groups.In fact older women are using Social Networks significantly more than men do. In North America, with 9 out of 10 female Internet users visiting a social network site in April 2010.
6. Men and Women use Twitter differently – the report comments that in an April 2010 comScore survey, men were found to be more likely to post their own Tweets than women; women on the other hand used Twitter more to find deals and promotions, as a place for conversing online and to follow celebrities.How does that change your content strategy for Twitter?
What other research and insights have you found about how female consumers use the web and how is it influencing your online marketing, PR and communications? What other insights did you glean from the comScore report?
Share on Facebook var button = document.getElementById('facebook_share_link_1846') || document.getElementById('facebook_share_icon_1846') || document.getElementById('facebook_share_both_1846') || document.getElementById('facebook_share_button_1846'); if (button) { button.onclick = function(e) { var url = this.href.replace(/share\.php/, 'sharer.php'); window.open(url,'sharer','toolbar=0,status=0,width=626,height=436'); return false; } if (button.id === 'facebook_share_button_1846') { button.onmouseover = function(){ this.style.color='#fff'; this.style.borderColor = '#295582'; this.style.backgroundColor = '#3b5998'; } button.onmouseout = function(){ this.style.color = '#3b5998'; this.style.borderColor = '#d8dfea'; this.style.backgroundColor = '#fff'; } } }"Waiting for Superman" - See the Movie
I think a lot of people will become emotionally moved by watching this movie. The film's creators hope that leads more people to get involved in public education issues.
To me, “Waiting for Superman” was 90 minutes of “preaching to the choir” showing the costs of poverty, the costs of prison vs education, the impact on the American economy caused by our education system falling behind those in other countries.
Its conclusion was “better teachers” are needed.
Its message was, “there are lots of parents who really want to send their kids to good schools, but there are not enough good public schools, and not enough open slots in good charter schools.”
If you visit this section of the Tutor/Mentor Connection library, you can find links to many web sites with more information on poverty, poorly performing school, the drop-out crisis, etc.
I’ve been reading articles like this for the past 35 years. Why? Because I became personally involved with an inner city boy as a volunteer in a non-school tutor/mentor program and I stayed involved for the past three decades. The longer I became involved, the more I was exposed to articles about poverty, and the more personally committed I became to helping the kids I was working with.
Because I was leading a program, not just serving as a tutor, I had to step back a level, and think of ways to recruit kids and volunteers at the beginning of the school year, and keep them connected to each other throughout the year. Because I was a volunteer with limited time, I had to innovate ways to motivate other volunteers to share part of the leader load.
Because of my workplace experiences in corporate advertising at the Montgomery Ward Corporation, I began to understand how mass communications could be used to support groups of 200 or more volunteers. I began to understand how computers could be used to build attendance sheets and to analyze participation patterns. I also began to see how media coverage of poverty might draw a lot of attention for a short time, but it did not provide the type of consistent support that retail stores need to build a customer base, and that non profits need to build a volunteer and donor support system.
I would not have been at Waiting for Superman if I had not been part of a non-school tutor/mentor program and if I had not been using the internet to connect people involved with tutoring/mentoring in Chicago with similar programs in other cities, and if I were not building a library of information that people could use to become better informed of ways they could become involved to help kids from poverty move through school and into jobs.
After I saw the movie, I visited the Waiting for Superman web site at http://www.waitingforsuperman.com . I encourage you to do the same, and then take a group of friends to see the movie.
The web site is intended to act as an intermediary, drawing people to a GET INVOLVED page, and pointing them to other web sites where they could learn more about the problem and become part of the solution. It divides into two sections:
Take Action: Help a School
In this section the message is “act locally”…meaning support your local school. This is good advise, but it won’t do much to change the performance of inner city schools located in high poverty neighborhoods unless more people from beyond poverty are giving time, talent and dollars every day to help people who do live in poverty neighborhoods.
This is one of the shortfalls of the movie that I saw. Most of the young people portrayed in the film were minority kids living in inner city neighborhoods of big cities like LA, Houston and New York City. The kids featured in the movie attend public schools in poverty areas, and have a parent, or guardian, who would pay for better education if they had the money.
They might also do more to show kids the importance of college, if they had a college degree themselves. But that’s what poverty is all about. It’s people who don’t have high paying jobs, college degrees, etc. How can they be providing the dollars to help teachers? How can they find the time to be mentors? How can they model jobs and college if they have not finished school themselves?
The solutions proposed in this section don’t show how people who don’t live in high poverty might be personally involved in helping youth and families who do. The actions proposed don’t take in consideration the geography of poverty and poor schools and don’t provide a road map for Superman to go from neighborhoods of affluence to neighborhoods of poverty.
This section does include a “be a mentor” link that points to the web site of the National Mentoring Partnership. However, it does not say “be a donor” so more mentoring programs might have the staff and infrastructure to add more volunteers, and provide high quality mentoring to those they already have. This is a missed opportunity in my estimation.
Fix the System –
This is the second section in the Take Action section. There are links in this section that focus on education standards, the Dept. of Education Race to the Top competition and getting involved with a local school board.
There is also a link to a Dept. of Education Innovation Portal, where anyone can submit ideas and connect with others who have submitted ideas. This has potential. I introduced the Tutor/Mentor Connection and posted a request for help in funding our maps and technology. I’ll let you know if I get any responses.
There’s also a section titled “Join a discussion” which points to the Edutopia community forum where people can join in discussion with others on education issues. I also joined this forum and introduced myself. I did not see any section that was focused on helping non-school organizations be available around poorly performing schools, so I emailed Edutopia to suggest they add such a section.
In total, I think Waiting for Superman has a lot of potential for increasing the number of people motivated to "fix the public education system", but the web site is missing some major opportunities.
Understand the issues and opportunities –
I think there are a broader range of web sites where you can learn more about the problems of our education system, and the poverty causing some schools to perform less well than others, and potential solutions. A starting point in your learning would be the Tutor/Mentor Connection library, where we point to more than 1600 resources such as these in our Research and Resources category.
Volunteer involvement, expanding the number of people who personally care.
I think the movie, and the forums, are efforts to engage people who care in discussions and actions that lead to solutions. However, these don’t provide enough entry points to get adults who don’t live in poverty personally connected with youth and families. In a recent study titled "Untapped Potential: Filling the Promise of Big Brothers Big Sisters and the Bigs and Littles they Represent, the authors point out how there were more than 240,000 active BBBS volunteers in 2009, and that many of them have become more concerned about the challenges facing the kids they mentor, because of their involvement as a mentor.
Thus, strategies that encourage more volunteering in well organized volunteer-based tutor/mentor programs would be ways to increase the number of people watching movies like Waiting for Superman, and spending time to “fix the system”.
However, for that to happen a more consistent flow of operating dollars needs to be going to every single program so they can recruit and retain leaders who can effectively mentor the mentors so they stay involve, build this level of empathy, then grow to be leaders who reach into their own business, alumni, faith and personal networks to get even more people involved.
This is what the Tutor/Mentor Connection focuses on. We're not yet listed as one of the resources on the Waiting for Superman web site. We're not yet invited to any planning meetings by CEO Ron Huberman of Chicago Public Schools. We’re not on their radar.
However, that can change. If you know about our work, or read this blog, pass on this message to leaders in your own network, the way Sara Caldwell did on this web site.
We can bring supermen and women to inner city neighborhoods by what we do to encourage people who have the talent and the resources to help this strategy grow in Chicago and other cities.
Thank you to Waiting for Superman for helping draw attention to this issue.
The fear economy.
Three new Facebook resources for personal and professional guidance for the media, journalists and PR professionals
Here are three new resources from Facebook that I think you will find of interest:
1. A new Page about Facebook Safety to provide you with updates and information to keep you and your family safe while using Facebook or surfing on the Internet. This compliments the Facebook Security Page.
2. A Facebook Page for PR professionals where the Facebook team share what they have learned about creating social content, promoting events, optimising Pages, and integrating with tools off of Facebook – it looks as though this will be a great resource for PR an marketing people alike. Check out the hour long video recording of a live event held last week at Facebook HQ in the US with information about using Facebook advertising and live streaming
3. A Facebook Page for the Media where they are providing guidance and tips for media outlets in terms of best practices and tools to drive referral traffic and increase engagement on your site. They are recommending all journalists should have a Facebook Page, and provide tips about running events, adding Facebook social plugins and how to use Facebook search to monitor conversations.
ADDITIONAL RESOURCES
Access my FREE Facebook webinars about using Facebook Pages and Facebook Advertising
Access my guide to Facebook Pages best practice guide for colleges and universities
Perhaps Facebook not where your potential clients are networking online? If they are using LinkedIn you might want to access my FREE LinkedIn for business – make sure that you leave a valid email address so that you can access a discount off my forthcoming 4 week programme starting the 9 August 2010 called “LinkedIn for Business Leads and Profits”. The discount is valid until the 31 July 2010.
Share on Facebook var button = document.getElementById('facebook_share_link_1842') || document.getElementById('facebook_share_icon_1842') || document.getElementById('facebook_share_both_1842') || document.getElementById('facebook_share_button_1842'); if (button) { button.onclick = function(e) { var url = this.href.replace(/share\.php/, 'sharer.php'); window.open(url,'sharer','toolbar=0,status=0,width=626,height=436'); return false; } if (button.id === 'facebook_share_button_1842') { button.onmouseover = function(){ this.style.color='#fff'; this.style.borderColor = '#295582'; this.style.backgroundColor = '#3b5998'; } button.onmouseout = function(){ this.style.color = '#3b5998'; this.style.borderColor = '#d8dfea'; this.style.backgroundColor = '#fff'; } } }What to do when faced with a boring client
Here’s a question I get all the time when I am running business development training courses:
“What do I do when the person I am speaking to is boring?”
In essence, business development for lawyers is all about building trusting relationships. The quickest and most sure-fire way to build trust is to spend more time listening than speaking. To be a good listener you need to be a good questioner and learn to ask about things that get people interested and speaking about subjects that matter to them.
Or, as Mark Hunter commented in his Slaw column last week: ”ever notice that people do business with people they like?” Being a good listener is the fast track to being likeable.
So what happens when you can’t listen? What do you do if you find your client or important contact boring?
Faking interest never works. And just imagine being on the receiving end with someone looking at you with boredom. The natural reaction is to feel insulted and to then judge the person to be arrogant, aloof and yes, unlikeable.
The answer: It’s up to you to find what is interesting about the person. Push aside your judgemental inner voice and place your focus firmly on the other person. Everyone is interesting, your job is to uncover this. Use questions to get the person speaking about things that are important to him/her. Follow your curiosity. The goal here is to listen and discover, not to prove how interesting you are. Some sample questions that can open up a conversation are:
- How did you get into being a …. ?
- What are you looking forward to this weekend?
- I’m curious, what made you decide to… (go to that school, travel to Palm Springs, etc.)
Another approach is to ask for advice when the opportunity arises. The majority of people enjoy teaching.
Take me for example. I don’t golf. I have never held a gold club. What do I do when faced with an avid golfer? Instead of getting bored and shifting the subject, I dig into it. I confess my general ignorance and then ask to be enlightened. What are the best golf courses in town? Has it been good for business development? What’s the best age to start kids in the sport? What have been the best golf courses they have ever played on? What I discovered is that while I am not interested in the sport I am interested in what people like about it and get out of it.
The bottom line: it’s up to you to turn it around. It is in your power to turn boring into interesting.
When you show you are interested and really listen to the person you will distinguish yourself from the majority of people who do not. The end result is that the person will then likely become interested in you and it will be your turn to tell your story.
My favorite resource on all things to do with listening is Just Listen by Dr. Mark Goulston. He reminds us all that we are responsible for our own degree of interest with this quote:
“Boredom is what happens when I fail to make someone interesting.” Warren Bennis, Founding Chariman, USC Leadership Institute
Get a job, or go to grad school?
Parents Support Tutor/Mentor Program. Can you?
Year-End Dinner 2010: Parent Speakers from Cabrini Connections on Vimeo.
See the Donor Page on the Cabrini Connections web site to see ways to contribute.
Visit the Tutor/Mentor Jam web site and see ways you can help us support the growth of tutor/mentor programs in all poverty areas of the Chicago region.
Could Small Banks See More Lending Opportunities In The Near Future?
When will unemployment checks be mailed? Not soon.
'ENOUGH IS ENOUGH' - SunTimes' front page
In the article Chicago Police Supt. Jody Weis is quoted saying “So I say, enough is enough. We are coming for you. We will find you, and we will bring you to justice.”
The article also quotes St. Sabina’s pastor, the Rev. Michael Pfleger, who said "it’s not enough to pray, not enough to lower flags every time an officer is killed."
How many times must we read the same headlines? How do we move beyond the prayers, marches and flag-lowering, to the research, planning, brainstorming and action steps that are needed?
On Thursday, October 08, 2009, Arne Duncan was quoted as saying, "This is the time to look in our collective mirror and ask whether we like what we see or whether we can do better together."
This is not a new problem. However, it's a problem that our leaders can't stay focused on every day, because there are so many other problems.
That's why I think it's important for another level of leaders to emerge, who are totally focused on building a better community understanding, and response, to the problems and solutions.
I've been issuing this invitation for the past 17 years, since we formed Cabrini Connections, Tutor/Mentor Connection, in the weeks following the shooting of Dantrell Davis in Chicago back in October 1992. I keep the front page of this Chicago SunTimes story in my office, as a reminder of my responsibility.
I've developed my own actions steps, and posted them on this blog in the past. Here they are again:
If we want to stop this violence, we have to act now, and keep acting to solve this problem for many years. We have to think spatially, that is, look at the entire city and suburban problem, not just one neighborhood. At the same time, we need to act locally, because none of us has the time, or the resources to help each of the kids in the entire Chicago region who live in neighborhoods where poverty is the root cause of the violence.
Here are some ways to remind yourself. Think of ENOUGH, is ENOUGH
E – educate yourself – most of us do not live in high poverty neighborhoods, so we only understand the root causes of senseless shootings from what we read in newspapers. We also only read negative news in the media, so we’re now really well informed on where these events are taking place most frequently. Finally, while there is a perception that there are plenty of youth programs, we really don’t have a good understanding of the distribution of different types of youth programs, to different age groups, in different zip codes. The only way this will change is if each of us pledges to spend one hour a week reading books, articles and web reports, that illustrate the root causes of these shootings, or of poor performance in schools. Through our learning we can draw ideas that we use in our own actions. We can also begin to contribute information that other people use to support their own decision making.
N – engage your network – find ways to draw others who you know into this shared understanding. Recognize people who volunteer time and talent, or who help kids through the programs they operate. If you are a business leader, or a church leader, engage your corporation or your congregation. You can use your web site, advertising, point of purchase materials, etc. to point to web sites that show all of the agencies in the city who do tutoring/mentoring, such as www.tutormentorconnection.org. If you do this weekly, year after year, your friends, coworkers and customers will become involved in solving this problem with you.
O – offer help, don’t wait to be asked. As you build your understanding of where poverty is most concentrated, and what social services are in those areas, choose a neighborhood, and reach out with offers of time, as a volunteer, talent, help build a web site, do the accounting, or offer Public relations services, and dollars, if the web site of an organization shows they do good work, you don’t need to ask for a proposal of h ow they would spend your donation, you need to send them a donation so they can keep doing that good work
U – build a shared understanding. Form groups of peers to share reading and learning assignments, just as you meet every Sunday to read passages of scripture and build the group’s understanding of the Word of God. Use the many different resources of the T/MC Links library as the starting point for your search for wisdom, and understanding.
G – give until it feels good – people who generously donate time and dollars to causes they believe in feel good about their giving. If we’re going surround kids living in poverty dominated neighborhoods with extra learning and adult mentoring networks, donors will need to give more than random contributions of time, dollars and talent. On the Bolder Giving web site donors are inspired to give to their full potential and those giving 50% or more are given recognition. Can we inspire donors who support youth services to give at this level?
H – form habits of learning, and pass these on to your kids. Imagine how much more successful teachers were if youth came to school every day asking questions about where to find information, or how to understand information they had researched on the Internet the previous day? We can model that habit if we build it into our own activity. Keep a chart, such as the OHATS on the Tutor/mentor connection web site, where you can document actions you take each week to same sure that this time ENOUGH, really means ENOUGH.
If you document actions, you can review what you’ve done at the end of each month, and each year, and begin to see a growing mountain of actions you have taken to solve this problem. Some of these will be actions that got other people involved, so that the good work you do is multiplying because of the good work others are also doing.
Through this process you help build this shared understanding, which will lead to better public policy. Without this habit of learning, and without learning to use the Internet to find good ideas from people in all parts of the world, we won’t be able to problem solve as well as we need to, and we won’t be able to teach this habit to our kids.
If we do this, we’ll not only reduce the root causes of youth on youth violence, we’ll also address one of the growing issues facing America in a global economy. We will begin to create a nation of learners, problem solvers, creative thinkers and innovators, who use learning and information as the basis of creating opportunity and keeping America great.
Read Leadership ideas here and here
Here are other articles I've written on this topic in the past few years.
5 Mistakes Online Job Hunters Make
Article in NY Times: Graduation Is the Goal, Staying Alive the Prize
This article talks about the muti-million dollar program launched by Chicago Public Schools to "get ahead of the next killings". According to the article, "the schools conducted an analysis to identify the 250 students most at risk of being shot (by studying profiles of 500 recent victims). Since December, each of those students has had an advocate on call to offer caretaking and support 24 hours a day, seven days a week.
The 60 advocates hired so far function like a high-energy amalgam of parent, tutor, friend and life coach, sometimes tackling simple assignments like homework. But more often they delve into the heart-wrenching details of the students’ lives. More than one has sat bedside in a hospital emergency room after bullets ricocheted through a charge’s body."
This is great if the money is there to keep these advocates connected to these kids for the next few years.
The Times article quotes Ron Huberman, CEO of Chicago Public Schools, who says, “Giving them a meaningful adult relationship, advocating for them and giving them incentive is the key to changing their behavior, since some of the students most at risk of being shot are also most likely to perpetrate violence."
According to the report, "Each advocate is assigned no more than four students and is paid $12 an hour for one-on-one time with the students."
What’s wrong with this picture?
There are 200,000 k-12 youth living in high poverty areas of Chicago, and thousands are at risk because of this long-term combination of highly concentrated poverty, racial segregation, and poor schools.
Spending millions of dollars on 250 of these students without a comprehensive plan to expand the number of other students who have “meaningful adult relationships” that Huberman describes, is short sighted.
What type of skills and experiences is a $12/hour mentor/advocate bringing to this job? What networks do they have to open doors at colleges or in area jobs for the young people they are working with?
At Cabrini Connections and at other volunteer-based tutor/mentor programs in Chicago, students are also connected to adults who are forming “meaningful relationships”. However, these are adults who hold a variety of jobs, ranging from high paid attorneys, to software engineers, artists and film makers. Many are already college graduates. Some hold advanced degrees. They don't live in poverty. They come from many different parts of the country. They can model opportunities and careers and aspirations for these young people, because they already have these jobs and experiences.
What kind of experience does a $12 hour social worker/mentor/advocate have? Are they still connected and committed to these young people when the money runs out to pay them? Are they still connected 37 years after their first contact, as I am with the boy I met in 1973 when he was in 4th grade?
Not every volunteer stays connected to a youth for as long as I have. In fact many don't stay involved for more than a year. And many are not as well supported as they need to be.
Why? The non-school tutor/mentor industry has the same challenges as the public school system. Not enough good leaders. Not enough well-trained and committed volunteers in tutor/mentor roles.
However, as this article shows, mentoring connects adults who might never be involved with issues of poverty, with kids, and then opens their eyes to the challenges those kids face. If we can expand the support for well-organized tutor/mentor programs, we can expand the number of volunteers who get involved, and stay involved. We can expand the number of people who are concerned about the violence in big cities and the poor schools that feed this problem.
Read the articles on this blog and follow the links. Learn how you, your company and your faith group can take lead roles to help make volunteer-based tutor/mentor programs available in more of the neighborhoods with high poverty, high violence and high numbers of poorly performing schools.
Then help mobilize resources for each of these programs to be operating this fall, and to constantly learn from each other, and from their own work, so they are constantly expanding their impact.
If you can help find donors to support the Tutor/Mentor Connection, we can continue to provide our own vision and leadership to this effort and we can continue to provide the Chicago Tutor/Mentor Program Locator resource to everyone in Chicago.
Preprocessor seams and assignment of responsibility
- The outer-most list represents “rows”. It collects all objects found. It has zero or more entries.
- The inner-most list represents a single field. It is a key value pair. It is a list of size 2. The first entry is the name of the field (column to FitNesse). The second field is the value. Both are strings.
- The middle list represents a single object. It is a collection of fields. It has zero or more entires.
I understand the need for this representation and it takes a little bit to get it built correctly. So much so, I built a simple tool to do it in java.
C++ is no different. In fact, the authors of cslim though the same thing and they created a C Abstract Data Type to help out (and an add-on method to create the correct final form):
- SlimList
- SlimList_Serializer
They use C because it can be used by both C and C++. I’m using C++ and I wanted to make building query results even easier, so I built a QueryResultAccumulator. The most recent source is in the previous blog and I’ll be putting it on github after I’ve had some more time to work on it.
Here’s the progression to my QueryResultAccumulator class:
- Wrote a Query-Table based fixture and followed the example provided with cslim (thank you for that!)
- Moved the code from functions into methods on a class
- Extracted a class, called SlimListWrapper, which made the fixture code easier to follow.
- Went to get takeout and realized that I had named the class incorrectly and that it was really accumulating query results (thus the name). The SlimList was a mechanism, not an intent.
- Refactored the class into QueryResultAccumulator (I left the original alone, created a new class, copied code from one to the other and changed it around a bit.
Now it might sound like I didn’t have any tests. In fact, I did. I had my original Acceptance Test in FitNesse. I kept running that, so in a sense I was practicing ATDD.
I was not happy with that, because I was not sure that I had properly handled memory allocation correctly. In fact, I had not. The final result is dynamically allocated and I was not releasing that. So I “fixed” it. (It needs to be released after the return from slim back to FitNesse, so the typical pattern is to lazily delete it, or release it in a “destroy” method called after the execution of a single table.)
I have a memory leak?! I am simplifying this story a bit. So I’m skipping some intermediate results. Ultimately I wrote the following test to check that you could use a single query result accumulator for multiple results correctly: TEST(QueryResultAccumulator, CanProduceFinalResultsMultipleTimes) { QueryResultAccumulator accumulator; accumulator.produceFinalResults(); accumulator.produceFinalResults(); }This caused a memory leak of 60 bytes. It was at this point I was up too late and banging my head against a wall. About 3 hours later I figured that out and went to bed. I fixed the problem and sent a patch to authors of cslim in maybe 45 minutes. So I should have gotten more sleep.
Where is that damn thing In any case, I visually checked the code. I debugged it. I did everything I could initially think of, and I was convinced that my code was correct. (As we’ll see it both was and was not due to a preprocessor seam in cslim.) I got to the point where I even tried different versions of gcc. (I found a parsing error in g++ 4.5 when handling templates, so in desperation and late at night I wasted 5 minutes switching my compiler.) I had the following code in my class: if(result) free(result);This was the correct thing, but it was in the wrong location. Again, this was related to a preprocessor seam in cslim.
Eureka! I looked at the cslim code and confirmed it was doing basic C stuff, nothing surprising. It was at that point that I remembered something important: cslim depends on CppUTest and uses a different malloc/freeAh ha! That’s it. So I tired to recompile my C++ code to use the same thing. However, I was not able to do that. CppUTest’s memory tracking implementation does not work with many of the C++ standard classes like <string> and <vector>. So I could not compile my code using the same approach.
I’m glad this happened becuase it made me realize that it was the wrong place anyway. Here’s the logic:
- CSlim has a preprocessor seam, comile with or without -Dfree=cpputest_free, -Dmalloc=cpputest_malloc
- I’m using a class in cslim to do the allocation, where the policy of allocation is stored
- I should not release the memory but instead allow the cslim library to release the memory becaue it has the allocation policy, and therefore the release policy.
I updated my QueryResultAccumulator to use SlimList_Release and my false positive disappeared.
It also turns out that this improved symmetry in the library. To allocate and release entries in an SlimList you use the following functions:
- SlimList* SlimList_Create()
- void SlimList_Destroy(SlimList*);
Now to serlalize a list and release the memory later you use:
- SlimList_Serialize
- SlimList_Release
As I write this, I think there’s a better name. I’ll let the authors give it a better name (like SlimList_Release_Serialization_Results). But in any case, if you use a function in the cslim library that allocates something, you use another method in the cslim library to release it.
Since the libray has a preprocessor seam, that symmetry removes a false-positive memory leak.
What took so long? I had an interesting time with this. Originally I had not released that memory in the class but rather in the unit test. I was working too late and not thinking clearly. I realized that my class needed to manage that.When I called free in the unit test, it was calling the correct version of free, cpputest_free, becasue it was a unit test using CppUTest. When I moved the code into the class, which has no knowledge of CppUTest (nor can it), the flow of the code was correct, but the compilation (preprocessor symbols) were different and it caused a false positive.
Since I changed the code, I assumed it was a problem with how I changed the code. To me more clear, I though it was a code-flow problem, not a preprocessor seam problem. So I spent a lot of time verifyig my code. Once I determined it was correct, I then moved into debugger mode.
It was not long after that when I finally figured out what was going on.
Conslusions As with many things in life, this is intuitive once you understand it!-)That cslim depends on CppUTest might be questionable. However, if I treat cslim as a (mostly) black box, and I don’t know its allocation policy, I should not assume a deallocation policy.
By putting the responsiblity in the correct library level, it fixed the problem and added symmetry to the overall solution.
I also really enjoyed this (after it was done). I’ve come across memory leaks using CppUTest in the past. Often they were my fault. Sometimes they were not. This was interesting because it both was and was not my fault. I originally had written the code incorrectly. When I put he correct steps in my code, I still had wrong code because I put the responsibility in the wrong place. It really was only correct after I moved the actual implementation into the library and then called it from my code that I had finally written it correctly.
5 best practice tips when building a community using Facebook Pages
Did you hear the news? Yesterday Facebook announced that now some 500 million people are actively using Facebook from across the globe.
I recently noticed a post from Jeremiah Owyang asking the readers of his blog for their input on Facebook marketing best practice.
Here is the feedback I shared:
1. Understand the online habits of your community – identify when your community are online so that you can time your Facebook update so that it has a chance to appear when they log on in their feed on their home page without too much scrolling. This simple online visibility tip could increase the possibility of them engaging with your update
2. Manage the frequency of posting – Take care not to publish content too frequently to your Facebook Page – if all people can see on their Facebook home page feed is your updates not their friends they may ‘unlike’ your Facebook Page or hide your feed
3. Don’t forget to promote your Page – When starting a Facebook Page we have found that also investing in engagement ads (on the home page of Facebook) has assisted in increasing the visibility and number of people joining your community quickly
4. Post relevant refreshing content – Keep your competitions relevant to the community on your Facebook Page. This may seem obvious but it is often overlooked. Your competition does not have to be for something that has an expensive price tag – but it is something valued by your community. Note – if you are hosting a competition or give way, make sure you comply with the guidelines for promotions and competitions (there are many brands who don’t and risk their Facebook Page being deleted)
5. Make it easy to do business with your app – When adding applications make sure you test it for useability – too many clicks as part of the process and people won’t add your application and if it’s not easy to use and does not add value (or fun) to them your Facebook app will remain a secret.
But what ideas would you add?
ADDITIONAL RESOURCES
Access my FREE Facebook webinar about using Facebook Pages
Access my FREE Facebook webinar about Facebook Advertising
Access my guide to Facebook Pages best practice guide for colleges and universities
Perhaps Facebook not where your potential clients are networking online? If they are using LinkedIn you might want to access my FREE LinkedIn for business – make sure that you leave a valid email address so that you can access a discount off my forthcoming 4 week programme starting the 9 August 2010 called “LinkedIn for Business Leads and Profits”. The discount is valid until the 31 July 2010.
Share on Facebook var button = document.getElementById('facebook_share_link_1828') || document.getElementById('facebook_share_icon_1828') || document.getElementById('facebook_share_both_1828') || document.getElementById('facebook_share_button_1828'); if (button) { button.onclick = function(e) { var url = this.href.replace(/share\.php/, 'sharer.php'); window.open(url,'sharer','toolbar=0,status=0,width=626,height=436'); return false; } if (button.id === 'facebook_share_button_1828') { button.onmouseover = function(){ this.style.color='#fff'; this.style.borderColor = '#295582'; this.style.backgroundColor = '#3b5998'; } button.onmouseout = function(){ this.style.color = '#3b5998'; this.style.borderColor = '#d8dfea'; this.style.backgroundColor = '#fff'; } } }Some C++ Fixtures for FitNesse.slim
I continue working on these. I was stuck in the airport for 5 hours. Between that and the actual flight, I managed to create three different test examples against a C++ RpnCalculator. Each example uses a different kind of fixture. I had a request from @lrojas to publish some results on the blog. So this is that, however these are in progress and rough.
I’m still trying different forms to figure out what I like the best.
By the way, that lastValue stuff in the fixtures has to do with the fact that all of the hook methods return a char* but I’m responsible for cleaning up after myself.
A Decision Table !|ExecuteBinaryOperator | |lhs|rhs|operator|expected?| |3 |4 |- |-1 | |5 |6 |* |30 | And Its Fixture Code #include <stdlib.h> #include <stdio.h> #include <string> #include "RpnCalculator.h" #include "OperationFactory.h" #include "Fixtures.h" #include "SlimUtils.h" struct ExecuteBinaryOperator { ExecuteBinaryOperator() { lastValue[0] = 0; } int execute() { RpnCalculator calculator(factory); calculator.enterNumber(lhs); calculator.enterNumber(rhs); calculator.executeOperator(op); return calculator.getX(); } static ExecuteBinaryOperator* From(void *fixtureStorage) { return reinterpret_cast<ExecuteBinaryOperator*>(fixtureStorage); } OperationFactory factory; int lhs; int rhs; std::string op; char lastValue[32]; }; extern "C" { void* ExecuteBinaryOperator_Create(StatementExecutor* errorHandler, SlimList* args) { return new ExecuteBinaryOperator; } void ExecuteBinaryOperator_Destroy(void* self) { delete ExecuteBinaryOperator::From(self); } static char* setLhs(void* fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); self->lhs = getFirstInt(args); return self->lastValue; } static char* setRhs(void* fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); self->rhs = getFirstInt(args); return self->lastValue; } static char* setOperator(void *fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); self->op = getFirstString(args); return self->lastValue; } static char* expected(void* fixture, SlimList* args) { ExecuteBinaryOperator *self = ExecuteBinaryOperator::From(fixture); int result = self->execute(); snprintf(self->lastValue, sizeof(self->lastValue), "%d", result); return self->lastValue; } SLIM_CREATE_FIXTURE(ExecuteBinaryOperator) SLIM_FUNCTION(setLhs) SLIM_FUNCTION(setRhs) SLIM_FUNCTION(setOperator) SLIM_FUNCTION(expected) SLIM_END } There’s a bit of duplication. I’ve been experimenting with pointers to member functions and template functions to make it better. I really should be using lambdas, but I’m not there yet. I have them available in some form since I’m using gcc 4.5. I simply compile with the option -sdd=c++0x. Even so, I’m not quite ready to do that. A Script Table !|script |ProgramTheCalculator | |startProgramCalled|primeFactorsOfSum | |addOperation |sum | |addOperation |primeFactors | |saveProgram | |enter |4 | |enter |13 | |enter |7 | |execute |primeFactorsOfSum | |check |stackHas|3|then|2|then|2|then|2|is|true| And Its Fixture Code #include <stdlib.h> #include <stdio.h> #include <string> #include "RpnCalculator.h" #include "OperationFactory.h" #include "SlimUtils.h" #include "SlimList.h" #include "Fixtures.h" struct ProgramTheCalculator { ProgramTheCalculator() : calculator(factory) { } static ProgramTheCalculator* From(void *fixtureStorage) { return reinterpret_cast<ProgramTheCalculator*>(fixtureStorage); } OperationFactory factory; RpnCalculator calculator; }; extern "C" { void* ProgramTheCalculator_Create(StatementExecutor* errorHandler, SlimList* args) { return new ProgramTheCalculator; } void ProgramTheCalculator_Destroy(void *fixture) { delete ProgramTheCalculator::From(fixture); } static char* startProgramCalled(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self->calculator.createProgramNamed(getFirstString(args)); return remove_const(""); } static char* addOperation(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self->calculator.addOperation(getFirstString(args)); return remove_const(""); } static char* saveProgram(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self->calculator.saveProgram(); return remove_const(""); } static char* enter(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self->calculator.enterNumber(getFirstInt(args)); return remove_const(""); } static char* execute(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); self->calculator.executeOperator(getFirstString(args)); return remove_const(""); } static char* stackHasThenThenThenIs(void *fixture, SlimList *args) { auto *self = ProgramTheCalculator::From(fixture); for(int i = 0; i < 4; ++i) { if(self->calculator.getX() != getIntAt(args, i)) return remove_const("false"); self->calculator.executeOperator("drop"); } return remove_const("true"); } SLIM_CREATE_FIXTURE(ProgramTheCalculator) SLIM_FUNCTION(startProgramCalled) SLIM_FUNCTION(addOperation) SLIM_FUNCTION(saveProgram) SLIM_FUNCTION(enter) SLIM_FUNCTION(execute) SLIM_FUNCTION(stackHasThenThenThenIs) SLIM_END } This one is a bit more regular. I am using the updated auto keyword in this code. The fixture is just holding the calculator and its OperationFactory (not my preferred name, but that’s what students wanted to call things like +, -, etc, operations not operators). The Dreaded Query Table It’s a bit of a pain to produce query results. So much so, I wrote a simple library in Java to make it easier. I can create a well-formed query result from a single object or a list of objects and even do basic transforms (in names and in paths to data). I started using the jakarta bean utils, but my use was so simple (2 methods), I ripped out that library and just hand-wrote the methods I needed. It was not a case of “not invented here syndrom.” I started by using the library, and I had tests. I didn’t like the size of the library relative to how much I was using it, so I just got rid of it.Well here I am working C++ and I felt compelled to make it easier work with query results in C++.
First the FitNesse table, then the fixture and finally the support class. I have tests for it as well, I’m not going to show those, however. !|Query: SingleCharacterNameOperators| |op | |+ | |* | |/ | |! | |- | And Its Fixture Code #include <stdlib.h> #include <stdio.h> #include <vector> #include <string> #include <memory> #include "RpnCalculator.h" #include "OperationFactory.h" #include "Fixtures.h" #include "SlimUtils.h" #include "QueryResultAccumulator.h" struct SingleCharacterNameOperators { OperationFactory factory; RpnCalculator calculator; SingleCharacterNameOperators() : calculator(factory), result(0) { } ~SingleCharacterNameOperators() { delete result; } static SingleCharacterNameOperators* From(void *fixtureStorage) { return reinterpret_cast<SingleCharacterNameOperators*> (fixtureStorage); } void resetResult(char *newResult) { delete result; result = newResult; } void conditionallyAddOperatorNamed(const std::string &name) { if (name.size() == 1) { accumulator.addFieldNamedWithValue("op", name); accumulator.finishCurrentObject(); } } void buildResult() { v_string names = calculator.allOperatorNames(); buildResult(names); } void buildResult(v_string &names) { for (v_string::iterator iter = names.begin(); iter != names.end(); ++iter) conditionallyAddOperatorNamed(*iter); resetResult(accumulator.produceFinalResults()); } QueryResultAccumulator accumulator; char *result; }; extern "C" { void* SingleCharacterNameOperators_Create(StatementExecutor* errorHandler, SlimList* args) { return new SingleCharacterNameOperators; } void SingleCharacterNameOperators_Destroy(void *fixture) { delete SingleCharacterNameOperators::From(fixture); } static char* query(void *fixture, SlimList *args) { auto *self = SingleCharacterNameOperators::From(fixture); self->buildResult(); return self->result; } SLIM_CREATE_FIXTURE(SingleCharacterNameOperators) SLIM_FUNCTION(query)SLIM_END SLIM_END And the Helper Class QueryResultAccumulator.h #pragma once #ifndef QUERYRESULTACCUMULATOR_H_ #define QUERYRESULTACCUMULATOR_H_ class SlimList; #include <vector> #include <string> class QueryResultAccumulator { public: typedef std::vector<SlimList*> v_SlimList; typedef v_SlimList::iterator iterator; QueryResultAccumulator(); virtual ~QueryResultAccumulator(); void finishCurrentObject(); void addFieldNamedWithValue(const std::string &name, const std::string &value); char *produceFinalResults(); private: SlimList* allocate(); void releaseAll(); void setInitialConditions(); private: v_SlimList created; SlimList *list; SlimList *currentObject; int lastFieldCount; int currentFieldCount; char *result; private: QueryResultAccumulator(const QueryResultAccumulator&); QueryResultAccumulator& operator=(const QueryResultAccumulator&); }; #endifI know there are too many fields. The counts help with validating correct usage. I also wrote it so one instance could be re-used and I tried to make sure it was in a “ready to receive fields” state when necessary. In any case, this error checking helped find a defect I introduced while refactoring.
QueryResultAccumulator.cpp #include "QueryResultAccumulator.h" #include "DifferentFieldCountsInObjects.h" #include "InvalidStateException.h" extern "C" { #include "SlimList.h" #include "SlimListSerializer.h" } QueryResultAccumulator::QueryResultAccumulator() : result(0) { setInitialConditions(); } QueryResultAccumulator::~QueryResultAccumulator() { releaseAll(); SlimList_Release(result); } void QueryResultAccumulator::setInitialConditions() { releaseAll(); list = allocate(); currentObject = allocate(); lastFieldCount = -1; currentFieldCount = -1; } SlimList* QueryResultAccumulator::allocate() { SlimList *list = SlimList_Create(); created.push_back(list); return list; } void QueryResultAccumulator::releaseAll() { for (iterator i = created.begin(); i != created.end(); ++i) SlimList_Destroy(*i); created.clear(); } void QueryResultAccumulator::finishCurrentObject() { if(lastFieldCount >= 0 && lastFieldCount != currentFieldCount) throw DifferentFieldCountsInObjects(lastFieldCount, currentFieldCount); SlimList_AddList(list, currentObject); currentObject = allocate(); lastFieldCount = currentFieldCount; currentFieldCount = -1; } void QueryResultAccumulator::addFieldNamedWithValue(const std::string &name, const std::string &value) { SlimList *fieldList = allocate(); SlimList_AddString(fieldList, name.c_str()); SlimList_AddString(fieldList, value.c_str()); SlimList_AddList(currentObject, fieldList); ++currentFieldCount; } char* QueryResultAccumulator::produceFinalResults() { if(currentFieldCount != -1) throw InvalidStateException("Current object not written"); SlimList_Release(result); result = SlimList_Serialize(list); setInitialConditions(); return result; } Note, this code uses a method I added to the cslim library: SlimListSerializer.h – in include/CSlim void SlimList_Release(char *serializedResults); SlimListSerializer.c – in src/CSlim void SlimList_Release(char *serializedResults) { if(serializedResults) free(serializedResults); }I needed to add these methods due to a false-positive memory leak indicated when using CppUTest to test this code. That’s another blog.
Low Rates Finally Make Mortgage Loans Palatable
Improving the Odds For Changing Jobs
New Roles for Out of Work Lawyers & Attorneys
Navigation
Search
Recent blog posts
- Becoming an IG Trainer in JCI
- Certification Levels for Trainers in JCI
- Mentors and Mentoring: Being a Mentor
- The Myth of What We Manage
- IG application
- Mentors and Mentoring: Finding a Mentor
- On a bad day
- How To Give Good Feedback: 11 Simple Rules
- There is almost 7 000 000 000 one-of-a-kind individuals in the world. How do you differ from them?
- Personal Branding - PIMP YOURSELF
Mentoring
Coaching
- Facebook Questions – the ultimate answer to life, the universe, and everything – or an online reputation disaster waiting to happen?
- What Mad Men Gets Right About Innovation
- Women on the web: 6 insights from the comScore report on how women are shaping the Internet
- The fear economy.
- Three new Facebook resources for personal and professional guidance for the media, journalists and PR professionals
Twitter Updates
User login
Archive
- June 2008 (2)
- August 2008 (3)
- September 2008 (16)
- October 2008 (8)
- November 2008 (6)
- December 2008 (9)
- January 2009 (5)
- February 2009 (3)
- March 2009 (8)
- April 2009 (5)
