Saturday, November 2, 2013

Understanding (That There Exists) An Opposing View

If you are passionate about anything, chances are you’ve found yourself wondering “how in the world could that person believe x about an issue?!”, where x is avoiding semicolons in javascript, using tabs instead of spaces, being pro-gun, anti-cupcake, etc.

I used to find some of those moments very stressful. I’d be sitting there with lots of “evidence” and “research” to support my position, fuming about some idiot who can’t use apostrophes correctly and is frickin’ ridiculous with his/her hyperbole and logical fallacies…and get nowhere.

I finally figured out a little exercise that helps me in those tense situations: I just consider that the other person probably sees me as just as insane as I see him/her. That other person is more or less like me (rational, thoughtful, educated, kind, etc.) but disagrees with me the same way I disagree with him/her. And that’s fine.

“But I’m right!” you say.

Maybe you are. So what? Go tweet about it with loud, emphatic language! What good is that going to do? It makes you look like an ass when you’re right, and an ass when you’re wrong. Save your energy and hope that your noncombativeness will be reciprocated. To quote Dale Carnegie (more from him in a minute), “You can't win an argument. You can't because if you lose it, you lose it; and if you win it, you lose it.”

A baby step on the way to figuring all this out was more or less the development of a coping mechanism. I made a decision to not engage in fruitless debate. I noticed that many arguments I was having on Twitter and Facebook were fruitless…so I just stopped enabling myself to get all worked up over things 140 characters at a time.

Later, I had a realization when a friend help a position I found to be indefensible. As friends often do, we had an easy, dispassionate conversation. Neither of us won over the other person and that wasn’t the goal—we were just friends talking. That is when the real trick I described above sunk in: me and that other dude are similar.

Then this happened again when I was listening to a podcast I’d been listening to for a long time. My views usually line up well with the host’s (I listen for entertainment, not education). But then he passionately, and repeatedly started taking a position I am strongly opposed to. I literally said “Whoa, what?!” to myself the first time I heard it. Then I went though the whole exercise: this crazy smart, well informed guy has an insane position on this issue. Whoa! But that’s ok!

Now, suppose you actually want to change some hearts and minds on an issue. That’s really, really hard, and I’m not going to tackle that here. I can recommend these two books I recently finished, though: Switch and How To Win Friends and Influence People (aka HTWFAIP).

Both titles walk you through the basics of understanding problems, working with people, and affecting change. They use lots of anecdotes, guidelines, and tips.

If you’re not familiar with either, you might be surprised to hear that I found Switch to be more mechanical and duplicitous than HTWFAIP. It seems to focus more on the steps necessary to analyze situations and maneuver others into your line of thinking (or outright manipulate them). It also helpfully provides a framework for approaching and solving problems, and a vocabulary for talking about them. This has been very useful at work—we read it as a group and now refer to it and use its terms all the time.

HTWFAIP on the other hand sounds like it’d be all about subterfuge but is actually entirely genuine. It has a slightly different goal of getting people to like you and it encourages this almost exclusively by teaching you to be a nicer person. Seriously! It offers many tips and admits that they will be effective only if you are sincere.

Relating this back to the post, here’s another Dale Carnegie quote from HTWFAIP about arguments:

“I have come to the conclusion that there is only one way under high heaven to get the best of an argument— and that is to avoid it. Avoid it as you would avoid rattlesnakes and earthquakes.”

Both are good, easy reads, and great for groups. I suggest reading FTWFAIP first, then Switch.

Monday, September 9, 2013

Notify New Relic of Deployments with Chef

You can tell New Relic about your deployments and they’ll add vertical lines to the graphs at the corresponding times. This is super helpful as the (often dramatic) impact of a deployment becomes easy to grok.

The documentation on the Events > Deployments page is very helpful, but I still had to tinker with my message to New Relic’s API to get it to work. Here’s what I ended up with:

At the end of my recipe, post to the API with the http_request resource:

http_request "notify_new_relic" do
  action :post
  url "https://rpm.newrelic.com/deployments.xml"
  headers "x-api-key" => "#{node["newrelic"]["apikey"]}"
  message "application_id" => "#{node["newrelic"]["appid"]}"
end

I’m loading the key and application id from attributes. And it works (this is dev…no traffic there :))!

deployment-markers

This was crazy simple to do, though it might be better implemented as a report handler. If you go that route please share.

Tuesday, June 18, 2013

How to use services in a NopCommerce Plugin that it doesn’t use by default

Suppose you want to override some behavior in a NopCommerce service via a plugin. You would start by subclassing the service that has the behavior you want to override. But what if your new code requires access to something that the existing service doesn’t know about?

The answer turns out to be pretty simple: just add it to your constructor, and the dependency resolver will figure it out for you. (You don’t need to worry about it.)

Here’s an example. I want to override the PictureService. So I started with this:

    public class MyPictureService : PictureService
    {
        // constructor
        public MyPictureService(
            IRepository<Picture> pictureRepository, 
            IRepository<ProductPicture> productPictureRepository,
            ISettingService settingService, 
            IWebHelper webHelper, 
            ILogger logger, 
            IEventPublisher eventPublisher, 
            MediaSettings mediaSettings,
            : base(pictureRepository, productPictureRepository, settingService, 
                webHelper, logger, eventPublisher, mediaSettings)
        {
        }

        // my overrides
    }

So you can see that we get a lot of stuff by default. If we want to use any of those services, we need to create class variables for them (the base class marks them private), like so:

    public class MyPictureService : PictureService
    {
        protected readonly ILoggerService Logger;

        // constructor
        public MyPictureService(
            IRepository<Picture> pictureRepository, 
            IRepository<ProductPicture> productPictureRepository,
            ISettingService settingService, 
            IWebHelper webHelper, 
            ILogger logger, 
            IEventPublisher eventPublisher, 
            MediaSettings mediaSettings,
            : base(pictureRepository, productPictureRepository, settingService, 
                webHelper, logger, eventPublisher, mediaSettings)
        {
            Logger = logger;
        }

        // my overrides
    }

And if I want to add a service or repo that’s not there already? Just add it:

    public class MyPictureService : PictureService
    {
        protected readonly ILoggerService Logger;
        protected readonly ISpecificationAttributeService SpecificationAttributeService;

        // constructor
        public MyPictureService(
            IRepository<Picture> pictureRepository, 
            IRepository<ProductPicture> productPictureRepository,
            ISettingService settingService, 
            IWebHelper webHelper, 
            ILogger logger, 
            IEventPublisher eventPublisher, 
            MediaSettings mediaSettings,
            // just add it to the constructor!
            ISpecificationAttributeService specificationAttributeService)
            : base(pictureRepository, productPictureRepository, settingService, 
                webHelper, logger, eventPublisher, mediaSettings)
        {
            Logger = logger;

            // and use it
            SpecificationAttributeService = specificationAttributeService;
        }

        // my overrides
    }

Have fun!

Friday, June 14, 2013

Chef: Cannot find a resource for powershell on windows version 6.1.7600 (solved)

While working on some deployment stuff I ran into this error:

Cannot find a resource for powershell on windows version 6.1.7600

The solution turned out to be pretty obvious, and easy: include the powershell cookbook. For some reason I assumed it came in as part of the windows cookbook, but no. So just include it in your metadata.rb file like so:

name             '...'
maintainer       '...'
maintainer_email '...'
description      '...'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version          '0.1.0'
depends          'windows'
depends          'powershell'

Of course, if you’re using Chef Solo, you’ll want to download your dependent cookbooks, too.

Monday, March 11, 2013

My Top 9 Favorite Podcasts (Updated March 2013)

Although I sample a ridiculously large number of podcasts, these are the select few that I subscribe to and listen to regularly. I’ve presented them in order of “fewest unplayed episodes remaining” (which suggests how much I like each one). Again, simply being on this list means I’m a regular listener—don’t avoid the ones at the bottom—they are excellent.

I was going to write a lengthy description/review for each but, let’s be honest, you weren’t going to read it. Just go listen to some of these!

Thursday, February 21, 2013

How do I add a MongoDB replicaset/node with auth/credentials to MMS monitor on 10gen?

Want to get in on that sweet, sweet MMS MongoDB monitoring action?

image[20]

Of course you do! But are your mongo instances setup to require authentication? Bummer—the instructions won’t work for you out of the box. Here’s what you’re missing.

  1. Go ahead and setup the agent as instructed
  2. Go into the MMS management site
  3. Add your host manually

    image_thumb[8]
  4. Enter the hostname, db username, and db password. I suggest creating a new user for this (it must be a user on the admin database!)

    image_thumb[9]

Now frantically check the hosts, agents, and pings tabs for updates. It might take a few minutes. Check the Agent Log tab for errors :).

Once you get the one host working, it will add the other hosts in the replicaset, too. You can then install the agent on those machines and add a password with the pencil icon to each new row directly.

How do I add another group to my MongoDB MMS monitor on 10gen?

10gen has some seriously awesome (free) monitoring software: MMS.

image

You’re supposed to add your machines to a group, and use a different group for each logical grouping of machines. For instance, one group for one production cluster and another group for a different cluster. But how do you add a new group!?

I admit the obvious answer eluded me. You do it from the Admins page. Once there you’ll see a little “Add New Group” link:

image

Once you do that you can switch among your groups with the select list in the upper-left corner.