One of the things that the Drupal community has learned in the last few weeks is that our current governance structures aren’t working in several ways. Having spent a lot of time at DrupalCon talking about these issues I figured I share a few initial thoughts for those working on our new processes.
This isn’t the first time I’ve been part of a community that was changing how it organizes itself. In my religious life I am a Quaker, and for a long time I was a member of Philadelphia Yearly Meeting which is the regional organizing body for Quakers in the greater Philadelphia area. And I served for a time on several of their leadership committees. I’ve seen that 300+ year old group pass through at least three different governance structures, and while many of the fundamentals are the same, the details that matter to people also change a lot.
My great aunt put it into perspective during one of the long discussions about change. When my wife asked her for her opinion about a then pending proposal she responded that it didn’t matter much to her as long as it worked for those willing to take leadership roles at the moment.
So as the Drupal community grows through a process to change our leadership structure here are the things I think it is important for all of us to remember.
It will not be perfect. We’re human, we will make mistakes, that’s okay.
It will change again. I don’t know when or why, but whatever we do will serve us for a time, and then we’ll replace it again.
Most of the community won’t care most of the time. Most of the time, most of us don’t notice what Dries, the Drupal Association, Community Working Group, and all the other groups that provide vision and leadership are doing.
I think we can all agree my first point is a given. I mention it mostly because some of us will find fault in anything done going forward. We should remember the people doing this work are doing the best they can and give them support to do it well.
On the plus side, whatever mistakes we make will be temporary because Drupal and its community will outlive whatever we create this time. We’ll outgrow it, get annoyed with the flaws, or just plain decide to change it again. Whatever we build needs to be designed to be changed, improved, and replaced in the future. Think about it like the clauses in the U.S. constitution designed to allow amends to the constitution itself.
Finally, we should remember that community and project governance is insider baseball. Understanding how and why we have the leadership we do is like watching a pitching duel on a rainy day, most baseball fans don’t enjoy those kinds of games. Most of our community wants to use Drupal and they don’t want to have to think about how DrupalCon, Drupal.org, and other other spaces and events are managed. That will not prevent them from complaining next time there are problems, but it is a fact of life those who do care should acknowledge.
Our community is stronger than we have been giving it credit for in the last few weeks. We need to be patient and kind with each other, and we’ll get through this and the divisions that will come in the future.
I’m using this post as a place to store and share “notes” from DrupalCon Baltimore. The part of conference notes I tend to find most useful are links and stray ideas I get talking with people. I don’t tend to take detailed notes anymore since I rarely if ever go back to those, although on rare occasions I do re-watch a session if I found it particularly useful.
Basically this is a dump of links, pictures from various things, and a few stray thoughts. I’ll edit as the week progresses and probably add more thoughts and ideas.
https://www.versioneye.com/ uses the licenses from composer.json to check for both out of date and for compatible licenses. Not terribly useful internally, but user for open projects since you can link a badge to the result. Alternative `composer licenses` which is actually smarter.
Main Take Aways: It seems to be working, and we’re confident enough about the current plan that I think it’s a bit more real than it’s been in the past. And there are ways to track (engage in) what’s being considered for new features.
In short he argues for a category of developer he calls the Expert Beginner. These are people who rose to prominence in their company or community due more to a lack of local competition than raw skill. Developers who think they are great because they are good but have no real benchmarks to compare themselves to and no one calling them out for doing things poorly. These developers not only fail to do good work, but will hold back teams because they will discourage people from trying new paths they don’t understand.
I have one big problem with his argument: he treats Expert Beginning as a finished state. He doesn’t provide a path out of that condition for anyone who has realized they are an expert beginner or that they are working with someone who needs help getting back on track to being an actual expert.
That bothers me because I realized that at times I have been, or certainly been close to being, such expert beginner. When I was first at AFSC, I was the only one doing web development and I lacked feedback from my colleagues about the technical quality of my work. If I said something could be good, it was good because no one could measure it. If I said the code was secure, it was secure because no one knew how to attack it. Fortunately for me, even before we’d developed our slogan about making new mistakes, I had come to realize that I had no idea what I was doing. Attackers certainly could find the security weaknesses even if I couldn’t.
I was talking to a friend about this recently, and I realized part of how we avoided mediocrity at the time was that we were externally focused for our benchmarks. The Iraq Peace Pledge gathered tens of thousands of names and email addresses: a huge number for us. But as we were sweating to build that list, MoveOn ran out and got a million. We weren’t playing on the right order of magnitude to keep pace, and it helped humble us.
I think expert beginnerism is a curable condition. It requires three things: mentoring, training, and pressure to get better.
Being an expert beginner is a mindset, and mindsets can be changed. Deitrich is right that it is a toxic mindset that can cause problems for the whole company but change is possible. If it’s you, a colleague, or a supervisee you have noticed being afflicted with expert beginnerism the good news is it is fixable.
Step 1: Make sure the expert beginner has a mentor.
Everyone needs a mentor, expert beginners need one more than everyone else. A good mentor challenges us to step out of the comfort zone of what we know and see how much there is we don’t understand. Good mentors have our backs when we make mistakes and help us learn to advocate for ourselves.
When I was first in the working world I had an excellent boss who provided me mentoring and guidance because he considered it a fundamental part of his job. AFSC’s former IT Director, Bob Goodman, was an excellent mentor who taught me a great deal (even if I didn’t always admit it at the time). Currently no one person in my life can serve as the central point of reference that he did, but I still need mentoring. So I maintain relationships with several people who have experiences they are willing to share with me. Some of these people own companies, some are developers at other shops, some are at Cyberwoven, and probably none think I look at them as mentors.
I also try to make myself available to my junior colleagues as a mentor whenever I can. I offer advice about programming, careers, and on any other topic they raise. Mentoring is a skill I’m still learning – likely always will be. At times I find it easy, at times it’s hard. But I consider it critical that my workplace has mentors for our junior developers so they continue progress toward excellence.
Step 2: Making sure everyone gets training.
Programming is too big a field for any of us to master all of it. There are things for all of us to learn that someone else already knows. I try to set a standard of constant learning and training. If you are working with, or are, an expert beginner push hard to make sure everyone is getting ongoing training even if they don’t want it. It is critical to the success of any company that everyone be learning all the time. When we stop learning we start moving backward.
Also make sure there are structures for sharing that knowledge. That can take many different shapes: lunch and learns, internal trainings, informal interactions, and many others. Everyone should learn, and everyone should teach.
Step 3: Apply Pressure.
You get to be an expert beginner because you, and the people around you, allow it. To break that mindset you have to push them forward again. Dietrich is right that the toxicity of an expert beginner is the fact that they discourage other people from learning. The other side of that coin is that you can push people into learning by being the model student.
Sometimes this makes other people uncomfortable. It can look arrogant and pushy, but done well (something I’m still mastering) it shows people the advantages of breaking habits and moving forward. This goes best for me is when I find places that other colleagues, particularly expert beginners, can teach me. Expert beginners know things so show them you are willing to learn from what they have to offer as well. They may go out and learn something new just to be able to show off to you again.
Finally, remember this takes time. You have to be patient with people and give them a chance to change mental gears. Expert beginners are used to moving slow but it feels fast to them. By forcing them into the a higher gear you are making them uncomfortable and it will take them time to adjust. Do not let them hold you back while they get up to speed, but don’t give up on them either.
With DrupalCon coming up I want to talk about a question I will be asking vendors giving out t-shirts: do you have women’s shirts? I’ll then request a men’s large (since it’s the size and cut that actually fits my body). Given the reminderthis weekaboutthe problems in the Drupal community around misogynism this seems appropriate topic.
Close your eyes and picture a Drupal developer (go ahead I’ll wait). I can’t say who you saw, but too many sales managers for technology companies just pictured a man or group of men. They want those developers to think well of their company and to wear shirts with their logos. They will buy, and in a few weeks give away, t-shirts for the developers they just pictured. They will forget that our community is strong because we’re diverse, and gender is a critically important form of diversity for us.
Thinking about this through t-shirts isn’t a new or original idea. The first time I ran into a form of this discussion was this 2006 blog post from Kathy Sierra (which I probably read in 2007, so I’ve been thinking about this for 10 years). I was a big fan of her work at the time (and was until she was driven from tech circles shortly after), and the support she got from women on the topic was almost as influential on me as the attacks she received from men for daring to talk about her own body. And it’s not just tech: if you listened to the entire Planet Money t-shirt saga you hear the NPR staff complain about the same problem.
For me usually the conversation starts something like:
“Do you have t-shirts for women?”
“Yes, do you want one for your wife or girlfriend?”
“No, I’ll take a men’s large.”
[confused stare from salesperson followed by them giving me a t-shirt.]
Like many tech conferences, there are usually lots of chances to get free t-shirts from various vendors. For anyone who hasn’t thought about it, that t-shirt is meant to make me and you into walking billboards. It puts their brand in the minds of people in your office, neighborhood, and anyplace else you go. And it works. After I got home from New Orleans last year I wore shirts from several different hosting companies everyday for a week. Since we were talking about new hosting relationships at the time, I got questions about the company on my shirt each day – we do business with two of those companies now. So giving me a free t-shirt is a request for me to advertise on their behalf which could easily pay for itself.
A few years ago I was at DrupalCon with a female colleague who was attending for the first time. The all male dev team members had attended several times before that and she had always liked the interesting variety of t-shirts they came home with, and so was looking forward to finally getting something for herself. Only she didn’t.
Very few vendors had women’s shirts at all and none in her size. Even worse, DrupalCon itself didn’t have a t-shirt for her because the men who had checked in before she arrived had thought their female partners would like the design and had taken all the woman’s shirts.
I should have known this was a risk for her since it’s not like the topic was new, but I didn’t and while I felt bad about it, that doesn’t undo the insult.
Instead of making sure she got to fully participate in our ritual, we allowed her to be left out. Several years had passed since the Kathy Sierra triggered discussion and I wrongly assumed we’d made progress as a community. Oops.
As part of trying to apologize to my friend for my own cluelessness, and in part to try to do something to make our community better, I took up asking vendors with t-shirts if they have women’s sizes. Not because I want one for someone else in particular but because I want other people in general to have the same chances I have. And I am not willing to advertise for companies if they are making our community worse. Anything we do that makes women feel less welcome makes our community worse.
Over time I’ve had interesting conversations with people who have said both yes and no.
The people who say yes are sometimes interesting. Usually they are just confused because they never thought the issue through. Sometimes they cite Kathy Sierra, sometimes they cite a similar experience to my own. Usually we’ll exchange thank yous and I’ll move on.
If they say no, the conversation goes a bit differently. I am always nice, but I don’t let them off the hook. I’ll ask “why not?” With one exception the answers are unfulfilling.
The most common answer is “I don’t know.” While the salesperson is sure no offense was meant (as if they would tell me if one was), I generally offer to wait while they call their boss to figure out why they don’t want women to advertise for them (no one has taken me up on it yet).
The next most popular answer (usually offered right after saying “I don’t know” didn’t get me to go away) “It’s too expensive to add those sizes.” Typically this is from a person who gives out hundreds or thousands of t-shirts a year. This just isn’t true at that scale. Most vendors are still going to order enough shirts to get over the same price breaks they would have with their current order, and every t-shirt they give a woman is one they didn’t give a man. The only way for this to really be true is if they end up giving away more total shirts because more people want them, which is the whole point of the exercise. The time a RackSpace employee gave me this answer I just stared at the woman, in a woman’s cut RackSpace t-shirt, and said “Really”? The next year RackSpace had women’s t-shirts (this probably had nothing to do with me, but it’s nice to think it might have).
I’ll also sometimes get “We didn’t have room to pack them.” I usually get this answer from smaller vendors who may not have as many to give out as a company like RackSpace or Pantheon, and are therefore concerned about bringing shirts and not finding a person to take them. But I’ve gotten it from big companies too who will admit shipping five or six boxes of shirts. Either way, sorry, but no, avoid insulting potential customers by splitting your packing space.
The final answer I hear is “Women don’t want them.” This is the go to excuse from men who don’t want to think about why women don’t participate in anything related to technology. I even got that response from a man planning a Drupal Camp when I pointed out that none of the women on the planning committee had shown any interest in having shirts at all – his daughter being one of them. When I commented that maybe they didn’t like shirts that didn’t fit a wave of nodding followed: we had women’s shirts made.
If you are attending DrupalCon, or any other large event for that matter, please ask everyone giving out t-shirts about women’s sizes. If they say yes, take whatever you want, but if they say no I encourage you to think hard about if you want to advertise for them. And draw them into a discussion on the topic.
If you are bringing t-shirts to DrupalCon, or any other large event I attend, please bring t-shirts for as many different types and sizes of attendees as you can fit. The right ratio is a hard problem to solve, and I know you have limited space. Ask the conference for an estimate of attendee demographics and make your best guess. If you guess wrong that’s okay, apologize, and try to do better next time.
Do I think refusing to take free t-shirts from tech companies will suddenly solve all of our the gender issues? Of course not. But it does force people into conversations they aren’t used to having, and it makes at least some stop and think about ways we create unfriendly atmospheres for women in technology.
I deal with passwords a lot. In any given day I log into five or six servers, another dozen web sites, plus my personal systems and tools. Some are stored in password managers, some are memorized, some are mine, and some are shared. To avoid losing things I need I have several patterns, schemes, and password generation tools I use to try to keep up with it all and make sure I’m using good passwords most of the time.
I don’t have a deep background in cryptography and a definitely don’t consider myself an expert in the related math. But I have spent a lot time time with users and observing behaviors, so I do consider myself reasonably knowledgeable about how people actually behave with their passwords.
A couple years ago this XKCD comic came out, and an admin’s view of it has become one of my measures of their understanding of users and passwords:
If you’re interested in understanding what technically right and wrong with the math and assumptions in that comic you might find some of the references on explain XKCD’s discussion interesting.
I don’t actually think that’s the interesting part. To me the interesting part is the number of system administrators I have talked to who are convinced the comic is wrong, because they are also convinced that anyone who doesn’t use truly random password and avoid password reuse is stupid and therefore their behavior can be ignored. These people have access to your system, and it’s your job to keep those system secure. The problem isn’t your users, the problem is we have made passwords unreasonably hard to do right.
At this point people generally know they are supposed to use good passwords, like we all know we’re supposed to brush after every meal. Sure there are people that do that, but not most of us. We all know that passwords should be long (even if we fight over the exact length to require) and use lots of different kinds of characters (although many password systems require them to be from the latin character set). But it’s too hard to follow all the rules, and security experts are so concerned about being right they don’t provide useful guidance about when the cheat.
Let me grant those who like long-random passwords the following point: if you use different passwords on every system that needs one, and they are all truly random strings, and you memorize them all so you don’t have them recorded someplace they could be stolen, you have the hardest for an attacker to crack. Great for you. But I work with people who are not perfect, have limited memories, and need to be able to have shared access on a regular basis.
Knowing the perfect random password generation pattern is useful in some cases (or so I’ve heard), but rarely are you in a case where you can use the perfect setup. I don’t care about perfect: I’m not perfect, I don’t work in a perfect office, have perfect colleagues, or perfect clients. So here are my good-enough rules for admins and developers.
0) Make it easier to do the right thing than the hard thing. This gets to be rule zero, because everything else is meant to support this idea. You want the path of least resistance to be the one that gets you the results that are secure enough to protect your systems from the attackers they face. Make sure your users have good tools for storing passwords, settings on password fields to encourage good (not perfect) behavior, and a minimum of stupid rules you don’t really understand but someone told you are “best practice”.
1) If you make it hard for people, they will find a way around you and likely weaken security. It might be post-it notes on monitors, cycles of passwords that are 5 long (because you force them to not use the last 4). If you make it hard to pick a password (because you required punctuation but not ‘, \, “, &, or !), you will end up with lots of passwords that are curse words – and your attacker will thank you for shrinking the search space. If they are using touch devices to type them, they will do things like repeat as many characters as you allow to make it easier to type (if you ban any repeats: again the attackers thank you for shrinking the search space). All things you want them to stop doing.
2) Do not have a maximum password length. Any time I hit a system with an upper bound of 12 I want to scream (although jokes about chimps might be a better tactic). Even if you are using a secure hashing system that ignores all characters after some point: who cares? Why limit the attacker’s search space to only strings between 8-12 characters?!? Sure that’s a massive search space, but not nearly as big as it could be.
3) Do have minimum lengths. Minimum lengths forces your users to do two things. First, not use passwords that could be broken in less time than it took you to read this article. Second, it gives you leverage to push them to either good phrases or generators. If you’re smart and don’t have legacy systems to support go with something like 15 or 20 characters.
5) Provide secure means to share passwords. I have more than once been sent a password in chat (running through Google, Slack, or once upon a time AOL’s servers), email, word documents, text file, and a variety of other terrible solutions. This happens not because my colleagues didn’t know it was a bad thing to do but because they didn’t have a good option. We spend so much time locking down passwords, that we don’t create secure channels to hand them around responsibly which defeats the purpose of secured storage.
6) Pay attention to how users will be using individual passwords. Not all passwords are created equal, which is why I encourage you to support throw away passwords: something short, easy to remember, and only used places it doesn’t matter if it were stolen. But even when a password is important there are issues like the ease of entering them: if I have to enter a password 4 times a day it better be easy to type or I better be able to copy and paste it. If I need it once a month it should be impossible to remember and its okay if it takes me 5 minutes to get it right. Most of us can’t type complicated passwords quickly, and if we have to enter it a bunch we want to be fast. This is even more true for people using touch interfaces where shift is an extra keystroke as is changing to a different part of the standard keyboard.
7) Stop telling people they have to use a different password every time. This is an extension of number six. People have too many passwords, and that’s not changing soon. Sure we can encourage them to use LastPass, or a tool like it, but most people aren’t going to (and if they did that could be its own problem since it creates single points of failure). Tell them to use a different password when it’s important, and to use a throw away password or scheme when it’s not.
Not everything needs to be Fort Knox so stop pretending it is. Important things like your bank account(s), your email, Facebook need their own passwords because they can be used to do real damage in the real world. Online communities, games, and other trivial places asking you to sign in do not.
8) Don’t lecture people about bad personal password habits. Honestly, this is probably the hardest one (here I am lecturing you about not lecturing them). Usually the first people to admit they are sloppy about passwords are developers and sysadmins. Sure, they will tell you about the awesome password wallet they use first, and the two factor authentication they created for their blog, but then toss off that all their production servers have the same root password and it’s 8-10 nonrandom characters. Even if you are perfect (if you are still reading this by definition you probably have room for improvement) don’t lecture people who aren’t. It just makes them feel they can’t admit when something has gone wrong, or if they don’t understand something. When you find people doing it wrong, show them how easy it is to do it right, and if it isn’t apologize and fix it.
Every week I try to ask myself: What did I do this week to make myself more valuable? Am I moving forward toward a goal, or further from it?
In technology, communications, or any other job that involves one of those two things you are either moving forward or moving backward: standing still is not an option. You are either learning new skills, trends, tools, and concepts, or you’re falling behind as other people build new tools that drive new ideas and trends.
I read lots of advice that says to plan your career two or three moves in advance. That is good advice, but I don’t think it’s wise to trust your gut that far out. The technology landscape changes too fast and too dynamically to believe you know where everything will be in three or five years. On the one hand I think it’s important to deepen my skills for the path I want to be on, but at the same time I try to broaden my skills into areas other areas that have things to teach me. In the back of my head there is always plan B and C, just in case plan A doesn’t come together they way I hope. In part, because I’ve never been able to stay on plan A very long: life always intervenes.
When I was 23 (and sure I wanted to be teacher) I was advised to read an hour a day in my field, and that it should not just be reading about the kind work I was already doing. At the time I was the new kid in IT of a mid-sized international nonprofit organization doing whatever no one else wanted to do: which is a great way to learn a variety of things. I didn’t really know anything yet about how to have a career – I had a job, and I liked my job, but couldn’t envision a career path.
But I took that advice to heart and tried to find ways to constantly learn about things I don’t know. I read books, listened to podcasts, and taught myself new skills. I learned about communications planning, economics, corporate strategy, algorithms, and a variety of other topics. The ideas I pick up from those sources help me think about technology more creatively, and helped me understand the importance of making sure I build tools that are useful not just cool to me.
The biggest thing I’ve learned from all these different inputs is that I need to live in constant fear of getting behind, outmoded, and sidelined. That fear keeps me motivated to learn more and push myself harder. By the time I retire I cannot imagine I will still be paid to be a full-time Drupal developer, I doubt that’s what I’ll be doing five years from now. Certainly by in 30 years Drupal, and the web as we know it, won’t look anything like they do today and I will be doing my job very differently. This is the blerch that keeps me motivated.
So every week ask yourself: what did I learn this week? Did I move forward or fall behind?
This week I was working with a new colleague on our account team. As with all people knew to working with technical teams and bug tracking, she’s having to learn how to create good trouble tickets for when clients report issues. This is a challenge I’ve seen played out in every place I’ve ever worked: developers want detailed tickets so we can dive in without asking 16 follow up questions, and people creating tickets don’t actually know what we want and assume we know how to find and fix the problem. And so I’d like to try to offer this explanation of what we’re looking for and why.
At the most basic level I need to know at least three things to find and fix a problem on a project (either a web site or some other tool I’m supporting):
Where in the program is the problem? This is usually a link to a sample page that has the problem.
What happened? I need a clear explanation of what went wrong. Is there a picture missing? Is the text format wrong? Is there a big red error message at the top?
What you expected to happen? What is the picture of and where exactly was the picture supposed to appear? What formatting was supposed to appear on the text? Did you do something right before the error message appeared that helps me see that message again?
These things are part of allowing me to reproduce the problem. If I can’t reproduce the problem, I can’t promise you I fixed it. If you can’t reproduce the problem, you can’t check that I’m right.
Developers will often say that if you can’t give me the step to reproduce a problem I can’t fix it. But in my experience sometimes a problem is actually really hard to reproduce, and you need a developer or a professional tester to actually figure out those steps. So it’s okay if you can’t give me perfect directions, but give me what you have.
If you find yourself writing a ticket that doesn’t say more than “Search is broken” or “Blog post didn’t look right” the problem better be massive (think big red error message level). As an account/support team member that may be all you got from the client but someone has to fill the gaps – and developers are terrible people to have fill those gaps.
As a developer there are several reasons that’s true.
First, rarely do developers get the luxury of working on one project for an extended period, and when they do those tools are large and complex. So we probably don’t have every detail in our heads at any moment. If we could store all that information we wouldn’t need task tracking systems, you could just call us and tell us about a problem as we’d call you back a few hours/days/weeks later and say “fixed”.
Second, we’re terrible at finding mistakes in our own work. Like everyone else, we need editors. If I could see the problem you are reporting, I would probably have fixed it, or at least reported it to you so we could open a task to get it fixed later.
Third, we probably don’t spend as much time in the project documentation as you do. So if someone needs to track down the original design to check for a discrepancy between the design and what’s happening a developer is probably going to be much slower at this task than you are (or you will become soon).
Also remember your developer probably will not look at the problem today unless it’s mission critical to the client. So they need to be able to figure out three weeks from now what you were talking about. If it just says: “search is broken” and I run a search in two weeks and everything looks fine, you are going to need to tell me what’s broken about it (maybe a result is missing, maybe it’s formatted wrong, maybe it’s working perfectly but the client doesn’t like the results).
Even with all that context, I know it is intimidating for many new support or account team members to crack the code developers use when talking. We over explain this, using technical terms, and get annoyed too quickly when people don’t understand us. And we often forget that teaching by analogy is helpful.
My new colleague is a baker, and so as I was trying to help her understand what I needed to be helpful on tasks I switched to bread:
If I came to you and said “my bread didn’t work out, please tell me how to fix it” how would you start?
That helped her make the connection. Just saying my bread didn’t work out, doesn’t tell her enough to help me do it right next time. She’s going to have to ask several follow up questions before she can be helpful.
Did it taste wrong or look wrong?
What kind of bread was it?
Did you follow the instructions or do something different?
Are your ingredients fresh?
Did it rise enough?
Did you knead it enough?
Did you set the oven to the right temperature?
On the other hand if I come to her and say:
I tried to make sourdough oatmeal bread over the weekend. I followed the recipe closely, but my bread turned out really dense instead of having the bready texture I expected.
Now she knows there was a problem getting the bread to rise. So we can focus questions on the yeast and other details of getting air into bread. Yes, there are still several things that could have gone wrong, but now we know where to start.
Frequently new support staff are intimidated by all the technical things they don’t know. And too often developers brush aside new staff who don’t give them the information they need and just say things like “Oh I’ll figure it myself” instead of helping their colleagues learn. Part of the solution is to help people understand that the first set of questions aren’t actually technical. Baking isn’t the right analogy for everyone, but it helped in this case. And hopefully next time I’ll do better at getting to a better explanation quickly.
I’ve been struggling with what to write about our new president, the protests he’s triggered, the ban on refugees he’s ordered, the families he’s dividing, the hateful things he has said about many groups, and all the related news. While this is mostly a technology blog and much more articulate people are already saying things worth hearing, these are not events I can allow to pass without comment.
For a variety of reasons I haven’t been able to attend the protests, except I accidentally attended part of a rally in Philadelphia (I thought the rally pictured above was over when I met a friend for dinner right in the middle of it), but it’s been exciting to watch the sustained energy the last few weeks.
Last week my wife paraphrased some of the memes that have been going around: Remember all those times in history class you thought “If I had been alive during ____ I would have ____”? What you are doing now is exactly what you would have done then.
She didn’t mean it as a direct challenge to me, but I haven’t been able to let it go. In part because while I’ve had good answers in the past, I’m not sure I have a good answer at the moment. Besides, the challenge takes on another level of importance when coming from a historian.
While I was in Philly I visited American Friends Service Committee’s Waging Peace exhibit marking their 100th year.
For four generations my family has spent time working and volunteering for AFSC, and there were markers of some of our work in the exhibit. Our widely different roles matched the times and events we were living through. As young adults my great grandparents worked in post-World War I Germany and France, and my great-grandfather later led the construction of a housing co-op. My grandfather and father served as conscience objector with AFSC during World War II and Vietnam. Most of my father’s siblings and their children have volunteered in various ways with some AFSC program or another, often packing donated clothing in the basement of Friends Center in Philadelphia. I spent ten years working in the IT and Communications departments in Philadelphia.
My great grandparents there was little formal training or planning. They both took on roles I can barely imagine doing now, let alone doing them at 22 in countries destroyed by war. Later in his life my great grandfather described part of his work after the armistice:
I was sent with an English boy to Bethlainville, near Verdun, none of the now returned owners knew who we were or why we were there. “To plow our land? Oh no! Americans come to take our land away from us?” My two high school years of French were put to a real test. We are here for Love. We are not the Americans you have met with during the war. We want no pay. But one young girl who had lost both her father and brothers, completely alone, said she would take a chance. “Oh but you’ll be raped said the others” O.K. she will have a gamble. So Jacoby plowed from day break until noon and then I plowed from noon until I couldn’t see at dark. Land all plowed, now we will see what these young men really want. Nothing? Nothing but love. Not the kind she expected. From then on everybody wanted their land plowed. Later on another crew of Americans came with seeds, tools, clothing, etc. So the people of Bethlainville were restored to almost normal living.
Relief work has grown a bit more formal in the last century.
He later returned to AFSC to support the self-help housing program, first in Ohio, and then leading the program in north Philadelphia which renovated a building to create a co-op that still functions today; my cousin, his wife, and daughter are members of the co-op.
My own work at AFSC was much less exciting: I sat in relatively comfortable offices and made sure the technology needed to support the programs worked. I supported mostly communications, and fundraising, and my program involvement tended to be limited to supporting their public facing functions. I was in entirely administrative roles: I was overhead.
Now I easily see what I couldn’t always see then: the value I contributed over 10 years. Too often we denigrate administrative functions at nonprofits as wasteful distractions from their true mission. But the truth is that well done administration is critical to the success of any good organization. They need money to pay the staff, they need web sites to inform people about their work, they advocate for systemic change, they post pictures of their own pets to grab your attention so you will help their work.
Now I’m struggling to find ways to help as the world seems to spin out of control and the US government does things even worse than we did while I was at AFSC (the US went to war twice, admitted torturing people, and openly spied on citizens, so this is a fairly high bar to cross).
While I’ve been pleased, and frankly surprised, at how effective the current protests appear to be, I believe over the next four years the resistance the administration’s fermentation of hatred and distrust will have to be a community by community movement. The lack of trust between communities, and the lack of political power make sustained broad-based movements hard to imagine. There are communities under new attack, and others that have been under assault for decades now starting to find their voices: many are voices of pain and anger. Even as we see mass protests we also see infighting within them and outside resistance from communities with shared interests.
I’ve written in the past about my sister-in-law’s students in Maryland. My wife and I posted similar messages to all our personal and social media networks, and hundreds of postcards and letters have poured in from all corners. The teachers read them to the kids, and sent them home so their families also know there are Americans who welcome them. Some of those letters came from other immigrant children, and her students are now writing back to share their warmth and stickers, with the other children. It doesn’t fix everything, but provides some of what that community needs: love, the kind my great grandparents carried to post-war France and Germany.
There need to be people in the world who are willing to go into the most dangerous places, but we can’t all be those people. We also need people working actively in their community to help spread love, respect, and basic dignity.
I’m still struggling to find ways to have a positive, and effective impact, but here are things I’m trying:
Making hats for a newly arrived Iraqi family I learned about from a woman at church this morning.
Calling and writing to my elected officials to thank them for the things I think they are doing right and asking them to change what I think they are doing wrong.
Writing and speaking openly about my concerns.
Attending rallies when I can, and supporting those who do when I cannot.
Donating to organizations taking the kinds of action we want to see in the world including Planned Parenthood and likely others (we’re still working on who all that will be).
Please share with me (and others) what you’re doing and what else you think can be done.
I believe that to work for positive change we all need to work in and with marginalized communities and help find positive solutions for their problems – even those expressing their frustration through hate toward others.
For Drupal 7, I have a pattern to help simplify creating and managing custom blocks for a site. Since the standard hook_block_info() and really hook_block_view() implementations tend to get messy and junked up with markup in the code. My solution was the use the block delta key from the block info array as a helper function name called from the hook_block_view(), and a theme function in hook_theme() to make sure I could easily create a template for each block. I’m not going into detail about it since was hardly original and I’ve seen several variations from other developers.
When I started to work on Drupal 8 I wanted to develop a similar pattern to help create simple conventions for integration with front end work on a project. While the new plugin system helps avoid the ugliness of old hook_block_view() implementations, how to create a twig file for your custom block isn’t obvious and doesn’t impose a naming convention. Worse, I’ve seen lots of example code with blocks that return render arrays of type markup meaning they have HTML in strings in PHP.
Most projects involve a collection of nearly static blocks that provide basic information like the copyright information, a disclaimer text, a link to the firm that built the site, decorative flourishes, and other similar elements that don’t benefit from being managed as content. After a couple experiments I’ve come up with a solution that works pretty well:
Create a module for simple blocks (although I use the rest of the pattern anytime I’m creating a custom block).
Create the block class for each block.
Create a theme function for each block.
Create a twig file to implement the theme function.
The for a copyright block the class itself is simple. We implement the variables we want rendered by the block, and set the cache to expire at midnight (one of the places a timed cache makes more sense that cache tags):
With the block created, we need to define the custom_blocks_copyright theme function we included in the block using hook_theme() from within the dot module file. Remember any custom variables you used in the block class need to also be defined here (in this case attributes and year):
Finally, create the twig file to provide the actual markup.
In December I gave a talk at the SCDUG meeting on Drupal 8 plugins. This is based on that talk with a few improvements and additions from things I’ve learned since.
Drupal 8 provides many great improvements, but one I’ve been finding to be the most exciting is the easy ability to create my own plugins. They are actually a bit addictive, and it’s easy to start seeing projects as an excuse to create a new plugin manager. At first it can take a little bit of effort to get your head around the process, but I got great details from Unraveling the Drupal 8 Plugin System from Drupalize.me. But the problem with those, and all the examples I could find, was they were either too deep (the drupalize.me article should be considered required reading, but the example is too abstract for most people) or too shallow (the drupal.org Plugin API examples currently lack context about why I would want to do this in practice).
So my goal is to straddle that gap.
What’s a plugin?
Plugins are a design pattern that let you extend a module or service. Drupal 8 has at least four plugin discovery systems:
Annotated ← I’m mostly talking about this one, its used for blocks, views, rules, Queue API, and more.
YAML ← These are used for menus, routes, and services.
Hook ← D7 carry over hook system, still used in many places.
Discovery Decorators ← Wrap around other plugin systems to replace/improve on the classic info alter hooks from previous Drupal versions.
Static ← These are used for test code, and I’m ignoring here.
Basic Commonly Used Plugins
As a Drupal 8 developer you probably use several plugins when building a site, particularly if there is any custom functionality required. When creating controllers you’ll need a route, and likely a menu item, which means you’ll use YAML files to define those aspects. For blocks, the queue api, or Rules you’ll create an annotated plugin. Theme functions are still commonly defined with hook_theme().
Why do I create new plugin?
Between core, and major contrib modules (like Rules and Search API), plugins options abound, but it’s not always obvious why you might want to create one for a more focused project. For large projects that may have a large number of related functions, poorly defined use cases, or use cases that are expected to expand over time Plugins provide three major advantages over other approaches:
Plugins make it easy to easily keep classes small and focused.
Plugins make it easy to extend a service.
Plugins allow one module to easily extend the function of another.
Cyberwoven has a client who needed an internal training portal. They want to provide some basic gamification, particularly badges, and they wanted a more detailed tracking of user behavior than the core statistics module provides. The badges present a function that has many related, but different, use cases and is likely to grow over time. So I created a pluggable service that allows us to easily define a set of conditions for creating a new badge. Each plugin’s annotation lists the events it cares about, and when one of those events is fired the service runs the plugin’s test function. If the badge has been earned the plugin returns the information needed to generate that entity. All the event listening, entity generation, and error checking happens in the service, so each plugin is only focused on the details of the one badge. The event tracker is similar, with each plugin defining a filter for the major system events to determining what details should be recorded, and the service handling the logging of those details and reporting. As the client needs have evolved we’ve been able to add and modify the plugins to meet their needs.
The second place I’ve created a custom plugin system for was an internal project at Cyberwoven (it was actually the project I used to learn how to create custom plugins). Our testing server has always had a service to perform some basic operations on the server, like pulling repos via webhooks and similar tools to help developers. Setting up our development environments for D8 meant it was time for a new test server, and therefore new tools to manage it. From the start I wanted to create a tool that helped both developers and account managers. So I created a D8 site to manage the sites that provides various tools to perform task operations we all need (not only code handling, but also checking if security releases apply to any sites). All the various operations we want exposed through that site are created as plugins to our custom manager. Each task plugin is focused on just that one task. All the other various needed to track the sites, route requests to run a task, and render their responses are all handled in other places. It’s also now making it easy to add features that wrap around the plugins since the plugins all have a consistent interface (like adding new displays and running some tasks through cron).
Introducing Site Manager
The main module defines an entity for each site, a couple displays (like the listing page displayed above), and the annotated plugin base so we can add new features easily. Plugins can be enabled and disabled on a site-by-site basis, and can be run from the plugins dropbutton.
Once we had the basics in place (like getting the git and drush status’s via simple plugins) we started to add more powerful features to turn the tool into a dashboard. We added the module search block you see on the left as a separate module that searches all sites for a specific Drupal module (nice when security updates are released). The search module also provides a plugin for each site that lists the modules for just that site.
The last site in the screen shot has a reference to scanning the HTTPS certificate for a specific site. This is another feature we added recently as this tool increasingly starts to serve as a dashboard. The HTTPS Scanner module again provides both a batch job to scan all sites, and a task plugin that scans just one.
As of this writing, all told there are nine working task plugins across four modules (there are a couple more underway as well). Tasks can also have their results displayed in a block when you look at the details for a site.
Building your own manager
Hopefully by now your convinced that it’s worth having your own plugin manager at least sometimes. So the next question is how to build them.
Elements of a custom plugin
Plugins have several parts, most of which are small and simple:
Annotation Plugin Definition
Plugin Manager Service
The first step is to define the annotation for your plugin. This is a simple class that extends Drupal\Component\Annotation\Plugin to define the variables you want listed in the annotation comments of the plugin. This file goes in custom_module/src/Annotation, and as always the file name and class name match:
Plugin Manager Service
The plugin manager itself is a service, but the vast majority of its function comes from the parent classes. The convention is to place this file in custom_module/src/Plugin (as will the rest of the base definitions we’re about to provide). In this case we call it: TaskPluginManager.php.
The full version of this provides a few more improvements to this class (I overrode the getDefinitions() method to provide some filtering options to support disabling plugins), but those aren’t actually required for it to work well.
In short, this class just provides some general definitions to separate it from all the other annotated plugins.
And since the plugin manager is a service, we add it to our module’s service.yml file:
For this plugin I defined 4 critical public functions, three just provide basic information about a plugin, but fourth (run) will be the interesting one in a minute.
Finally we’re getting to something interesting (or at least something that requires code). The plugin base is an abstract class which all the actual plugins will extend. This goes in custom_module/src/Plugin/TaskPluginBase.php.
The things worth taking notice of here are the fact that I inject several services into the base class, so I have them for each plugin: translation, main sitemanager module configuration, and a wrapper on Symfony’s process service to make running drush and git commands easier. The three informational functions are fully defined here, but the run function stays abstract since it’s the function that actually justifies creating a plugin at all.
In theory I could stop right there. I’ve created a plugin manager and defined all the things someone else needs to be able to use it. But there are two technically optional parts that are useful if you like to work and play well with others: an example implementation and a controller for use or testing purposes.
We went through all the trouble to create the plugin manager, before you stop you should create at least one plugin to prove all the work we just did actually works.
This is a simple task to use drush to run cron for a site. The site entities know the location on the file system for Drupal root, and the simple task service handles the extra settings to control where the commands are run (and time outs and error trapping), so we can safely feed that to command and the location to get the response.
The method returns a render array, that can be used as part of a response.
The controller is truly 100% optional. There are two reasons you might want to create one: to actually run the plugin if that makes sense (it does for the site manager), and to provide for easy testing of a plugin.
For site manager I created the controller because I actually needed it to run the tasks from the dropbutton (its the link used by all the links on those buttons). But when I created the others for clients, I realized they can be very hard to test. They are buried inside several layers of complexity, making a test suite is a challenge to create correctly. And since are of the reason to use a plugin for a project with growing definitions, the test suite is often of limited use for rush additions. But by having a carefully built (and secured) controller and route, you can create an endpoint to use to test the plugin.
Because it’s optional, and well covered elsewhere (or heck just use Drupal console to generate it), I’m going to skip over most of the details of actually building the route, and linking that to the controller, and focus on the single function of running the task itself. To keep this short I’ve removed lots of extraneous details like security and error trapping – creating a tool like this isn’t for beginners so I’m assuming you know how to do those things.
The plugin manager service was injected into the controller (code not shown) so I just have it create an instance of the task requested. The controller calls the run function. If the task is successful the output (a render array) is used for the response, otherwise a simple message is send. This sends an AjaxResponse to work with Drupal’s standard JS handlers, but it could generate a full page just as easily.
Being able to create your own plugins easily is really nice. In Drupal 7 custom plugins where generally considered an advanced developer task. The improvements in the abstraction (and the fact that true plugin support is now in core not pulled from ctools or other critical modules), means that while its still not a beginner task it is something all Drupal developers should be learning.
But remember you don’t always need or want the complexity of your own plugins. I’ve found the idea a bit addictive, and I get unreasonably excited when I find a place plugins are used or that it makes sense for me to create a new plugin type. For custom work you can almost always do the same thing using extra functions on a service, controller, or event listener, so this is a judgement call in the end.