Tuesday, December 14, 2010

Feedback on "craftsman" activities at work...

Got some good feedback from one of the people at the office on the idea of doing after-hours randori sessions, topics to choose and the last "Craft Day" we did.
  • The JQuery session at craft day was his favorite.  Hands-on technical stuff for specific technologies is king.  More academic problems cause him to lose interest quickly.
  • 40-and-out is very important to him.  Doesn't want to do any after-hours stuff because he works very hard while he's here, and is committed to his family.
  • He was unpleasantly surprised that so few people understood the fundamentals of agile development, specifically of TDD.
  • Real-world stories in a lunch & learn, not contrived.  He's thinking along lines of micro-patterns for mocking portlet behavior - problems with specific technologies that we use every day.
All of these came from one person, but were worth writing down because they're a distillation of what I have heard from other people around the office.  Great food for thought.

Thursday, November 18, 2010

The results are in: In-house software craftsmanship day

On Friday Nov 12, we hosted an in-house "software craftsmanship day".  The format was similar to many of the software conferences I have attended, with multiple tracks, some more technical than others.
The schedule and session notes are in my previous blog post.
The raw retrospective notes are on the learning group's google site.
The event was an unqualified success, based on feedback from the participants.  Some of the most valuable things we found:
  • Relationships: getting everyone talking to (and pairing with) people on other sub-teams is an end worth pursuing by itself.
  • Sharing knowledge: having different people pair on hands-on exercies spread out some of the micro-patterns that people follow in their day-to-day work.
The feedback was entirely positive and constructive.  In my experience, people here are not at all shy about sharing criticism, so I took that at face value.
I believe the two main keys to success were...
  • Preparation: most of the people who hosted sessions did a dry run with a handful of people first, and adjusted their presentation and delivery.
  • Food!  Having grub for everyone (donuts in the morning and a big lunch mid-day) kept us all together and underlined the importance of the event for all participants.
I'll chat more about the event in the google software craftsmanship group.

Tuesday, November 9, 2010

Software Craftsmanship Day at my workplace

Well, we finally pulled together a schedule and planned out all of our sessions for a Software Craftsmanship day at my workplace. 

The coolest part?  I didn't have to beg anyone to make it happen.  One of the VP's suggested that we could devote a day per month to honing our development skills.  How many organizations do that?  Very few, I think.

Since I was already leading a craftsmanship group, my boss asked me to lead the effort to put this together.  I just asked for volunteers, called a weekly meeting to work out what we wanted to do, and we did it!

I'll be sure to report what I learned once the first one is over.  I expect this to be a very useful and interesting day, but I won't know for sure until after Friday, Nov 12.

The best way to describe what we're doing is to paste the invitation I just sent to all of the agile teams here (about 120 people are invited, I expect around 100 to attend).

Craftsmanship Day (a.k.a. "Craft Day") takes place all day this Friday.  Our management has chosen to give us a full day to practice and define our "craft" when it comes to developing and delivering products.   Your fellow agilists decided to run with this idea, and we put together a day of conference-style sessions, all of which offer hands-on activities.
The term "craft day" comes from the "software craftsmanship" movement.  Try googling "software craftsmanship" for more information on the background for this effort.  The movement is software-centric, but encompasses much more than just programming practices.
We will have a retrospective at the end of the day, but we will also be gathering feedback in the Gale Agile Learning Group (a google discussion group).  You can post questions, ideas or feedback there any time!
The following schedule details the sessions you can choose from.  A description of each of the sessions is below the schedule.
WhenSpace 1 Space 2Space 3
9:00 - 9:30Introduction
Team 3 & 4 Areas
9:00 – 12:20 (3h20m)Clean Code Retreat– Erik Przekop, Karen Wasielewski, Tim Taylor, Jerry Hoerig

Team 3 & 4 Areas
Story Writing & Splitting – Bernard Grunow, Aimme Keener, Mike Gantz

Team 5 & Agile Concept Space
12:20 – 1:00 (40m)Lunch
1:00 – 2:50 (1h50m)Refactoring Randori – Erik Przekop, Jerry Hoerig, Sajid Mohammed, Pete Murasky, Mike Seiler

Team 3 & 4 Areas
Fun with Jquery – Jason Dinkelmann

Team 2 area
Defining / getting to done – Bernard Grunow

Team 5 & Agile Concept Space
2:50 – 3:00Break
3:00 – 4:15 (1h15m)Legacy Rescue – Aaron Chesny, John Nader

Team 3 & 4 Areas
Story Estimation – Aimme Keener

Team 5 & Agile Concept Space
4:15 - endRetrospective

Team 3 & 4 Areas

The Code Retreat session will focus on clean code
  • a series of 20-minute coding sessions
  • a retrospective and suggestions for coding practices to try
  • rinse and repeat
The Story Writing & Splitting section will focus on writing epics and splitting them into stories
  • review stories for some of our current products
  • hands-on converting epics to stories - how we should split them
  • key realizations about best practices
  • examples of good & bad stories
Refactoring Randori will use a Code Dojo format, and work through several refactoring problems
  • split into groups of 20 or less
  • a pair codes on a machine with a projector
  • everyone else shouts out suggestions
  • the pair changes every 5-10 minutes
The Fun With JQuery session will focus on programming with JQuery
  • Jason will give an overview of the what, why & how of JQuery
  • Hands-on programming exercises
Defining / Getting To Done:
  • A retrospective approach to determining what "done" means
  • Various definitions of "done" for a story to move to the next stage
Legacy Rescue:
  • "Travel light", "do no harm" and "avoiding rabbit holes" - how we assess legacy code
  • Hands-on programming exercises
  • Review of the exercise
  • Tips & pointers
Story Estimation
  • Why it matters
  • Exercises involving:
  • prior projects
  • decomposition
  • team estimation
  • relative estimates
  • overall measurements

Saturday, November 6, 2010

At SCNA: Part 4

This is the last post in a multi-part series about the Software Craftsmanship North America conference in Chicago.

Combinator-based design in functional programming: Michael Feathers

I'll be honest - I didn't really pick up a central theme on this one.  It was interesting and I took some ideas from it, but I can't really summarize it well..

My take-aways:
  • We have a settled idea of OO, but not yet one of functional programming - the "best practices" are still evolving.
  • Haskell is a good functional language to learn with - it forces you to be functional.
  • Duplicating objects at runtime is no longer evil.  Duplicating code still is.
  • OO increases encapsulation and understandability.  Functional increases immutability and reduces the number of moving parts.

Panel Discussion: Bob Martin, Michael Feathers, Chad Fowler and Enrique Comba Riepenhausen

This was my favorite session of the conference.  Instead of my interpretation of what the presenter was trying to say, here are my favorite quotes from the session, grouped by theme.

On the image we project as developers 
"We are not a bunch of twinkie-eating guys who don't are about their customers.  We are professionals.  That perception is what has to change."
 - Bob Martin

"Programming shouldn't be a 'lifestyle choice', particularly when you reinforce negative 'nerd' stereotypes."
 - Chad Fowler

On the "craftsmanship" movement
"We don't have to evangelize.  What we're doing is enough.  It does not have to include all developers."
 - Chad Fowler

"...but we should welcome everyone who wants to come."
 - Enrique Comba Riepenhausen

On practicing software development
"Coding is relaxing.  When I wake up in the middle of the night and sit down to code, it's refreshing."
 - Michael Feathers

"...I try to practice four hours per day.  Doing that is refreshing."
 - Enrique Comba Riepenhausen

"I don't do anything I have to do after 5:00 PM.  Only things I want to do."
 - Bob Martin

Wrap-up: Corey Haines

In a lot of ways, this conference is Corey's baby.  He is (as far as I know) the driving force behind the "craftsmanship movement".   (Credit where credit is due: Uncle Bob Martin's cohorts were the organizers of the event, and they did a great job.)

Corey's talk  can be summed up by his own words: "What will allow us to take over the world?"

My take-aways:
  • Happiness is what sets craftsman apart from non-craftsman.  if you're not happy, figure out why not & change that.
  • "Division and negativity are what will keeps us from total world domination."
  • Stay positive about yourself, your work and your craft.  Above all, stop bitching about other developers and our customers.  More civility is needed, and we can all contribute to that!

 Great stuff.  I can't wait for next year.

At SCNA: Part 3

This is the third post in a multi-part series.  The conference covered two days, with many presentations, lightning talks, and conversations about software craftsmanship.

Chad Fowler: McDonalds, Six Sigma and Saxaphone

Fowler, like many other people at SCNA is a "musician/developer" - he chose software development as a career after trying to make his way as a musician.  Exactly how much that influences his craft is hard to say, but it seems to happen often enough to take note of it.

He described what we do as in the middle of a continuum with "Art" on one end and "Commodity" on the other.  A parallel is that art is about form, while commodity is about function.

My take-aways:
  • Treating your work as "art" means that you can talk about it subjectively, which is a cop-out.
  • Internal quality is irrelevant.  Customers don't care about "form", only "function".
  • We can't make software better than McDonald's sells burgers.  Having a system for what you do matters.  He cited the Standish Chaos report to support this idea.
  • Having a training program with objectives for each phase helps for marathons.  A training program is essential for each of our careers.
  • The Six Sigma Design->Do->Measure->Refine->repeat cycle likewise applies to our on careers.
After Chad's talk, I told him I bought his book twice, not realizing "The Passionate Programmer" was the same as "My Job Went To India".  His answer was that they tried to make it very clear that it was essentially the same book in all of the descriptions of it.  It may have been the nicest way anyone has ever called me an idiot.

Keavy McMinn: Fine art and software development
McMinn talked about her transition from fine art to programming.

My take-aways:
  • Keep in mind both the internal (what are my motivations?) and external (what are the fears and motivations of my customers?) questions in any project.
  • Keep a sense of play in your work.  Do some things for yourself.
  • "As programmers, change is relatively cheap.  We have no excuse." (not to change our work product for the better)
  • Group critiques in art can be brutal, but they really move things forward
    • We have processes we can use to do this
    • We're too complimentary to each other - be polite, but dig into what the problems are!
    • Having a culture of blame will kill this - eliminate it.
  • Learn from larger problems, then solve smaller ones.  (Backwards from the usual take on this.)
  • "The future belongs to the few of us still willing to get our hands dirty." (Piece of art that revealed this message when you rubbed it - done in graphite)

Lightning Talks
The one that stood out the most was done by an oddball guy who claimed that he puts the fact he smokes pot on his resume.  (This wasn't part of the talk - I just overheard him loudly hitting on a pretty French software developer earlier in the day.) 
My favorite quote from his talk:  "If I think it's about me, I'm a narcissistic douche."
Another talk was on Genetic Programming.  The concept is:
  • Use a program to write a program.
  • Generations of grammar / evaluator determines which algorithm is the most fit.
  • Needs good tests - it isn't "fit" until it meets the expectations.

Enrique Comba Riepenhausen: The Forsaken Value
I spent quite a bit of the in-between session time (and at the bar the previous night) talking to Enrique.  He's a great storyteller, and a very good photographer.  I stole the photo of Corey for this blog entry from his Flickr site.
My take-aways:
  • "Why become as good as you can?"  To create productive partnerships.
  • Try to find the right customer to create such partnerships.  You're better off saying "no" to potential customers that you know you can't serve well, whether because you aren't able to meet their needs, or simply because you can't do it within their budget.
  • Some customers don't need top value.  They need something quick & dirty that will tell them if they have a market (and help them find investment if they do).  You can still work with them later if you advice them during start-up.
  • "We're not going to work for you.  We will work with you."
    • We're the experts in producing software.  Don't just do anything the customer asks.  We do have the right to refuse if it is foolish and will derail the project.  Just be diplomatic about why and make sure that you understand all of the assumptions.
  • Beauty is how we build our software, but that's purely internal.

Monday, October 25, 2010

Software Craftsmanship North America

Hands-down, the best conference I have been to so far.  It was a two day event that focused on "Software Craftsmanship" - the idea that writing software is somewhere between "art" and "science", and should pay attention to what both of those disciplines have to say.

If you read nothing else, be sure to check out the quotes from the panel discussion in part 2 of day 2.

I'm going to post this in several parts, so this post will serve as a guide to what I write about it.

Day 1 - part 1: Kickoff, and a mixed bag
Bob Martin, Doug Bradbury and Michael Norton.

Day 1 - part 2: Lunch and some great afternoon sessions
Lightning talks, Apprenticeship Panel, Randori with the Stars and Ken Auer

Day 2 - part 1: A slow start, then momentum
Chad Fowler, Keavy McMinn, Lightning talks and Enrique Comba Riepenhausen

Day 2 - part 2: The best part of the conference
Michael Feathers, Panel discussion and Corey Haines wrap-up.

Thanks to Enrique Comba Riepenhausen for the photo.

At SCNA: Part 2

This is the second post in a multi-part series.  The conference covered two days, with many presentations, lightning talks, and conversations about software craftsmanship.

Lightning talks
The one that stood out most for me was by a group of developers from Boston.  They talked about their software craftsmanship meet-up group.  Interesting because it intersects somewhat with my plans for adding a craftsmanship group at my workplace. 
Take-away: (in their opinion) it doesn't matter how big the group is, and smaller is better.

Apprenticeship panel
The concept of apprenticeship is really taking off in software development shops.  This was a group of "apprentices" describing their experience.

My take-aways:
  • Apprenticeship is very effective, and lasts somewhere between 6-12 months.
  • You need an understanding customer, since the apprentice must work side-by-side with masters on a client site.
  Randori with the stars
A laugh fest.  It was done in Code Dojo (by my definition) format using Ruby and Rspec.  I followed along for a while, but they didn't know what they wanted to do.  Uncle Bob rubbed an English guy's head.

My take-aways:
  •  Don't run my Randori's like this.
Lean vs Corporate
Ken Auer talked about his entrepreneur clients, and how they need a real value proposition.  
My take-aways:
  • If/when I return to consulting, my customers really won't like to part with their money.  
  • Giving them what they need is a good thing - don't build a Mercedes for someone who needs a Yugo. 

Wednesday, October 20, 2010

At SCNA: Part 1

This is the first post in a multi-part series.  The conference covered two days, with many presentations, lightning talks, and conversations about software craftsmanship.

This may have been the best conference I have attended.  I found nearly all of the speakers interesting, and the conversations I had between sessions were at least as valuable as the sessions themselves.  It has provided me with a lot of food for thought, that I will comment more on later.

Here is a summary of Day 1, and what I took away from it.  Note that the topics may differ from what the presenters actually put on the screen.

"Uncle" Bob Martin: The Failure of State
Uncle Bob's talk centered on the need for functional programming.  The thrust of it was that most (and perhaps all) OO languages are all about state.  You can modify the state of an object externally through public methods.  You check the state to determine what operations have already been performed, etc.

Functional languages are different.  You can still do "stateful" things in them, but they make it easy to take an input object, transform a copy of it, and return the copy.

So what is so bad about state?  Well, according to Uncle Bob, the breakdown of Moore's law.  Processor speeds have tailed off in the last 5 years.  Instead of doubling every 18 months like they did through the 80's, 90's and early 2000's, they have been pretty much flat.

What has changed is that both memory and processor cores have become dirt cheap.  Instead of running all of our operations in a single thread through one processor, we can get more out of our computing hardware by running them through multiple cores in parallel.  Coupled to this is cheap memory - you can make copies of your information and not have to worry that you'll run out of RAM (within reasonable limits).

What all of this means is that you can get a lot more done if your program doesn't depend on the state of it's objects.  Local variables are no problem, as long as you don't depend on any fields across more than one method.

What this means for testing, I'm not sure of.  I really need to play with some functional languages to get a handle on this paradigm.

This was one of my favorite talks of the conference.  My only complaint is that I would have liked him to keep going for another hour.

Doug Bradbury: What is Craftsmanship (and the Bible)
The central argument of this talk was that software development is a craft.  We're following our creative impulses and making something new every time we code.

The other central argument was that religion informs our craft, and is an important part of being a developer.  I don't think that was Mr. Bradbury's point, but it was heavy on bible quotes and even after 12 years of Catholic school, I thought it wandered away from the central topic of software craftsmanship.

While I laud Bradbury for his courage in presenting an overtly religious view to a largely atheist audience, I don't think it was the right forum for him to make that kind of point.

Michael Norton: Medicine, Programming and Licensing
Norton gave a fairly lively talk on the history of medicine, as well as the challenges and solutions that profession has worked through.  For medicine, it boils down to:
  • Both general and specialized education.  The medical profession requires practitioners to have a broad base of Biology and Physiology, but also have gone through a more general undergraduate program.
  • Hands-on practice in a clinical setting.  Docs must go through a variety of "clinicals", which are more like an apprenticeship than a classroom.  They watch someone who knows what they are doing through years of practice, and slowly are allowed to take a more hands-on approach.
  • Licensing.  Medical practitioners have to pass board exams if they are going to specialize at all.  (And probably if not - I'll have to ask some of my doctor friends if a GP has to pass boards.)
  • Certification.  Practitioners have to have a certain number of hours (I think that a friend of mine said 150 hours for his specialty every 2-3 years) of time in seminars and related activities to keep their license.
Norton never came out and said that we should do the same things in software development, and I saw his response to at least one tweet stating that his aim was to provoke more debate on the subject. 

It's certainly worth thinking about.  I don't want to have to be licensed, but the state of certifications in our profession is positively awful.  What should we do about it?

 To be continued...

Thursday, August 19, 2010

Too much testing, too little clue

A couple of interesting things shook out of today's retrospective.  It turns out that we're well behind on our targets for the current project, and two of the culprits seem to be:

  1. Too much Selenium testing
  2. No card wall

The evils of Selenium

The right way to do Selenium testing is pretty well covered in Patrick Welsh's blog and in other places.  Talk about great timing - Patrick was at the office today to give a lunchtime talk on this very subject.

The team decided to handle the Selenium problem by writing tests for only the things that we absolutely had to test through the UI.  Most of us (we'll have to revisit this) also agreed that we would keep the Se tests as small as we could get away, with while still retaining a reasonable level of test protection.

VersionOne or card wall?

The second item is something I should have brought up before, but I wasn't sure of it until I had been on the project for a month.  We have been using VersionOne as our story management system, and doing all of our updates through it.

It's a nice tool and fun to play with.  Just one problem - I wasn't  aware that we were behind this week (as in others) until after it was too late to do anything about it.  Two reasons came to mind for this:
  • I'm lazy.  I didn't realize that VersionOne had a Story Board view because I didn't take the time to learn the ins and outs of the tool.  The task-oriented view has far too much information on it to give me an overview.
  • We didn't have a card wall that I can just glance up at to see how many stories were still not done and who was working on them.
The team focused on the second bullet - lack of card wall, and I think that is a wise decision. 

It doesn't matter  how good your electronic tools are.   There is no substitute for being able to just look up and see status without any mouse clicks.  It is also very powerful to be able to stand up with another team member or two, and point at cards as you talk.  The simplicity of the setup is what makes it so powerful.

What goes on a card...and on the wall?

I did a quick search for examples of story cards, and this one (scroll down a bit after you click the link) will work.  The best setup I have seen adds some refinements to the cards and their organization on the wall:
  • Write the names of the people working on it on the card, or have mini-cards with team member's names on them that you can post next to the card their working on.
  • Have some sticky notes handy with a bright color.  If the story is blocked for any reason (even if it's something you expect to get resolved the same day), write a few words on the note describing the block and stick it on the card.
  • Organize the cards in columns by status, such as "Dev Ready", "In Progress", "Test Ready", "Test Verified" and "Business Verified".
  • Write a "definition of done" where appropriate for each status and post it at the top of each column.  For instance, "In Progress" would have bullet points like:
    • Unit tested
    • Integration tested if it has external dependencies
    • Selenium tested if it has UI components
    • Reviewed in both IE and Firefox if it has UI components
I doubt that we'll go to such lengths this late in the project, but it's something to consider for the next one.  It isn't a panacea, but it does solve several problems.

Above all, it's simple.

(Image courtesy of J'Roo's Flickr page)

Monday, June 14, 2010

Safari Crashes & Firefox Issues

Looks like Safari is having a lot of problems lately:
Fanbois howl over 'hang a lot' Safari 5 • The Register

I find that Firefox crashes on a regular basis - to the point where I use Chrome almost exclusively. Best bet is that it is a bad plugin, and once Firefox "Lorentz" is out of beta, I may be able to tell which one is dying and taking my browser with it.

Tuesday, March 30, 2010

Transhumanism RSS feeds

I'm interested in the subject of Transhumanism. I suspect that most of my fellow technologists are also interested in the concepts it embodies, even if they're unfamiliar with the term.

"Transhumanism" is a catch-all term for enhancing our abilities as human beings. It is related to Posthumanism,which is more about what human beings will transform themselves into and/or AI that we may create that will surpass our abilities.

There are plenty of blogs and online magazines on the subject, but many of them either have no RSS feed ("and you call yourself a transhumanist!").  Many others only have a feed that delivers a couple of sentences with a link, which is to my mind both hypocritical and self-defeating (it drives almost no traffic, but does irritate potential readers like me). 

I haven't found anyplace that aggregates full RSS feeds, so I made a tentative start.  Here is a Google Reader bundle.  If you see anything you really like in there, I'd suggest  that you subscribe to it in your own reader of choice - I will almost certainly change the list of blogs in here over time, including deleting some that I don't read.

As of this writing I haven't done more than skim these to see if the content looks complete.

Tuesday, March 23, 2010

Content is King

Recently the content team at my employer showed us a presentation about the whys, hows and challenges that they face in organizing content for our products (mainly graduate-level research applications, but some general-use software as well).

Their problems differ somewhat from what most people thing of as "content" in that they don't create the vast majority of what we publish.  Instead, the company purchases or licenses large chunks of information in various forms, and then transforms it into something that you can search and read through a web app. 

What struck me as most relevant were the challenges they face in becoming "agile".  This seems like an area ripe for a better process and cultural changes to accompany it.  It is also far more important than the software development process ("pretty" web apps may engage people up-front, but you have to have something authoritative and useful behind it if you want end-users to want to keep coming back.)

There doesn't seem to be much out there right now on the subject.  About all that I found was this PowerPoint converted to PDF that covers are few of the "whys" and "how's" at a high level.

The author seems to know the subject well, but there's only so much you can get out of a PowerPoint without a person driving it.  (I know nothing about him, but his contact information is at the bottom if you want to ask him yourself  - looks like he does consulting work.)

Sunday, March 21, 2010

Cross-Browser Control of the Back Button

Update:  (3/30/2010) We ended up going with an Ajax solution instead.  Although the code below works, it is really annoying in IE, since you see the page redraw twice.

Here is a very brief how-to on forcing a reload of a page when the back button is clicked.  In my current project, I needed to do this because the header portion of the screen contains some status information that could be confusing to our users if the latest updates don't show up.

We're using JBoss Portal server, which is why I put the code in two  different places.

Using JQuery, the JQuery(document).ready function handles this just fine for IE, but not at all for Firefox.  Here is the IE code, which I placed in the header jsp that appears on all portal pages:

<input type="hidden" id="refreshed" value="no">
<script type="text/javascript">
        var e=document.getElementById("refreshed");

To make it work in Firefox, I added an empty "onunload" event in the 1column theme jsp page:
  <body onunload="">

That's it!  It took quite a while for me to track down examples of both of these, so I thought I'd put everything in one place to help out others.

Sunday, January 31, 2010

Retrospective: The First Coding Dojo

After attending OneDevDay and CodeRetreat, I was gung-ho to get some regular nerdly fun going at my place of business. Accordingly, I pulled together a Wiki site, scheduled a meeting, and "just did it".

It went better than I had hoped it would. I got some great positive feedback from the attendees in our brief retrospective. I got a good vibe from everyone as we were going through the exercise.

I wanted to keep things as informal as possible, but we did follow this minimal schedule:
5:30 - 5:45 Food & Conversation
5:45 - 6:00 Description of Dojo Format. Choose topic & Codebase
6:00 - 7:20 Coding!
7:20 - 7:30 Retrospective

The team came up with the following in our retrospective:

What went well What could have gone better

  • Taking the initiative to do this.

  • Logistics / room / projector.

  • Welcoming atmosphere helped everyone dig in.

  • Small problem domain made it easy to focus on skill.

  • Everyone wrote code - even the managers!

  • More QA people should attend

  • Next time, have someone available to go on a food run.

  • More developers should attend.

  • Promote the event more - many people weren't aware of it.

We also came up with a set of ideas for future topics:

  • Refactoring

  • Selenium

  • Ping-pong pairing

  • Code retreat format

My plan is to tackle the first two over the course of the next few months. I'm not sure about the third, and I want to get in touch with Corey and/or Patrick about using their format. I think they encourage doing retreats, but they don't want the meaning of it to morph into something else, so it may not fit into a 2-hour twice-monthly meeting. If not, I'll just borrow the ideas I think will work & call it something else.

Windows 10 Driver Issue with Falcon / Z-77 Keyboard

Windows 10 has an issue with this mechanical keyboard (which works great, BTW).  It's a Chinese-made keyboard (aren't they all?), bu...