Pages

Tuesday, December 13, 2016

Things an "Expert" C Developer Knows: Undefined Behavior

This is the first post in my series: Things an "Expert" C Developer Knows


The 2016 SEI CERT C Coding Standard [free download] gives  this definition of Undefined Behavior:
Behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which the C Standard imposes no requirements.
An example of an action that causes undefined behavior is signed integer overflow. Professor John Regehr at U of Utah has a blog post that gives several possible examples of what C compilers *could* do with this C statement in a program:
printf ("%d\n", (INT_MAX+1) < 0);
The possibilities Regehr lists include printing 0, 1, 42 or formatting your hard drive. While the latter won't actually happen, undefined behavior can cause data corruption and/or security vulnerabilities.

The CERT C Coding Standard lists. in Appendix C, all undefined behaviors in the current C standard: C11 (more formally known as: ISO/IEC 9899:2011) There are 203.

Since I've mentioned the C11 standard here, I should probably have a Things an "Expert" C Developer Knows post about C standards.

Things an "Expert" C Developer Knows...

In January, my engagement with my current client will be taking a real change in direction. Rather than being a software craftsmanship coach, I will be joining a large team as an embedded C developer.

In that vein, I submitted a talk to my employer's internal conference in February about things that developers need to know if they are going to say they *really* know C.

In preparation for that, watch for a series of posts from me on: "Things an "Expert" C Developer Knows"

Tuesday, November 15, 2016

Always TDD? But Certainly Not for Startups, Right?


I just read "Uncle Bob is Smoking His Socks", in which the author, Joe Rounceville, starts by taking issue with Uncle Bob's statement that you are not a professional software developer if you don't TDD. I understand how that statement makes people bristle. Rounceville goes on to suggest that there are contexts (in particular lean startup) that don't merit TDD. He goes as far as to suggest that TDD in that context might be "gold plating."

Of course, startups need to be ultra-agile and able to get fast feedback on experiments by getting work out in front of customers rapidly. There's an element of racing against time when a company has to achieve success with only a certain amount of capital to burn through. Startups need to be able to pivot quickly in response to what they learn in their experiments.

But people who argue against "always TDD" seem to think that they save time up front by not using TDD. Among experienced TDD developers, I have not found that to be the case. And well test-driven code allows for rapid pivots because it's easy to understand and different concerns in the code are not tangled-up among each other.

Another risk for startups that decide not to TDD is that prototypes tend to be pushed into production as-is. Many young companies have met serious pains when their initial rushed-to-market release could not handle the load that came with the product's rapid success. And there's the old saw that if you don't have the time to write it correctly the first time, you are not going to have the time to re-write it later.

The relationship between TDD and startups is tricky. Learning TDD takes time. It's not a simple matter to start using TDD if you aren't good at it. Developing software with TDD when you are new to it is slower than developing without TDD. There is a non-trivial learning curve. As a developer, I would not want to try to get good at TDD while working for a startup. And I personally would not want to join a startup if I wasn't already strong in TDD. And because of the ever-changing nature of the market, if I have a startup idea and I want to get good at TDD before starting on it, I'm likely to miss my window of opportunity. And if I develop my startup without TDD, I'm likely to end up with a hard to change and hard to maintain project that's prone to defects. So while Uncle Bob's statement about "always TDD" may sound dogmatic, I find the statement that "startups don't need / can't afford TDD" to be false.


Wednesday, October 19, 2016

The Importance of Saying "I don't know and..."

As a technical coach, especially when I am embedded in a team, it is hard to overemphasize the importance of using the phrase "I don't know," plus "let me go find out." or "I'll ask someone who I think can help us."

Being able to say "I don't know" is an important skill for developers if they want to be on a high-performing team. Without it, the team risks creating an environment of fear and delayed learning. So when I say "I don't know ..." as a coach, I am modeling behavior that will help devs succeed. And adding the second phrase models taking initiative. While many, perhaps most, devs are good at finding answers to things they don't know, there can still be cultural and other reasons why a developer might not step out of their usual domain.

If you have coaching responsibilities, either formal or informal, and you don't say "I don't know..." maybe ask yourself if you are missing an opportunity to model important behavior.

Tuesday, October 11, 2016

Guest Post: Thoughts on Re-evaluating Spring as a Framework for Building Well Maintainable Applications

I'm hosting this post for Brandon Zeeb, another software craftsman at Pillar

Thoughts on Re-evaluating Spring as a Framework for Building Well Maintainable Applications


Spring Boot is good for the general populous.  Not sure I’d recommend it for any greenfield development.

Spring Boot wraps up a lot of auto configuration that most developers, in my experience, do not understand.  Spring Boot enables 3-6 annotations, 2-3 of which you cannot enable outside of Spring Boot.  Those 3-4 common annotations explode out into at least 10 more annotations.  In total, all those annotations create a large number of beans very few developers know exist.  Only if you had been using Spring since version 2.0 and had followed it's growth through MVC (and its ViewResolvers) into the RESTy side (with its MessageConverters) will you know what it's actually doing.  In short, very few developers I've found can actually be effective within Spring.  If they try to find the right place for a thing, they spend more time reading documentation to find the right extension point (what base class does my @Configuration need to extend so that I can put this bean in the ContentNegotiationManager!?!?) and if they work around the framework they pay later when Spring works against them

If you're writing small micro services and you finish them and forget them I don't see a problem.

Though these days there are many more frameworks which are slimmer and offer a more obvious and easily testable environment which makes, in my view, Spring less relevant. (edited)

In short, I'm looking at more ala cart solutions.  An example might be using Guice (for IoC) with Vert.x 3.  There is pretty minimal frameworking, whatever your app does, you see very clearly.  The examples online don't show what I believe to be the best use of Vert.x (and Guice), they put all the codes in one file and say "hey look how easy this is!".  The Java APIs of Vert.x are incredibly clean, all interfaces, easy as hell to mock, which ties in well to properly abstracting and dividing the application into components

The built-in Hazelcast solves a lot of problems in architecture N-tier apps have.


Brandon Zeeb:
Twitter: @phasebash
Github.com/phasebash

Monday, September 26, 2016

SonarLint for Eclipse Does Not Analyze Test Files by Default

I say unit tests are code like any other code. As such, they deserve to be refactored and kept clean.

I learned today that, by default, SonarLint for Eclipse disagrees. If you select Window->Preferences->Sonar Lint, you will see that "Test file regular expressions" contains "**/*Test.*,**/test/**/*":


For SonarLint to behave the way I want, which is to treat any file whose name ends in ".java" as code, I have to clear the regex.

Wednesday, September 21, 2016

Legacy Code: Characterize or Test Protect?

In the context of working with legacy code, I often hear the terms "Characterization Tests" and "Test Protecting". Here is how I think about each term:


Characterization Tests: a suite of tests that I build against legacy code that uses sufficient representative inputs to convince myself that I have characterized the behavior of the object I am testing. This suite also documents the behavior.

Test Protecting: building a suite of tests against legacy code that covers the object under test sufficiently that I am confident that the suite protects me from inadvertently changing the object's behavior during refactoring or when I add features.


One thing that is interesting to me is that the exact same suite of tests can both characterize and protect an object's behavior.

I was running a workshop today and introducing the concept of test protecting. Here are the steps I introduced today. If you are new to test protecting, they should be a good starting point. If you've done some test protecting, I hope you'll find some new nuance to your understanding. If you're already awesome at test protecting, maybe you'll want to teach from my steps, or comment with your insights about test protecting.

Steps I Teach to Test Protect Legacy Code:

Select a class to protect. 

Usually this is the class that I need to fix a bug in or add a feature to. Or maybe I have a few spare cycles and I want to add coverage to a frequently edited class. I do not select a rarely-modified class to test protect - that would be a waste of time (and thereby money, mine or my employer or client's)

Create a test class.

Legacy code, by one definition is code that doesn't have tests, so it follows that a legacy class won't have a test corresponding class. Create a test file with a name and location that follows your unit testing framework's conventions.
(Commit to your version control.)

Choose a public method to start with.

Often legacy classes are large and complex enough that it is difficult to test protect them well through only the public methods. I see several options (of varying risk) in that case:

  1. Change private methods to public
  2. Change private methods to package protected
  3. Don't protect private methods that are difficult to test through public methods.
  4. Refactor the class so that it is easier to test.
  5. Use a testing tool that allows you to test non-public methods.
  6. Protect as much as you can in a reasonable amount of time, assess risks posed by unprotected code, then decide on your next action.
The only answer that I am comfortable with is number 6.

Write a test that exercises the method you selected.

If you are at least somewhat familiar with the behavior of the method you selected, think about edge case inputs and happy and sad path inputs. Choose one to start with. Some devs like to start with edge cases, some like to start happy or sad path. I'm not sure it matters.

Give your test an absurd assertion against the result.

This step is as much like characterization as it is like test protecting. I want to be sure my test fails before it passes, so I choose a value that is unlikely to be correct. For instance, if the method I am exercising is:
int lookupDogAverageWeightLbs(string breed);
then I will choose a number like 5000:

assertEquals(5000, lookupDogAverageWeightLbs("Goldendoodle"));

Run the test so it fails.

In the previous example, your test should fail with a message something like:
Expected [5000] got [40].
If it doesn't, check your assumptions and look for mistakes in your exercising of the method or in how you wrote your assertion.

Fix the test so it passes.

When we test drive, we assert what the expected value should be, run it to see it fail, and then write the least amount of code needed to make the test pass. In test protection, the existing implementation is the standard behavior, so we fix our expectation to make the test pass. From absurd fail message above, you can easily see the actual result delivered by the implementation and fix the expectation with it so that the test passes:
assertEquals(40, lookupDogAverageWeightLbs("Goldendoodle"));
(Commit to your version control.)

Examine the test coverage of the method you are exercising.

If your coverage tool doesn't automatically run when you run tests (why doesn't it?), then run your coverage tool. Find which lines of your exercised method are not executed by your first test. If there are none, your method is test protected.

Write another test that hopefully increases coverage. 

Write a new test and give your exercised method new input data. Use inputs that, based on whatever understanding you have of the method so far, will exercise a non-covered line. Sometimes the name of the method will give you an idea, sometimes you will have gleaned some tentative understanding by scanning the implementation code while looking at coverage, and sometimes you still won't have a clue. Pick new inputs however you can and run your test.

Get the new test passing.

You might have needed to write a green test in order to increase the method's coverage. That's ok. In test driving, a test that doesn't go red before going green is worthless and time-wasting at best and possibly dangerous at worst. But in test protecting, such a test is only worthless if it does not add to the method's coverage. If your new test didn't increase the method's coverage, change your inputs until it does. This is another difference from when we test drive. When we test drive, we choose a set of inputs that fail and implement code to make it pass. We change the inputs only if the ones we chose did not make the test fail.
(Commit to your version control.)

Check the coverage of your method again.

If you have not covered all the lines in the method, jump back to "Write another test that hopefully increases coverage." If you have covered all the lines in the method, start over again with"Choose a public method to start with." If you've covered all the lines in the class, you have test protected the class. Congratulations!

Make sure new tests are run in CI.
If there are already other test classes in your project, your continuous integration server may already be configured to run tests in all test classes. If not, adjust your CI server's configuration to be sure that it runs your new tests. Kick off a build and inspect the build output to be sure your new tests ran.


Monday, May 9, 2016

Jokes and Fun and Safety at Work

Something happened at a conference I recently attended:

Between sessions, there was a long line at the men’s room. There was little or no line at the women’s room. Behind me in line, out of my vision, I heard a man say:

“Maybe we're all starting to feel transgender right now.”

If you didn't cringe when you read that, I get it. In a way, it is a clever nod to all the happenings related to the recent North Carolina bathroom law.

But I cringed when I heard it, and I cringe each time I read it again. Unfortunately, that comment is hurtful. Would a transgender man feel welcome hearing that? I can't imagine one would.

I'm sure that the comment was not intended to be hurtful. But if a transgender man heard it, and I can't be certain that one did not, I expect it would have a hurtful impact. And if we want a better workplace and a better world, I believe we have to take responsibility for the impact of our actions, not just our intentions.

I believe everyone wants a fun work environment, and jokes can certainly be part of that. But I'm hoping that we can create cultures that push women and members of marginalized groups out of IT less. When someone is outnumbered in a setting, it can be hard to speak up about what feels OK and what doesn’t, especially if the rest of the group seems to (even if silently) condone something. I understand - rocking the boat about culture can be a risk to employment. As white, heterosexual men, we are probably not experienced with what can feel hurtful to people different from us. I try to honor and believe people’s life experiences. Even if I can’t see how something can be hurtful, I try to believe people when they say something is.

All of this means that I try to avoid humor that is sexually charged, comments on people’s bodies, or touches on race, religion, sexual orientation, gender presentation, and other characteristics of members of marginalized groups.

And if a joke like that slips out and I notice, I don't wait for someone else to point it out. I call myself out on it and acknowledge the possible impact, even though it wasn't my intention.


Saturday, May 7, 2016

Slides from my Diversity in IT talk at Agile and Beyond 2016 are Now Available

At Agile and Beyond 2016, I presented: "Why Should I Go See Another White Man Talk About Diversity in IT?" I spoke mainly about how women and members of marginalized groups are often made to feel unsafe or unwelcome at IT companies, usually without men realizing the impact of what we are doing.

I've put my slides up (link below). If you are interested in the topic, please take a look. I have included many links to information and resources.

slides - scroll down below my profile to find the .pptx



Wednesday, May 4, 2016

A New Adventure - Same Employer, Same Client!

For the last ten months, I have been a software developer on a high-functioning, reference team at a major enterprise client. The team is a great group of people, with solid processes, and has been delivering defect-free code and providing mission-critical business value since before I joined them. But my time as a member of that team has drawn to a close.

Starting Monday, I will be moving within that same client to join the coaches in their Agile Center of Excellence. This new role will allow me to use more of my personal, social, coaching, and training skills, and will no longer involve creating production code on a cadence.

I am really excited for my employer, my client, and myself. The change comes at a time when the development team is beginning a pre-planned size-down, so my employer has somewhere to place me immediately. My client can continue to benefit from my accumulated domain experience. Both will be getting their best value by paying for work that I excel at, and I'll be doing work that I have a deep passion for.


Thursday, March 31, 2016

On Privilege

What do I mean by “Privilege”? Privilege is a set of advantages that I receive, without earning them, merely because of my birth circumstance(s). Privilege is different than prejudice or “ism”s. As a person of privilege, I get the advantages even if don’t have prejudice and don’t engage in overt oppressive activities like sexism or racism.

Some examples of my privilege as a white man include:
• I can go to any workplace and expect to see people who look like me
• If I make a mistake, no one will say that it’s because white people are stupid
• The lead roles in movies and tv shows are usually of my color and gender
• If I have children and a career, I won’t be called selfish for not being home with the children
• I am more likely to get a job than an equally qualified applicant who is a woman and/or person of color

There are many types of privilege, including (specific examples and details can be found by following the links):
White Privilege
Male Privilege
Heterosexual Privilege
Able-bodied Privilege
Class Privilege
Religious Privilege
Cisgender Privilege (contrast with transgender)

You may say: “But I have struggled! I don’t have privilege!” Privilege isn’t about whether I am powerful, wealthy, have a good job, have worked hard all my life to get where I am, or struggle every day. Privilege is simply unearned advantages I get because I belong to a group.

Sometimes when people learn about the concept of privilege, people feel guilt?  If this happens to you, ask yourself where the feeling is coming from. Is it because:
• I never noticed it before?
• I act in ways that make this worse?
• I don’t do things that make it better for people without privilege?

Now that you know about privilege, what can you do about it? You can:
• Read about privilege
• Stay on the lookout for other privileges you might discover you have
• Belive the life experiences of people with less privilege
• Ask yourself if your actions or policies reinforce the advantages of certain privileged groups
• Don’t “help” less-privileged groups - it robs them of agency. Instead amplify their voices (retweet, etc)

Wednesday, March 2, 2016

Pair Programming "Out Loud"

One element of Pair Programming that I find key to success is "Programming Out Loud". When I have the keyboard and mouse (driving), I want to be explaining my train of thought to my pair partner, moment-by-moment. Conversely, if I am the non-keyboard partner (navigating), I want my partner to be explaining their thoughts moment-to-moment. If my partner is practicing "silent pair programming", I try to ask ask questions like: "What's next?" or "Where are we headed?" to try to get them talking about what they are thinking or doing. Or if that doesn't help, I can ask to drive for a while and try and draw out their ideas that way. Usually things don't go this far, unless my partner is new to pairing. When I start to go off silent and solo, my partner usually invites me back into collaborative mode.

But what if my partner is the navigator and they are disengaged? I can ask (slightly tongue-in-cheek): "Are you with me?" It can require courage to "call out" my partner in that way, but sometimes it takes courage to be on a successful agile team. And if I'm the disengaged navigator and I catch myself being distracted, I can ask to write the next test to try and focus myself back on what we are doing.

Do you have ways that you draw a distracted partner back into collaboration? Or do you have ways to get yourself back into collaboration?

Wednesday, February 24, 2016

Hiring and Diversity

I’m so glad to see another man thinking about hiring women and members of marginalized groups. I started a comment that post, but it became rather long, so I am posting it here instead. Read Jay's original post at the link above for perspective, although I hope that what I have written below stands fairly well on its own.

Jay,
I really like your post: "Hiring Awesome Developers (who happen to be women)". I've been thinking about how to write a "disclaimer" paragraph like your “Before you start” paragraph. You've covered many of my thoughts. I also try and acknowledge to people that I will make mistakes, and that I will accept the impact of my words regardless of their intention. Further, I won’t expect people to teach me about those mistakes (although I am totally open to it), and I will research on my own until I think I understand them.

Another thing I find important is to amplify the voices of people in marginalized groups. I try to provide references to people who belong to the groups that I am speaking about. They are the ones whose lives are affected daily by these issues and they speak from the most authority.

Your paragraph “A Possible Plan” addresses the so-called “pipeline” problem that results in too few minority and women candidates. But another reason that the makeup of companies is still disproportionately is that women are leaving STEM in large numbers. We need to make sure that our company cultures and environments are really fair to women and minorities and free from discrimination and bias before we bring in women and minorities, or we risk losing them and alienating them more.

We can also examine our websites and job descriptions for wording and imagery that may discourage women and members of marginalized groups from applying. A simple example is a posting that looks for “ninja” developers who can “smash” technical problems — this aggressive language exclude women from considering themselves as a candidate.

Finally, women tend not to apply for tech jobs unless they meet 100% of the criteria in the posting while men apply if they match 60%. I’m not sure what to do about that - maybe mention in the posting that not all criteria are required and avoid long lists of “nice-to-haves”.

I wrote another post that has a more concise bullet-list of things I'm learning about diversity and the workplace.

My Crash Course Crayon Video: 4 Levels of Listening

My employer, Pillar, produces a series of two-minute videos related to software development and the people skills needed to do it well.

A video I made was just released. The title is: "4 Levels of Listening" and you can watch it here. I'd love to hear your reactions.

Sunday, February 14, 2016

Things I am Learning About my Part in Diversity and Inclusion

As a cis-gendered, heterosexual, white man, I want to:

  • do my homework to learn fundamentals about marginalized groups' experiences
  • amplify marginalized people’s voices
  • believe marginalized people's life experiences 
  • understand intent vs impact of what I say
  • be ready for the mistakes I will make
  • accept that the people that my mistakes hurt may be angry
  • accept that they don’t owe me an explanation of why it hurts (see doing homework)
  • not “expect a cookie” for working on diversity and inclusion (pic)
  • understand that being an ally is not a yes/no condition, but requires a level of proactivity
  • find someone besides marginalized people to help me explore my feelings about allyship
  • learn to "check my privilege" and understand that I have privilege even if I had a hard life of poverty and abuse.

If these ideas interest you, please follow the links above and come see me present at Agile and Beyond 2016 this May.


Sunday, January 17, 2016

Accountability - Do you do what you agree to do?

How accountable are you for your agreements? When you say you are going to do something, do you do it?

There was a time when I would say I would do things but then often not do them. For example: an acquaintance would suggest we go bowling and I would answer something like: "Yeah, I'll call you." But then I wouldn't call. Or when I first started in my career, a manager might ask me to provide a write-up on something and I might say something like: "I'll have it by the end of tomorrow." But that day and the next would pass, without any high-priority emergencies, and yet I wouldn't finish the write-up.

Does that sound familiar? Do you have patterns like this? Maybe at work, or with a family member or spouse, or with friends or acquaintances?

What was I doing when I said I would do something but then not do it? In both examples above, I might have had mixed feelings about doing the thing, or I might have actually meant to do it. But somehow I never quite managed to get it done. What did this behavior communicate to my friend or my manager? Perhaps it told them that I couldn't be counted on. Maybe even it said that I didn't put much value on things are that important to them. They might not have realized it consciously, but I suspect that they received a message that I didn't care very much about them.

There came a time when I realized that not keeping agreements were weakening relationships with people in my life, at work and outside work. So I briefly decided that the answer was that I wouldn't commit to very much. So if that acquaintance suggested bowling, my new answer would be something like: "Yeah, maybe." Or with my manager, I would try to get away with telling him that I would complete the write-up "soon". But it quickly became apparent that this strategy wasn't strengthening relationships with people.

These days, I have a strategy around agreements that strengthens relationships with people. When I'm asked something, I stop and consider the request seriously. I ask myself whether I want to agree to it, and whether I'm for sure able to commit to it. If both are yes, then I give the person a date or time when I will do it, and then I follow through. So, in the bowling example again, my answer would be "Yeah, that sounds fun! Can you do it this Friday?" And with my manager, I would say: "I've got a lot on my plate right now; I'm not sure when I will be able to get to the write-up. Do you want to change my priorities? If I stopped everything else right now, I could have it by noon tomorrow."

Obviously, my new strategy doesn't require me to agree to everything. Maybe I don't like bowling. In that case, I could suggest a specific time for an alternate activity. Or maybe I really don't want to hang out with that person at all, I might just say: "Nah, but thanks for asking." Or I might tell my manager, if it's true, that I don't think I would do a good job on the write-up, and suggest a different person to ask. Or if it's just a preference, I could tell him something like: "If you need it to be me, I will do it. But if not, I'd rather stay on what I'm working on. Okay?"

Besides the way that this method of handling agreements strengthens connections with people, I find it has personal benefits as well. I'm able think of myself as a responsible person. And I don't feel guilty for indirect communication. And I get much more clear about what I want, what I'm willing to do, and what I'm not willing to do.


Friday, January 8, 2016

Even Well-Meaning Words Can Hurt - What Can We Do When It Happens?

Have you ever heard an exchange like this?

Person A. < some remark >
Person B. "Hey! That's not nice!"
Person A. "Jeez, lighten up! I was just joking."

What happened here is that Person B doesn't understand the difference between Intention and Impact.


Intention is whatever result Person B wanted their words to have. In the case above, they probably wanted people to laugh. On the other hand, impact is the emotional meaning that Person A received. In the case above, Person A felt slighted in some way - probably by one of the common "isms": sexism, racism, etc.


A tool I learned to work with Intention and Impact is called Ouch / Oops. I have only tried it in groups that are already close, but I bet it would work in somewhat mature teams as well. When a person receives a negative Impact, they can tell the other person: "Ouch" or: "That was an ouch for me." 

Here's the same example as above, but with Ouch:

Person A. < some remark >
Person B. "Ouch." or "That was an ouch for me."
Person A. "Oh, I'm sorry. What did I say that hurt?

Person B.
Person A. "Wow, I had no idea that what I said could be taken that way. Thanks for explaining it.

Here is another version of the above example, except that when Person B points out the impact, Person A can see the problem right away.

Person A. < some remark >
Person B. "Ouch." or "That was an ouch for me."

Person A. "Oh right, I'm sorry. I see what my words implied. That wasn't what I intended. Thanks for pointing it out."


By contrast to Ouch, Oops works in the opposite direction. A person says something, catches a possible Impact of their own words, and then uses Oops. Here's our example again, this time with Oops. Notice that Person A speaks twice before Person B speaks:

Person A. < some remark >
Person A. "Oops. That might have a different impact than I intended. I'm sorry. Let me say it this was instead: ..."
Person B. "Yeah, the first way didn't feel good. Thanks for catching it."


It is important here that neither person belabor the point during an Oops or an Ouch. The point isn't to punish person A. Person A needs simply to recognize their impact and express a brief apology. From there, both people move on. Any additional apologizing or lecturing can lead to hurt.


Receiving "Hey! That's not nice!" is uncomfortable. Often, a"Hey! That's not nice!" response is met with defensiveness. This could be because a part of the speaker may feel shame, and sometimes a way to deal with shame is to lash out and blame the other person. By contrast Ouch offers the possibility of the parties involved learning something and becoming closer. Being on the receiving end of Ouch may still be unpleasant, but is less likely to invoke shame. Calling "Ouch" focuses on the impact on the listener while presuming good faith on the part of the commenter, rather than implying that the commenter is mean, insensitive, or prejudiced. Similarly, with the focus on the impact received, there is less room for someone to be misjudged as touchy or over-sensitive.


Oops is a way of acknowledging that the listener has valid feelings and that the speaker's words may have been received as hurtful, but that the speaker doesn't intend to hurt the listener. Like with Ouch, this offers the pair the opportunity strengthen their relationship.


Increasing my Blogging

I've decided to really try and be consistent and blog good content on a regular basis. I am taking a free 6-part course by https://www.pluralsight.com/ instructor and author of "Soft Skills: The Software Developer's Life Manual", John Somnez. The course is written for software developers.

On John's site http://simpleprogrammer.com/ I signed up for "How To Build A Blog That Will Boost Your Career" (http://devcareerboost.com/blog-course/ Again, it's free, and I don't get anything if you sign up.)

John's course takes you through:
  • Deciding on a theme (mine is Understanding Yourself and Others to Improve your Dev Career) 
  • Easily creating an actual blog site using Wordpress + Bluehost (but if you want to use something else, or already have something, no problem) 
  • Creating a big backlog of blog topics 
  • Choosing and committing to a posting schedule, including when you are going to write (I'm going to publish every other Monday, writing on Sunday night) 
  • Generating traffic to your site without using anything scammy 
  • Marketing yourself 

I like the course format. It comes out twice a week. Each email has a couple of homework assignments that require real work but are doable by the next email. I am really keeping up, and I tend to procrastinate some things like this.


Disclosure: Writing and publishing a post about the course is one of this week's homework assignments. It simply says to write a post about the course and include the links. I wrote the content without any input from him, he didn't see it before I published, and I don't get paid for it.